Bug 1380709 - Add mochitests and mocha tests to ensure entries are loaded as expected. r=bgrins

This adds several tests to make sure we can expand Sets and Maps entries, and that we manage
those properties in the store as expected.
We also add a stub for a Set object and take this as an opportunity to fix the stub name.

MozReview-Commit-ID: ChhIHKMPINF

--HG--
extra : rebase_source : 5aba016c0a231032dc411aa4bd01d059e07ebd79
This commit is contained in:
Nicolas Chevobbe 2017-08-01 16:27:00 +02:00
Родитель a9d80db97b
Коммит f065ad2b7c
7 изменённых файлов: 392 добавлений и 11 удалений

Просмотреть файл

@ -27,8 +27,8 @@ const consoleApiCommands = [
let consoleApi = new Map(consoleApiCommands.map(
cmd => [cmd, {keys: [cmd], code: cmd}]));
consoleApi.set("console.map('mymap')", {
keys: ["console.map('mymap')"],
consoleApi.set("console.log('mymap')", {
keys: ["console.log('mymap')"],
code: `
var map = new Map();
map.set("key1", "value1");
@ -36,6 +36,12 @@ map.set("key2", "value2");
console.log('mymap', map);
`});
consoleApi.set("console.log('myset')", {
keys: ["console.log('myset')"],
code: `
console.log('myset', new Set(["a", "b"]));
`});
consoleApi.set("console.trace()", {
keys: ["console.trace()"],
code: `

Просмотреть файл

@ -558,11 +558,11 @@ stubPreparedMessages.set("console.log('myobject', {red: 'redValue', green: 'gree
"indent": 0
}));
stubPreparedMessages.set("console.map('mymap')", new ConsoleMessage({
stubPreparedMessages.set("console.log('mymap')", new ConsoleMessage({
"id": "1",
"allowRepeating": true,
"source": "console-api",
"timeStamp": 1493125410207,
"timeStamp": 1501506737042,
"type": "log",
"helperType": null,
"level": "log",
@ -571,7 +571,7 @@ stubPreparedMessages.set("console.map('mymap')", new ConsoleMessage({
"mymap",
{
"type": "object",
"actor": "server1.conn0.child1/obj36",
"actor": "server1.conn0.child1/obj37",
"class": "Map",
"extensible": true,
"frozen": false,
@ -593,7 +593,7 @@ stubPreparedMessages.set("console.map('mymap')", new ConsoleMessage({
}
}
],
"repeatId": "{\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-console-api.html\",\"line\":5,\"column\":1},\"groupId\":null,\"indent\":0,\"level\":\"log\",\"messageText\":null,\"parameters\":[\"mymap\",{\"type\":\"object\",\"actor\":\"server1.conn0.child1/obj36\",\"class\":\"Map\",\"extensible\":true,\"frozen\":false,\"sealed\":false,\"ownPropertyLength\":0,\"preview\":{\"kind\":\"MapLike\",\"size\":2,\"entries\":[[\"key1\",\"value1\"],[\"key2\",\"value2\"]]}}],\"source\":\"console-api\",\"type\":\"log\",\"userProvidedStyles\":[]}",
"repeatId": "{\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-console-api.html\",\"line\":5,\"column\":1},\"groupId\":null,\"indent\":0,\"level\":\"log\",\"messageText\":null,\"parameters\":[\"mymap\",{\"type\":\"object\",\"actor\":\"server1.conn0.child1/obj37\",\"class\":\"Map\",\"extensible\":true,\"frozen\":false,\"sealed\":false,\"ownPropertyLength\":0,\"preview\":{\"kind\":\"MapLike\",\"size\":2,\"entries\":[[\"key1\",\"value1\"],[\"key2\",\"value2\"]]}}],\"source\":\"console-api\",\"type\":\"log\",\"userProvidedStyles\":[]}",
"stacktrace": null,
"frame": {
"source": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-console-api.html",
@ -607,6 +607,49 @@ stubPreparedMessages.set("console.map('mymap')", new ConsoleMessage({
"indent": 0
}));
stubPreparedMessages.set("console.log('myset')", new ConsoleMessage({
"id": "1",
"allowRepeating": true,
"source": "console-api",
"timeStamp": 1501506737051,
"type": "log",
"helperType": null,
"level": "log",
"messageText": null,
"parameters": [
"myset",
{
"type": "object",
"actor": "server1.conn0.child1/obj38",
"class": "Set",
"extensible": true,
"frozen": false,
"sealed": false,
"ownPropertyLength": 0,
"preview": {
"kind": "ArrayLike",
"length": 2,
"items": [
"a",
"b"
]
}
}
],
"repeatId": "{\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-console-api.html\",\"line\":2,\"column\":1},\"groupId\":null,\"indent\":0,\"level\":\"log\",\"messageText\":null,\"parameters\":[\"myset\",{\"type\":\"object\",\"actor\":\"server1.conn0.child1/obj38\",\"class\":\"Set\",\"extensible\":true,\"frozen\":false,\"sealed\":false,\"ownPropertyLength\":0,\"preview\":{\"kind\":\"ArrayLike\",\"length\":2,\"items\":[\"a\",\"b\"]}}],\"source\":\"console-api\",\"type\":\"log\",\"userProvidedStyles\":[]}",
"stacktrace": null,
"frame": {
"source": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-console-api.html",
"line": 2,
"column": 1
},
"groupId": null,
"exceptionDocURL": null,
"userProvidedStyles": [],
"notes": null,
"indent": 0
}));
stubPreparedMessages.set("console.trace()", new ConsoleMessage({
"id": "1",
"allowRepeating": true,
@ -1689,7 +1732,7 @@ stubPackets.set("console.log('myobject', {red: 'redValue', green: 'greenValue',
}
});
stubPackets.set("console.map('mymap')", {
stubPackets.set("console.log('mymap')", {
"from": "server1.conn0.child1/consoleActor2",
"type": "consoleAPICall",
"message": {
@ -1698,7 +1741,7 @@ stubPackets.set("console.map('mymap')", {
"mymap",
{
"type": "object",
"actor": "server1.conn0.child1/obj36",
"actor": "server1.conn0.child1/obj37",
"class": "Map",
"extensible": true,
"frozen": false,
@ -1729,7 +1772,48 @@ stubPackets.set("console.map('mymap')", {
"lineNumber": 5,
"private": false,
"styles": [],
"timeStamp": 1493125410207,
"timeStamp": 1501506737042,
"timer": null,
"workerType": "none",
"category": "webdev"
}
});
stubPackets.set("console.log('myset')", {
"from": "server1.conn0.child1/consoleActor2",
"type": "consoleAPICall",
"message": {
"addonId": "",
"arguments": [
"myset",
{
"type": "object",
"actor": "server1.conn0.child1/obj38",
"class": "Set",
"extensible": true,
"frozen": false,
"sealed": false,
"ownPropertyLength": 0,
"preview": {
"kind": "ArrayLike",
"length": 2,
"items": [
"a",
"b"
]
}
}
],
"columnNumber": 1,
"counter": null,
"filename": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-console-api.html",
"functionName": "triggerPacket",
"groupName": "",
"level": "log",
"lineNumber": 2,
"private": false,
"styles": [],
"timeStamp": 1501506737051,
"timer": null,
"workerType": "none",
"category": "webdev"

Просмотреть файл

@ -44,6 +44,7 @@ skip-if = (os == 'linux' && bits == 32 && debug) # bug 1328915, disable linux32
[browser_webconsole_network_messages_click.js]
[browser_webconsole_nodes_highlight.js]
[browser_webconsole_nodes_select.js]
[browser_webconsole_object_inspector_entries.js]
[browser_webconsole_object_inspector.js]
[browser_webconsole_observer_notifications.js]
[browser_webconsole_shows_reqs_in_netmonitor.js]

Просмотреть файл

@ -0,0 +1,185 @@
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
// Check expanding/collapsing maps and sets in the console.
const TEST_URI = "data:text/html;charset=utf8,<h1>Object Inspector on Maps & Sets</h1>";
add_task(async function () {
const hud = await openNewTabAndConsole(TEST_URI);
const store = hud.ui.newConsoleOutput.getStore();
// Adding logging each time the store is modified in order to check
// the store state in case of failure.
store.subscribe(() => {
const messages = store.getState().messages.messagesById
.reduce(function (res, {id, type, parameters, messageText}) {
res.push({id, type, parameters, messageText});
return res;
}, []);
info("messages : " + JSON.stringify(messages));
});
await ContentTask.spawn(gBrowser.selectedBrowser, null, function () {
content.wrappedJSObject.console.log(
"oi-entries-test",
new Map(
Array.from({length: 20}).map((el, i) => [Symbol(i), i])
),
new Map(
Array.from({length: 331}).map((el, i) => [Symbol(i), i])
),
new Set(Array.from({length: 20}).map((el, i) => i)),
new Set(Array.from({length: 222}).map((el, i) => i)),
);
});
let node = await waitFor(() => findMessage(hud, "oi-entries-test"));
const objectInspectors = [...node.querySelectorAll(".tree")];
is(objectInspectors.length, 4, "There is the expected number of object inspectors");
const [
mapOi,
largeMapOi,
setOi,
largeSetOi,
] = objectInspectors;
await testMap(mapOi);
await testLargeMap(largeMapOi);
await testSet(setOi);
await testLargeSet(largeSetOi);
});
async function testMap(oi) {
info("Expanding the Map");
let onMapOiMutation = waitForNodeMutation(oi, {
childList: true
});
oi.querySelector(".arrow").click();
await onMapOiMutation;
ok(oi.querySelector(".arrow").classList.contains("expanded"),
"The arrow of the node has the expected class after clicking on it");
let oiNodes = oi.querySelectorAll(".node");
// There are 4 nodes: the root, size, entries and the proto.
is(oiNodes.length, 4, "There is the expected number of nodes in the tree");
info("Expanding the <entries> leaf of the map");
let entriesNode = oiNodes[2];
is(entriesNode.textContent, "<entries>", "There is the expected <entries> node");
onMapOiMutation = waitForNodeMutation(oi, {
childList: true
});
entriesNode.querySelector(".arrow").click();
await onMapOiMutation;
oiNodes = oi.querySelectorAll(".node");
// There are now 24 nodes, the 4 original ones, and the 20 entries.
is(oiNodes.length, 24, "There is the expected number of nodes in the tree");
}
async function testLargeMap(oi) {
info("Expanding the large map");
let onMapOiMutation = waitForNodeMutation(oi, {
childList: true
});
oi.querySelector(".arrow").click();
await onMapOiMutation;
ok(oi.querySelector(".arrow").classList.contains("expanded"),
"The arrow of the node has the expected class after clicking on it");
let oiNodes = oi.querySelectorAll(".node");
// There are 4 nodes: the root, size, entries and the proto.
is(oiNodes.length, 4, "There is the expected number of nodes in the tree");
info("Expanding the <entries> leaf of the map");
let entriesNode = oiNodes[2];
is(entriesNode.textContent, "<entries>", "There is the expected <entries> node");
onMapOiMutation = waitForNodeMutation(oi, {
childList: true
});
entriesNode.querySelector(".arrow").click();
await onMapOiMutation;
oiNodes = oi.querySelectorAll(".node");
// There are now 8 nodes, the 4 original ones, and the 4 buckets.
is(oiNodes.length, 8, "There is the expected number of nodes in the tree");
is(oiNodes[3].textContent, "[0..99]");
is(oiNodes[4].textContent, "[100..199]");
is(oiNodes[5].textContent, "[200..299]");
is(oiNodes[6].textContent, "[300..331]");
}
async function testSet(oi) {
info("Expanding the Set");
let onSetOiMutation = waitForNodeMutation(oi, {
childList: true
});
oi.querySelector(".arrow").click();
await onSetOiMutation;
ok(oi.querySelector(".arrow").classList.contains("expanded"),
"The arrow of the node has the expected class after clicking on it");
let oiNodes = oi.querySelectorAll(".node");
// There are 4 nodes: the root, size, entries and the proto.
is(oiNodes.length, 4, "There is the expected number of nodes in the tree");
info("Expanding the <entries> leaf of the Set");
let entriesNode = oiNodes[2];
is(entriesNode.textContent, "<entries>", "There is the expected <entries> node");
onSetOiMutation = waitForNodeMutation(oi, {
childList: true
});
entriesNode.querySelector(".arrow").click();
await onSetOiMutation;
oiNodes = oi.querySelectorAll(".node");
// There are now 24 nodes, the 4 original ones, and the 20 entries.
is(oiNodes.length, 24, "There is the expected number of nodes in the tree");
}
async function testLargeSet(oi) {
info("Expanding the large Set");
let onSetOiMutation = waitForNodeMutation(oi, {
childList: true
});
oi.querySelector(".arrow").click();
await onSetOiMutation;
ok(oi.querySelector(".arrow").classList.contains("expanded"),
"The arrow of the node has the expected class after clicking on it");
let oiNodes = oi.querySelectorAll(".node");
// There are 4 nodes: the root, size, entries and the proto.
is(oiNodes.length, 4, "There is the expected number of nodes in the tree");
info("Expanding the <entries> leaf of the Set");
let entriesNode = oiNodes[2];
is(entriesNode.textContent, "<entries>", "There is the expected <entries> node");
onSetOiMutation = waitForNodeMutation(oi, {
childList: true
});
entriesNode.querySelector(".arrow").click();
await onSetOiMutation;
oiNodes = oi.querySelectorAll(".node");
// There are now 7 nodes, the 4 original ones, and the 3 buckets.
is(oiNodes.length, 7, "There is the expected number of nodes in the tree");
is(oiNodes[3].textContent, "[0..99]");
is(oiNodes[4].textContent, "[100..199]");
is(oiNodes[5].textContent, "[200..222]");
}

Просмотреть файл

@ -12,6 +12,7 @@ const {
getCurrentGroup,
getVisibleMessages,
getAllMessagesObjectPropertiesById,
getAllMessagesObjectEntriesById,
} = require("devtools/client/webconsole/new-console-output/selectors/messages");
const {
clonePacket,
@ -869,4 +870,100 @@ describe("Message reducer:", () => {
expect(getAllMessagesObjectPropertiesById(getState()).size).toBe(0);
});
});
describe("messagesObjectEntriesById", () => {
it(`adds messagesObjectEntriesById data in response to
MESSAGE_OBJECT_ENTRIES_RECEIVE action`, () => {
const { dispatch, getState } = setupStore([]);
// Add 2 log messages with loaded entries.
dispatch(actions.messageAdd(stubPackets.get("console.log('myset')")));
dispatch(actions.messageAdd(stubPackets.get("console.log('mymap')")));
let messages = getAllMessagesById(getState());
const setEntries = Symbol();
const mapEntries = Symbol();
const mapEntries2 = Symbol();
const [id1, id2] = [...messages.keys()];
dispatch(actions.messageObjectEntriesReceive(id1, "fakeActor1", setEntries));
dispatch(actions.messageObjectEntriesReceive(id2, "fakeActor2", mapEntries));
dispatch(actions.messageObjectEntriesReceive(id2, "fakeActor3", mapEntries2));
let loadedEntries = getAllMessagesObjectEntriesById(getState());
expect(loadedEntries.size).toBe(2);
expect(loadedEntries.get(id1)).toEqual({
fakeActor1: setEntries,
});
expect(loadedEntries.get(id2)).toEqual({
fakeActor2: mapEntries,
fakeActor3: mapEntries2,
});
});
it("resets messagesObjectEntriesById in response to MESSAGES_CLEAR action", () => {
const { dispatch, getState } = setupStore([
"console.log('myset')"
]);
let messages = getAllMessagesById(getState());
const entries = Symbol("entries");
const message = messages.first();
const {actor} = message.parameters[1];
dispatch(actions.messageObjectEntriesReceive(message.id, actor, entries));
let loadedEntries = getAllMessagesObjectEntriesById(getState());
expect(loadedEntries.size).toBe(1);
expect(loadedEntries.get(message.id)).toEqual({
[actor]: entries
});
dispatch(actions.messagesClear());
expect(getAllMessagesObjectEntriesById(getState()).size).toBe(0);
});
it("cleans messagesObjectPropertiesById when messages are pruned", () => {
const { dispatch, getState } = setupStore([], null, {
logLimit: 2
});
// Add 2 log messages with loaded entries.
dispatch(actions.messageAdd(stubPackets.get("console.log('myset')")));
dispatch(actions.messageAdd(stubPackets.get("console.log('mymap')")));
let messages = getAllMessagesById(getState());
const setEntries = Symbol();
const mapEntries = Symbol();
const mapEntries2 = Symbol();
const [id1, id2] = [...messages.keys()];
dispatch(actions.messageObjectEntriesReceive(id1, "fakeActor1", setEntries));
dispatch(actions.messageObjectEntriesReceive(id2, "fakeActor2", mapEntries));
dispatch(actions.messageObjectEntriesReceive(id2, "fakeActor3", mapEntries2));
let loadedEntries = getAllMessagesObjectEntriesById(getState());
expect(loadedEntries.size).toBe(2);
// This addition will remove the first message.
dispatch(actions.messageAdd(stubPackets.get("console.log(undefined)")));
loadedEntries = getAllMessagesObjectEntriesById(getState());
expect(loadedEntries.size).toBe(1);
expect(loadedEntries.get(id2)).toEqual({
fakeActor2: mapEntries,
fakeActor3: mapEntries2,
});
// This addition will remove the second table message.
dispatch(actions.messageAdd(stubPackets.get("console.log('foobar', 'test')")));
expect(getAllMessagesObjectEntriesById(getState()).size).toBe(0);
});
});
});

Просмотреть файл

@ -85,11 +85,17 @@ describe("Release actor enhancer:", () => {
const firstMessageActor = firstMessage.parameters[1].actor;
const arrayProperties = Symbol();
const arraySubProperties = Symbol();
const mapEntries1 = Symbol();
const mapEntries2 = Symbol();
const [id] = [...messages.keys()];
dispatch(actions.messageObjectPropertiesReceive(
id, "fakeActor1", arrayProperties));
dispatch(actions.messageObjectPropertiesReceive(
id, "fakeActor2", arraySubProperties));
dispatch(actions.messageObjectEntriesReceive(
id, "mapActor1", mapEntries1));
dispatch(actions.messageObjectEntriesReceive(
id, "mapActor2", mapEntries2));
const packet = clonePacket(stubPackets.get(
"console.assert(false, {message: 'foobar'})"));
@ -98,10 +104,12 @@ describe("Release actor enhancer:", () => {
dispatch(actions.messagesClear());
expect(releasedActors.length).toBe(4);
expect(releasedActors.length).toBe(6);
expect(releasedActors).toInclude(firstMessageActor);
expect(releasedActors).toInclude("fakeActor1");
expect(releasedActors).toInclude("fakeActor2");
expect(releasedActors).toInclude("mapActor1");
expect(releasedActors).toInclude("mapActor2");
expect(releasedActors).toInclude(secondMessageActor);
});
});

Просмотреть файл

@ -88,7 +88,7 @@ function prepareBaseStore() {
"console.count('bar')",
"console.log('myarray', ['red', 'green', 'blue'])",
"console.log('myregex', /a.b.c/)",
"console.map('mymap')",
"console.log('mymap')",
"console.log('myobject', {red: 'redValue', green: 'greenValue', blue: 'blueValue'});",
"GET request",
]);