Bug 1644428 - Added tests to verify Compatiblity Panel reacting to DOM mutations r=daisuke,mtigley

The tests cover the following test cases:
* Dynamic addition of inline style
* Dynamic change of classlist - addition and removal of class
* Inline style change via the rule-view
* Dynamic addition of nodes with issues
* Dynamic addition of nodes whose children have issues
* Dynamic removal of node with issue
* Dynamic removal of node whose children have issue

Differential Revision: https://phabricator.services.mozilla.com/D81443
This commit is contained in:
Kriyszig 2020-07-03 17:22:59 +00:00
Родитель 6a6c70267a
Коммит 30282112dd
6 изменённых файлов: 552 добавлений и 4 удалений

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

@ -10,6 +10,10 @@ support-files =
!/devtools/client/shared/test/test-actor.js
[browser_compatibility_css-property_issue.js]
[browser_compatibility_dynamic_js-attribute-change.js]
[browser_compatibility_dynamic_js-dom-change.js]
[browser_compatibility_dynamic_markup-dom-change.js]
[browser_compatibility_dynamic_ruleview-attribute-change.js]
[browser_compatibility_event_document-reload.js]
[browser_compatibility_event_panel-select.js]
[browser_compatibility_event_rule-change.js]

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

@ -0,0 +1,128 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
const MDNCompatibility = require("devtools/shared/compatibility/MDNCompatibility");
const {
COMPATIBILITY_UPDATE_NODE_COMPLETE,
} = require("devtools/client/inspector/compatibility/actions/index");
// Test the behavior rules are dynamically added
const ISSUE_CURSOR = {
type: MDNCompatibility.ISSUE_TYPE.CSS_PROPERTY,
property: "cursor",
url: "https://developer.mozilla.org/docs/Web/CSS/cursor",
deprecated: false,
experimental: false,
};
const ISSUE_HYPHENS = {
type: MDNCompatibility.ISSUE_TYPE.CSS_PROPERTY_ALIASES,
aliases: ["hyphens"],
property: "hyphens",
url: "https://developer.mozilla.org/docs/Web/CSS/hyphens",
deprecated: false,
experimental: false,
};
const TEST_URI = `
<style>
.issue {
cursor: grab;
}
</style>
<body>
<div class="test"></div>
</body>
`;
add_task(async function() {
info("Testing dynamic style change using JavaScript");
const tab = await addTab(
"data:text/html;charset=utf-8," + encodeURIComponent(TEST_URI)
);
const {
allElementsPane,
inspector,
selectedElementPane,
} = await openCompatibilityView();
info("Testing inline style change due to JavaScript execution");
const onPanelUpdate = waitForUpdateSelectedNodeAction(inspector.store);
info("Select the div to undergo mutation");
await selectNode(".test", inspector);
await onPanelUpdate;
info("Check initial issues");
await assertIssueList(selectedElementPane, []);
await assertIssueList(allElementsPane, []);
info("Adding inline style with compatibility issue");
await testAttributeMutation(
tab,
inspector,
selectedElementPane,
allElementsPane,
[ISSUE_HYPHENS],
[ISSUE_HYPHENS],
async function() {
content.document.querySelector(".test").style.hyphens = "none";
}
);
info("Adding a class with declarations having compatibility issue");
await testAttributeMutation(
tab,
inspector,
selectedElementPane,
allElementsPane,
[ISSUE_HYPHENS, ISSUE_CURSOR],
[ISSUE_HYPHENS, ISSUE_CURSOR],
async function() {
content.document.querySelector(".test").classList.add("issue");
}
);
info("Removing a class with declarations having compatibility issue");
await testAttributeMutation(
tab,
inspector,
selectedElementPane,
allElementsPane,
[ISSUE_HYPHENS],
[ISSUE_HYPHENS],
async function() {
content.document.querySelector(".test").classList.remove("issue");
}
);
await removeTab(tab);
});
async function testAttributeMutation(
tab,
inspector,
selectedElementPane,
allElementsPane,
expectedSelectedElementIssues,
expectedAllElementsIssues,
contentTaskFunction
) {
const onPanelUpdate = Promise.all([
inspector.once("markupmutation"),
waitForDispatch(inspector.store, COMPATIBILITY_UPDATE_NODE_COMPLETE),
]);
info("Run the task in webpage context");
await ContentTask.spawn(tab.linkedBrowser, {}, contentTaskFunction);
info("Wait for changes to reflect");
await onPanelUpdate;
info("Check issues listed in selected element pane");
await assertIssueList(selectedElementPane, expectedSelectedElementIssues);
info("Check issues listed in all issues pane");
await assertIssueList(allElementsPane, expectedAllElementsIssues);
}

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

