Bug 1289258 - Part 6: Convert store tests. r=bgrins

MozReview-Commit-ID: 8pUV8KFuo4Y

--HG--
extra : rebase_source : 7771dd4138c1be22f4ffff4bc62766268c70e10e
This commit is contained in:
Lin Clark 2016-07-27 16:24:15 -04:00
parent f744805fe8
commit 73b02432ed
14 changed files with 199 additions and 230 deletions

View File

@ -9,6 +9,7 @@
const {
prepareMessage
} = require("devtools/client/webconsole/new-console-output/utils/messages");
const { IdGenerator } = require("devtools/client/webconsole/new-console-output/utils/id-generator");
const {
MESSAGE_ADD,
@ -18,8 +19,14 @@ const {
FILTERS_CLEAR,
} = require("../constants");
function messageAdd(packet) {
let message = prepareMessage(packet);
const defaultIdGenerator = new IdGenerator();
function messageAdd(packet, idGenerator = null) {
if (idGenerator == null) {
idGenerator = defaultIdGenerator;
}
let message = prepareMessage(packet, idGenerator);
return {
type: MESSAGE_ADD,
message

View File

@ -19,11 +19,3 @@ DevToolsModules(
'store.js',
'types.js',
)
MOCHITEST_CHROME_MANIFESTS += [
'test/chrome/chrome.ini'
]
XPCSHELL_TESTS_MANIFESTS += [
'test/store/xpcshell.ini'
]

View File

@ -2,17 +2,20 @@
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
const {
messageAdd,
messagesClear
} = require("devtools/client/webconsole/new-console-output/actions/messages");
const { getRepeatId } = require("devtools/client/webconsole/new-console-output/utils/messages");
const { stubConsoleMessages } = require("devtools/client/webconsole/new-console-output/test/fixtures/stubs");
const { setupActions } = require("devtools/client/webconsole/new-console-output/test/helpers");
const constants = require("devtools/client/webconsole/new-console-output/constants");
const expect = require("expect");
let actions;
describe("Message actions:", () => {
before(()=>{
actions = setupActions();
});
describe("messageAdd", () => {
it("creates expected action given a packet", () => {
const packet = {
@ -38,7 +41,7 @@ describe("Message actions:", () => {
"category": "webdev"
}
};
const action = messageAdd(packet);
const action = actions.messageAdd(packet);
const expected = {
type: constants.MESSAGE_ADD,
message: stubConsoleMessages.get("console.log('foobar', 'test')")
@ -47,7 +50,7 @@ describe("Message actions:", () => {
// Some values on the message are generated by prepareMessage. Manually set
// these on the expected message to match.
expected.message = expected.message.set("repeatId", getRepeatId(expected.message));
expected.message = expected.message.set("id", "0");
expected.message = expected.message.set("id", "1");
expect(action).toEqual(expected);
});
@ -55,7 +58,7 @@ describe("Message actions:", () => {
describe("messagesClear", () => {
it("creates expected action", () => {
const action = messagesClear();
const action = actions.messagesClear();
const expected = {
type: constants.MESSAGES_CLEAR,
};

View File

@ -96,6 +96,19 @@ exports.stubConsoleMessages = new Map([
severity: SEVERITY_LOG,
})
],
[
"console.clear()",
new ConsoleMessage({
allowRepeating: true,
source: MESSAGE_SOURCE.CONSOLE_API,
type: MESSAGE_TYPE.CLEAR,
level: MESSAGE_LEVEL.LOG,
messageText: null,
parameters: ["Console cleared."],
repeat: 1,
repeatId: null,
})
],
[
"console.count('bar')",
new ConsoleMessage({

View File

@ -7,6 +7,43 @@ let ReactDOM = require("devtools/client/shared/vendor/react-dom");
let React = require("devtools/client/shared/vendor/react");
var TestUtils = React.addons.TestUtils;
const actions = require("devtools/client/webconsole/new-console-output/actions/messages");
const { configureStore } = require("devtools/client/webconsole/new-console-output/store");
const { IdGenerator } = require("devtools/client/webconsole/new-console-output/utils/id-generator");
const { stubConsoleMessages } = require("devtools/client/webconsole/new-console-output/test/fixtures/stubs");
const Services = require("devtools/client/webconsole/new-console-output/test/fixtures/Services");
/**
* Prepare actions for use in testing.
*/
function setupActions() {
// Some actions use dependency injection. This helps them avoid using state in
// a hard-to-test way. We need to inject stubbed versions of these dependencies.
const wrappedActions = Object.assign({}, actions);
const idGenerator = new IdGenerator();
wrappedActions.messageAdd = (packet) => {
return actions.messageAdd(packet, idGenerator);
};
return wrappedActions;
}
/**
* Prepare the store for use in testing.
*/
function setupStore(input) {
// Inject the Services stub.
const store = configureStore(Services);
// Add the messages from the input commands to the store.
input.forEach((cmd) => {
store.dispatch(actions.messageAdd(stubConsoleMessages.get(cmd)));
});
return store;
}
function renderComponent(component, props) {
const el = React.createElement(component, props, {});
// By default, renderIntoDocument() won't work for stateless components, but
@ -25,6 +62,8 @@ function shallowRenderComponent(component, props) {
}
module.exports = {
setupActions,
setupStore,
renderComponent,
shallowRenderComponent
};

View File

@ -7,3 +7,6 @@ DIRS += [
'fixtures'
]
MOCHITEST_CHROME_MANIFESTS += [
'chrome/chrome.ini'
]

View File

@ -7,9 +7,7 @@ const expect = require("expect");
const actions = require("devtools/client/webconsole/new-console-output/actions/messages");
const { getAllMessages } = require("devtools/client/webconsole/new-console-output/selectors/messages");
const { configureStore } = require("devtools/client/webconsole/new-console-output/store");
const { stubConsoleMessages } = require("devtools/client/webconsole/new-console-output/test/fixtures/stubs");
const Services = require("devtools/client/webconsole/new-console-output/test/fixtures/Services");
const { setupStore } = require("devtools/client/webconsole/new-console-output/test/helpers");
describe("Search", () => {
it("matches on value grips", () => {
@ -24,16 +22,3 @@ describe("Search", () => {
expect(messages.size).toEqual(1);
});
});
function setupStore(input) {
const store = configureStore(Services);
addMessages(input, store.dispatch);
return store;
}
function addMessages(input, dispatch) {
input.forEach((cmd) => {
dispatch(actions.messageAdd(stubConsoleMessages.get(cmd)));
});
}

View File

@ -1,64 +0,0 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/* exported configureStore */
"use strict";
var { utils: Cu } = Components;
var { require } = Cu.import("resource://devtools/shared/Loader.jsm", {});
const Services = require("Services");
var DevToolsUtils = require("devtools/shared/DevToolsUtils");
var flags = require("devtools/shared/flags");
flags.testing = true;
flags.wantLogging = true;
flags.wantVerbose = false;
const { configureStore } = require("devtools/client/webconsole/new-console-output/store");
const testPackets = new Map();
testPackets.set("console.log", {
"from": "server1.conn4.child1/consoleActor2",
"type": "consoleAPICall",
"message": {
"arguments": [
"foobar",
"test"
],
"columnNumber": 1,
"counter": null,
"filename": "file:///test.html",
"functionName": "",
"groupName": "",
"level": "log",
"lineNumber": 1,
"private": false,
"styles": [],
"timeStamp": 1455064271115,
"timer": null,
"workerType": "none",
"category": "webdev"
}
});
testPackets.set("console.clear", {
"from": "server1.conn1.child1/consoleActor2",
"type": "consoleAPICall",
"message": {
"arguments": [],
"columnNumber": 1,
"counter": null,
"filename": "debugger eval code",
"functionName": "",
"groupName": "",
"level": "clear",
"lineNumber": 1,
"private": false,
"timeStamp": 1462571355142,
"timer": null,
"workerType": "none",
"styles": [],
"category": "webdev"
}
});

View File

@ -0,0 +1,99 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
const { getAllMessages } = require("devtools/client/webconsole/new-console-output/selectors/messages");
const { getRepeatId } = require("devtools/client/webconsole/new-console-output/utils/messages");
const {
setupActions,
setupStore
} = require("devtools/client/webconsole/new-console-output/test/helpers");
const { stubConsoleMessages } = require("devtools/client/webconsole/new-console-output/test/fixtures/stubs");
const expect = require("expect");
describe("Message reducer:", () => {
let actions;
before(() => {
actions = setupActions();
});
it("adds a message to an empty store", () => {
const { dispatch, getState } = setupStore([]);
const message = stubConsoleMessages.get("console.log('foobar', 'test')");
dispatch(actions.messageAdd(message));
const messages = getAllMessages(getState());
// @TODO Remove repeatId once stubs are generated using prepareMessage.
let expected = message.set("repeatId", getRepeatId(message)).set("id", "1");
expect(messages.first()).toEqual(expected);
});
it("increments repeat on a repeating message", () => {
const { dispatch, getState } = setupStore([
"console.log('foobar', 'test')",
"console.log('foobar', 'test')"
]);
const message = stubConsoleMessages.get("console.log('foobar', 'test')");
dispatch(actions.messageAdd(message));
dispatch(actions.messageAdd(message));
const messages = getAllMessages(getState());
expect(messages.size).toBe(1);
expect(messages.first().repeat).toBe(4);
});
it("does not clobber a unique message", () => {
const { dispatch, getState } = setupStore([
"console.log('foobar', 'test')",
"console.log('foobar', 'test')"
]);
const message = stubConsoleMessages.get("console.log('foobar', 'test')");
dispatch(actions.messageAdd(message));
const message2 = stubConsoleMessages.get("console.log(undefined)");
dispatch(actions.messageAdd(message2));
const messages = getAllMessages(getState());
expect(messages.size).toBe(2);
expect(messages.first().repeat).toBe(3);
expect(messages.last().repeat).toBe(1);
});
it("clears the store in response to console.clear()", () => {
const { dispatch, getState } = setupStore([
"console.log('foobar', 'test')",
"console.log(undefined)"
]);
dispatch(actions.messageAdd(stubConsoleMessages.get("console.clear()")));
const messages = getAllMessages(getState());
expect(messages.size).toBe(1);
expect(messages.first().parameters[0]).toBe("Console cleared.");
});
it("limits the number of messages displayed", () => {
const { dispatch, getState } = setupStore([]);
const logLimit = 1000;
const baseMessage = stubConsoleMessages.get("console.log(undefined)");
for (let i = 1; i <= logLimit + 1; i++) {
const msg = baseMessage.set("parameters", [`message num ${i}`]);
dispatch(actions.messageAdd(msg));
}
const messages = getAllMessages(getState());
expect(messages.count()).toBe(logLimit);
expect(messages.first().parameters[0]).toBe(`message num 2`);
expect(messages.last().parameters[0]).toBe(`message num ${logLimit + 1}`);
});
});

View File

@ -1,118 +0,0 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
const actions = require("devtools/client/webconsole/new-console-output/actions/messages");
const packet = testPackets.get("console.log");
const clearPacket = testPackets.get("console.clear");
const {
getRepeatId,
prepareMessage
} = require("devtools/client/webconsole/new-console-output/utils/messages");
const { getAllMessages } = require("devtools/client/webconsole/new-console-output/selectors/messages");
function run_test() {
run_next_test();
}
/**
* Test adding a message to the store.
*/
add_task(function* () {
const { getState, dispatch } = configureStore();
dispatch(actions.messageAdd(packet));
const expectedMessage = prepareMessage(packet);
const messages = getAllMessages(getState());
equal(messages.size, 1, "We added exactly one message.")
const message = messages.first();
notEqual(message.id, expectedMessage.id, "ID should be unique.");
// Remove ID for deepEqual comparison.
deepEqual(message.remove('id'), expectedMessage.remove('id'),
"MESSAGE_ADD action adds a message");
});
/**
* Test repeating messages in the store.
*/
add_task(function* () {
const { getState, dispatch } = configureStore();
dispatch(actions.messageAdd(packet));
dispatch(actions.messageAdd(packet));
dispatch(actions.messageAdd(packet));
const messages = getAllMessages(getState());
equal(messages.size, 1,
"Repeated messages don't increase message list size");
equal(messages.first().repeat, 3, "Repeated message is updated as expected");
let newPacket = Object.assign({}, packet);
newPacket.message.arguments = ["funny"];
dispatch(actions.messageAdd(newPacket));
equal(getAllMessages(getState()).size, 2,
"Non-repeated messages aren't clobbered");
});
/**
* Test adding a console.clear message to the store.
*/
add_task(function*() {
const { getState, dispatch } = configureStore();
dispatch(actions.messageAdd(packet));
let messages = getAllMessages(getState());
equal(messages.size, 1,
"MESSAGE_ADD action adds a message");
dispatch(actions.messageAdd(clearPacket));
messages = getAllMessages(getState());
deepEqual(messages.first().remove('id'), prepareMessage(clearPacket).remove('id'),
"console.clear clears existing messages and add a new one");
});
/**
* Test message limit on the store.
*/
add_task(function* () {
const { getState, dispatch } = configureStore();
const logLimit = 1000;
const messageNumber = logLimit + 1;
let newPacket = Object.assign({}, packet);
for (let i = 1; i <= messageNumber; i++) {
newPacket.message.arguments = [i];
dispatch(actions.messageAdd(newPacket));
}
let messages = getAllMessages(getState());
equal(messages.count(), logLimit, "Messages are pruned up to the log limit");
deepEqual(messages.last().parameters, [messageNumber],
"The last message is the expected one");
});
/**
* Test message limit on the store with user set prefs.
*/
add_task(function* () {
const userSetLimit = 10;
Services.prefs.setIntPref("devtools.hud.loglimit", userSetLimit);
const { getState, dispatch } = configureStore();
let newPacket = Object.assign({}, packet);
for (let i = 1; i <= userSetLimit + 1; i++) {
newPacket.message.arguments = [i];
dispatch(actions.messageAdd(newPacket));
}
let messages = getAllMessages(getState());
equal(messages.count(), userSetLimit,
"Messages are pruned up to the user set log limit");
});

View File

@ -1,7 +0,0 @@
[DEFAULT]
tags = devtools devtools-webconsole
head = head.js
tail =
firefox-appdir = browser
[test_messages.js]

View File

@ -0,0 +1,22 @@
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
exports.IdGenerator = class IdGenerator {
constructor() {
this.messageId = 1;
}
getNextId() {
// Return the next message id, as a string.
return "" + this.messageId++;
}
getCurrentId() {
return this.messageId;
}
};

View File

@ -28,13 +28,7 @@ const {
} = require("../constants");
const { ConsoleMessage } = require("../types");
let messageId = 0;
function getNextMessageId() {
// Return the next message id, as a string.
return "" + messageId++;
}
function prepareMessage(packet) {
function prepareMessage(packet, idGenerator) {
// This packet is already in the expected packet structure. Simply return.
if (!packet.source) {
packet = transformPacket(packet);
@ -43,7 +37,7 @@ function prepareMessage(packet) {
if (packet.allowRepeating) {
packet = packet.set("repeatId", getRepeatId(packet));
}
return packet.set("id", getNextMessageId());
return packet.set("id", idGenerator.getNextId());
}
/**

View File

@ -4,6 +4,7 @@
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
DevToolsModules(
'id-generator.js',
'messages.js',
'variables-view.js',
)