Bug 1776831 - [devtools] Refresh rules view on STYLESHEET resource available. r=jdescottes,devtools-reviewers.

Differential Revision: https://phabricator.services.mozilla.com/D185393
This commit is contained in:
Nicolas Chevobbe 2023-09-11 15:32:29 +00:00
parent 4e841cf287
commit 0506baf22f
6 changed files with 101 additions and 3 deletions

View File

@ -32,6 +32,7 @@ add_task(async function () {
selectNode,
// selectNodeInFrames depends on selectNode, getNodeFront, getNodeFrontInFrames.
selectNodeInFrames,
waitUntil,
});
// This is a simple test page, which contains a <div> with a CSS rule `color: red`
@ -63,6 +64,7 @@ add_task(async function () {
info("Retrieve the sourceLabel for the rule at index 1");
const ruleView = inspector.getPanel("ruleview").view;
await waitUntil(() => getRuleViewLinkByIndex(ruleView, 1));
const sourceLabelEl = getRuleViewLinkByIndex(ruleView, 1).querySelector(
".ruleview-rule-source-label"
);

View File

@ -2077,7 +2077,10 @@ function RuleViewTool(inspector, window) {
this.inspector.styleChangeTracker.on("style-changed", this.refresh);
this.inspector.commands.resourceCommand.watchResources(
[this.inspector.commands.resourceCommand.TYPES.DOCUMENT_EVENT],
[
this.inspector.commands.resourceCommand.TYPES.DOCUMENT_EVENT,
this.inspector.commands.resourceCommand.TYPES.STYLESHEET,
],
{
onAvailable: this._onResourceAvailable,
ignoreExistingResources: true,
@ -2140,6 +2143,11 @@ RuleViewTool.prototype = {
},
_onResourceAvailable(resources) {
if (!this.inspector) {
return;
}
let hasNewStylesheet = false;
for (const resource of resources) {
if (
resource.resourceType ===
@ -2148,7 +2156,23 @@ RuleViewTool.prototype = {
resource.targetFront.isTopLevel
) {
this.clearUserProperties();
continue;
}
if (
resource.resourceType ===
this.inspector.commands.resourceCommand.TYPES.STYLESHEET &&
// resource.isNew is only true when the stylesheet was added from DevTools,
// for example when adding a rule in the rule view. In such cases, we're already
// updating the rule view, so ignore those.
!resource.isNew
) {
hasNewStylesheet = true;
}
}
if (hasNewStylesheet) {
this.refresh();
}
},

View File

@ -173,6 +173,7 @@ skip-if =
[browser_rules_refresh-no-flicker.js]
[browser_rules_refresh-on-attribute-change_01.js]
[browser_rules_refresh-on-style-change.js]
[browser_rules_refresh-on-stylesheet-change.js]
[browser_rules_search-filter-computed-list_01.js]
[browser_rules_search-filter-computed-list_02.js]
[browser_rules_search-filter-computed-list_03.js]

View File

@ -0,0 +1,65 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
// Test that the rule view refreshes when a stylesheet is added or modified
const TEST_URI = "<h1>Hello DevTools</h1>";
add_task(async function () {
await addTab("data:text/html;charset=utf-8," + encodeURIComponent(TEST_URI));
const { inspector, view } = await openRuleView();
await selectNode("h1", inspector);
info("Add a stylesheet with matching rule for the h1 node");
let onUpdated = inspector.once("rule-view-refreshed");
await SpecialPowers.spawn(gBrowser.selectedBrowser, [], () => {
const addedStylesheet = content.document.createElement("style");
addedStylesheet.textContent = "h1 { background: tomato }";
content.document.head.append(addedStylesheet);
});
await onUpdated;
ok(true, "Rules view was refreshed when adding a stylesheet");
checkRulesViewSelectors(view, ["element", "h1"]);
is(
getRuleViewPropertyValue(view, "h1", "background"),
"tomato",
"Expected value is displayed for the background property"
);
info("Modify the stylesheet added previously");
onUpdated = inspector.once("rule-view-refreshed");
await SpecialPowers.spawn(gBrowser.selectedBrowser, [], () => {
const addedStylesheet = content.document.querySelector("style");
addedStylesheet.textContent = "body h1 { background: gold; color: navy; }";
});
await onUpdated;
ok(true, "Rules view was refreshed when updating the stylesheet");
checkRulesViewSelectors(view, ["element", "body h1"]);
is(
getRuleViewPropertyValue(view, "body h1", "background"),
"gold",
"Expected value is displayed for the background property"
);
is(
getRuleViewPropertyValue(view, "body h1", "color"),
"navy",
"Expected value is displayed for the color property"
);
});
function checkRulesViewSelectors(view, expectedSelectors) {
Assert.deepEqual(
getRuleSelectors(view),
expectedSelectors,
"Expected selectors are displayed"
);
}
function getRuleSelectors(view) {
return Array.from(
view.styleDocument.querySelectorAll(".ruleview-selectorcontainer")
).map(el => el.textContent);
}

View File

@ -185,6 +185,7 @@ async function compareAppliedStylesWithUI(inspector, view, filter) {
entries = [...entryMap.values()];
const elementStyle = view._elementStyle;
await waitFor(() => elementStyle.rules.length === entries.length);
is(
elementStyle.rules.length,
entries.length,

View File

@ -1008,9 +1008,14 @@ async function assertTooltipHiddenOnMouseOut(tooltip, target) {
* @return {DOMNode} The rule editor if any at this index
*/
function getRuleViewRuleEditor(view, childrenIndex, nodeIndex) {
const child = view.element.children[childrenIndex];
if (!child) {
return null;
}
return nodeIndex !== undefined
? view.element.children[childrenIndex].childNodes[nodeIndex]._ruleEditor
: view.element.children[childrenIndex]._ruleEditor;
? child.childNodes[nodeIndex]?._ruleEditor
: child._ruleEditor;
}
/**