@ -0,0 +1,151 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
const MDNCompatibility = require("devtools/shared/compatibility/MDNCompatibility");
const {
COMPATIBILITY_APPEND_NODE_COMPLETE,
COMPATIBILITY_CLEAR_DESTROYED_NODES,
} = require("devtools/client/inspector/compatibility/actions/index");
// Test the behavior rules are dynamically added
const ISSUE_CURSOR = {
type: MDNCompatibility.ISSUE_TYPE.CSS_PROPERTY,
property: "cursor",
url: "https://developer.mozilla.org/docs/Web/CSS/cursor",
deprecated: false,
experimental: false,
};
const ISSUE_HYPHENS = {
type: MDNCompatibility.ISSUE_TYPE.CSS_PROPERTY_ALIASES,
aliases: ["hyphens"],
property: "hyphens",
url: "https://developer.mozilla.org/docs/Web/CSS/hyphens",
deprecated: false,
experimental: false,
};
const TEST_URI = `
<style>
.child {
cursor: grab;
}
</style>
<body></body>
`;
add_task(async function() {
info("Testing dynamic DOM mutation using JavaScript");
const tab = await addTab(
"data:text/html;charset=utf-8," + encodeURIComponent(TEST_URI)
);
const {
allElementsPane,
inspector,
selectedElementPane,
} = await openCompatibilityView();
info("Check initial issues");
await assertIssueList(selectedElementPane, []);
await assertIssueList(allElementsPane, []);
info("Append nodes dynamically using JavaScript");
await testNodeMutation(
".child",
COMPATIBILITY_APPEND_NODE_COMPLETE,
tab,
inspector,
selectedElementPane,
allElementsPane,
[ISSUE_CURSOR],
[ISSUE_HYPHENS, ISSUE_CURSOR],
async function() {
const doc = content.document;
const parent = doc.querySelector("body");
const newElementWithIssue = doc.createElement("div");
newElementWithIssue.style.hyphens = "none";
const parentOfIssueElement = doc.createElement("div");
parentOfIssueElement.classList.add("parent");
const child = doc.createElement("div");
child.classList.add("child");
parentOfIssueElement.appendChild(child);
parent.appendChild(newElementWithIssue);
parent.appendChild(parentOfIssueElement);
}
);
info("Remove node whose child has compatibility issue");
await testNodeMutation(
"div",
COMPATIBILITY_CLEAR_DESTROYED_NODES,
tab,
inspector,
selectedElementPane,
allElementsPane,
[ISSUE_HYPHENS],
[ISSUE_HYPHENS],
async function() {
const doc = content.document;
const parent = doc.querySelector(".parent");
parent.remove();
}
);
info("Remove node which has compatibility issue");
await testNodeMutation(
"body",
COMPATIBILITY_CLEAR_DESTROYED_NODES,
tab,
inspector,
selectedElementPane,
allElementsPane,
[],
[],
async function() {
const doc = content.document;
const issueElement = doc.querySelector("div");
issueElement.remove();
}
);
await removeTab(tab);
});
async function testNodeMutation(
selector,
action,
tab,
inspector,
selectedElementPane,
allElementsPane,
expectedSelectedElementIssues,
expectedAllElementsIssues,
contentTaskFunction
) {
let onPanelUpdate = Promise.all([
inspector.once("markupmutation"),
waitForDispatch(inspector.store, action),
]);
info("Add a new node with issue and another node whose child has the issue");
await ContentTask.spawn(tab.linkedBrowser, {}, contentTaskFunction);
info("Wait for changes");
await onPanelUpdate;
onPanelUpdate = waitForUpdateSelectedNodeAction(inspector.store);
await selectNode(selector, inspector);
await onPanelUpdate;
info("Check element issues");
await assertIssueList(selectedElementPane, expectedSelectedElementIssues);
info("Check all issues");
await assertIssueList(allElementsPane, expectedAllElementsIssues);
}

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

@ -0,0 +1,152 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
const MDNCompatibility = require("devtools/shared/compatibility/MDNCompatibility");
const {
COMPATIBILITY_APPEND_NODE_COMPLETE,
COMPATIBILITY_REMOVE_NODE_COMPLETE,
} = require("devtools/client/inspector/compatibility/actions/index");
// Test the behavior rules are dynamically added
const ISSUE_CURSOR = {
type: MDNCompatibility.ISSUE_TYPE.CSS_PROPERTY,
property: "cursor",
url: "https://developer.mozilla.org/docs/Web/CSS/cursor",
deprecated: false,
experimental: false,
};
const ISSUE_HYPHENS = {
type: MDNCompatibility.ISSUE_TYPE.CSS_PROPERTY_ALIASES,
aliases: ["hyphens"],
property: "hyphens",
url: "https://developer.mozilla.org/docs/Web/CSS/hyphens",
deprecated: false,
experimental: false,
};
const TEST_URI = `
<style>
div {
cursor: grab;
}
</style>
<body>
<div></div>
<div class="parent">
<div style="hyphens: none"></div>
</div>
</body>
`;
add_task(async function() {
info("Testing dynamic DOM mutation using JavaScript");
const tab = await addTab(
"data:text/html;charset=utf-8," + encodeURIComponent(TEST_URI)
);
const { allElementsPane, inspector } = await openCompatibilityView();
info("Check initial issues");
await assertIssueList(allElementsPane, [ISSUE_CURSOR, ISSUE_HYPHENS]);
info("Delete node whose child node has CSS compatibility issue");
await testNodeRemoval(".parent", inspector, allElementsPane, [ISSUE_CURSOR]);
info("Delete node that has CSS compatibility issue");
await testNodeRemoval("div", inspector, allElementsPane, []);
info("Add node that has CSS compatibility issue");
await testNodeAddition("div", inspector, allElementsPane, [ISSUE_CURSOR]);
await removeTab(tab);
});
/**
* Simulate a click on the markup-container (a line in the markup-view)
* that corresponds to the selector passed.
* This overrides the definition in inspector/test/head.js which times
* out when the container to be clicked is already the selected node.
* @param {String|NodeFront} selector
* @param {InspectorPanel} inspector The instance of InspectorPanel currently
* loaded in the toolbox
* @return {Promise} Resolves when the node has been selected.
*/
var clickContainer = async function(selector, inspector) {
info("Clicking on the markup-container for node " + selector);
const nodeFront = await getNodeFront(selector, inspector);
const container = getContainerForNodeFront(nodeFront, inspector);
const updated = container.selected
? promise.resolve()
: inspector.once("inspector-updated");
EventUtils.synthesizeMouseAtCenter(
container.tagLine,
{ type: "mousedown" },
inspector.markup.doc.defaultView
);
EventUtils.synthesizeMouseAtCenter(
container.tagLine,
{ type: "mouseup" },
inspector.markup.doc.defaultView
);
return updated;
};
async function deleteNode(inspector, selector) {
info("Select node " + selector + " and make sure it is focused");
await selectNode(selector, inspector);
await clickContainer(selector, inspector);
info("Delete the node");
const mutated = inspector.once("markupmutation");
const updated = inspector.once("inspector-updated");
EventUtils.sendKey("delete", inspector.panelWin);
await mutated;
await updated;
}
async function testNodeAddition(
selector,
inspector,
allElementsPane,
expectedAllElementsIssues
) {
let onPanelUpdate = Promise.all([
inspector.once("markupmutation"),
waitForDispatch(inspector.store, COMPATIBILITY_APPEND_NODE_COMPLETE),
]);
info("Add a new node");
await inspector.addNode();
await onPanelUpdate;
onPanelUpdate = waitForUpdateSelectedNodeAction(inspector.store);
await selectNode(selector, inspector);
await onPanelUpdate;
info("Check issues list for the webpage");
await assertIssueList(allElementsPane, expectedAllElementsIssues);
}
async function testNodeRemoval(
selector,
inspector,
allElementsPane,
expectedAllElementsIssues
) {
const onPanelUpdate = Promise.all([
inspector.once("markupmutation"),
waitForDispatch(inspector.store, COMPATIBILITY_REMOVE_NODE_COMPLETE),
]);
info(`Delete the node with selector ${selector}`);
await deleteNode(inspector, selector);
await onPanelUpdate;
info("Check issues list for the webpage");
await assertIssueList(allElementsPane, expectedAllElementsIssues);
}

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

@ -0,0 +1,114 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
const MDNCompatibility = require("devtools/shared/compatibility/MDNCompatibility");
const {
COMPATIBILITY_UPDATE_NODE_COMPLETE,
} = require("devtools/client/inspector/compatibility/actions/index");
// Test the behavior rules are dynamically added
const ISSUE_CURSOR = {
type: MDNCompatibility.ISSUE_TYPE.CSS_PROPERTY,
property: "cursor",
url: "https://developer.mozilla.org/docs/Web/CSS/cursor",
deprecated: false,
experimental: false,
};
const ISSUE_HYPHENS = {
type: MDNCompatibility.ISSUE_TYPE.CSS_PROPERTY_ALIASES,
aliases: ["hyphens"],
property: "hyphens",
url: "https://developer.mozilla.org/docs/Web/CSS/hyphens",
deprecated: false,
experimental: false,
};
const TEST_URI = `
<style>
.issue {
cursor: grab;
}
</style>
<body>
<div class="test issue"></div>
</body>
`;
add_task(async function() {
info("Testing dynamic style change via the devtools inspector's rule view");
const tab = await addTab(
"data:text/html;charset=utf-8," + encodeURIComponent(TEST_URI)
);
const {
allElementsPane,
inspector,
selectedElementPane,
} = await openCompatibilityView();
info("Select the div to undergo mutation");
const waitForCompatibilityListUpdate = waitForUpdateSelectedNodeAction(
inspector.store
);
await selectNode(".test.issue", inspector);
await waitForCompatibilityListUpdate;
info("Check initial issues");
await checkPanelIssues(selectedElementPane, allElementsPane, [ISSUE_CURSOR]);
await addNewRule(
"hyphens",
"none",
inspector,
selectedElementPane,
allElementsPane,
[ISSUE_CURSOR, ISSUE_HYPHENS]
);
info("Toggle the inline issue rendering it disable");
await togglePropStatusOnRuleView(inspector, 0, 0);
info("Check the issues listed in panel");
await checkPanelIssues(selectedElementPane, allElementsPane, [ISSUE_CURSOR]);
info("Toggle the class rule rendering it disabled");
await togglePropStatusOnRuleView(inspector, 1, 0);
info("Check the panel issues listed in panel");
await checkPanelIssues(selectedElementPane, allElementsPane, []);
await removeTab(tab);
});
async function addNewRule(
newDeclaration,
value,
inspector,
selectedElementPane,
allElementsPane,
issue
) {
const { view } = await openRuleView();
const waitForCompatibilityListUpdate = waitForDispatch(
inspector.store,
COMPATIBILITY_UPDATE_NODE_COMPLETE
);
info("Add a new inline property");
await addProperty(view, 0, newDeclaration, value);
info("Wait for changes");
await waitForCompatibilityListUpdate;
info("Check issues list for element and the webpage");
await checkPanelIssues(selectedElementPane, allElementsPane, issue);
}
async function checkPanelIssues(selectedElementPane, allElementsPane, issues) {
info("Check selected element issues");
await assertIssueList(selectedElementPane, issues);
info("Check all panel issues");
await assertIssueList(allElementsPane, issues);
}

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

@ -2,12 +2,11 @@
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
/* import-globals-from ../../../rules/test/head.js */
/* import-globals-from ../../../test/head.js */
// Import the inspector's head.js first (which itself imports shared-head.js).
// Import the rule view's head.js first (which itself imports inspector's head.js and shared-head.js).
Services.scriptloader.loadSubScript(
"chrome://mochitests/content/browser/devtools/client/inspector/test/head.js",
"chrome://mochitests/content/browser/devtools/client/inspector/rules/test/head.js",
this
);