commit 8472726a9ae67210f6028b5f877fda16147da51e
parent 86ddf3344251887e01c18abdb827e0ea7376ed44
Author: Nicolas Chevobbe <nchevobbe@mozilla.com>
Date: Tue, 4 Nov 2025 14:39:01 +0000
Bug 1997525 - [devtools] Use checkRuleViewContent in browser_rules_inherited-element-backed-pseudo-elements.js. r=devtools-reviewers,ochameau.
`checkRuleViewContent` was tweaked so it will go through elements inside expandable containers.
This is needed as the test has element having multiple pseudo element rules.
The function started to have a high complexity, so we create a new function to
retrieve the elements we're interested in.
Differential Revision: https://phabricator.services.mozilla.com/D270848
Diffstat:
2 files changed, 468 insertions(+), 185 deletions(-)
diff --git a/devtools/client/inspector/rules/test/browser_rules_inherited-element-backed-pseudo-elements.js b/devtools/client/inspector/rules/test/browser_rules_inherited-element-backed-pseudo-elements.js
@@ -87,40 +87,99 @@ add_task(async function () {
await addTab("data:text/html;charset=utf-8," + encodeURIComponent(TEST_URI));
const { inspector, view } = await openRuleView();
- await selectNode("summary", inspector);
- Assert.deepEqual(
- getInheritedHeadersText(view),
- ["Inherited from details"],
- "There's no inherited ::details-content header when top-level <summary> is selected"
- );
-
- await selectNode("body > details > p", inspector);
- Assert.deepEqual(
- getInheritedHeadersText(view),
- ["Inherited from details::details-content", "Inherited from details"],
- "Got expected inherited headers when children of top-level <details> is selected"
- );
-
- is(
- view.element.querySelector(
- ".ruleview-header + #pseudo-elements-container .ruleview-selector-pseudo-class"
- ).textContent,
- "::after",
- "The ::after pseudo element rules is properly displayed in its section"
+ info(
+ "Check that there's no inherited ::details-content header when top-level <summary> is selected"
);
+ await selectNode("summary", inspector);
+ await checkRuleViewContent(view, [
+ { selector: `element`, ancestorRulesData: null, declarations: [] },
+ {
+ selector: `& summary`,
+ ancestorRulesData: ["details {"],
+ declarations: [{ name: "color", value: "violet" }],
+ },
+ {
+ header: "Inherited from details",
+ },
+ {
+ selector: `details`,
+ inherited: true,
+ declarations: [
+ { name: "--x", value: "blue" },
+ { name: "color", value: "gold", overridden: true },
+ ],
+ },
+ ]);
- ok(
- !isPropertyOverridden(view, 6, { color: "dodgerblue" }),
- "color property in ::details-content is not overridden"
- );
- ok(
- isPropertyOverridden(view, 7, { color: "forestgreen" }),
- "color property in lower specificity ::details-content is overridden"
- );
- ok(
- isPropertyOverridden(view, 9, { color: "gold" }),
- "color property in details is overridden"
+ info(
+ "Check that there are expected inherited headers when children of top-level <details> is selected"
);
+ await selectNode("body > details > p", inspector);
+ await checkRuleViewContent(view, [
+ {
+ header: "Pseudo-elements",
+ },
+ {
+ selector: `&::after`,
+ ancestorRulesData: [`p {`],
+ declarations: [
+ { name: "content", value: `" meow"` },
+ { name: "color", value: "green" },
+ ],
+ },
+ {
+ header: "This Element",
+ },
+ { selector: `element`, ancestorRulesData: null, declarations: [] },
+ {
+ selector: `p`,
+ declarations: [{ name: "outline-color", value: "var(--x)" }],
+ },
+ {
+ header: "Inherited from details::details-content",
+ },
+ {
+ selector: `&::details-content`,
+ ancestorRulesData: [`details {`],
+ inherited: true,
+ declarations: [
+ { name: "--x", value: "tomato" },
+ { name: "color", value: "dodgerblue" },
+ ],
+ },
+ {
+ selector: `:where(body > details)::details-content`,
+ inherited: true,
+ declarations: [
+ {
+ name: "color",
+ value: "forestgreen",
+ // overridden because lower specificity than ::details-content
+ overridden: true,
+ },
+ ],
+ },
+ {
+ header: "Inherited from details",
+ },
+ {
+ selector: `details`,
+ inherited: true,
+ declarations: [
+ {
+ name: "--x",
+ value: "blue",
+ overridden: true,
+ },
+ {
+ name: "color",
+ value: "gold",
+ // overridden by color: dodgerblue on ::details-content
+ overridden: true,
+ },
+ ],
+ },
+ ]);
checkCSSVariableOutput(
view,
@@ -132,58 +191,168 @@ add_task(async function () {
info("Check rules and declarations for details in summary");
await selectNode("details#in-summary", inspector);
- Assert.deepEqual(
- getInheritedHeadersText(view),
- ["Inherited from summary"],
- "Got expected inherited headers when <details> in <summary> is selected"
- );
-
+ await checkRuleViewContent(view, [
+ {
+ header: "Pseudo-elements",
+ },
+ {
+ selector: `&::details-content`,
+ ancestorRulesData: ["details#in-summary {"],
+ declarations: [
+ { name: "--x", value: "rebeccapurple" },
+ { name: "color", value: "brown" },
+ ],
+ },
+ {
+ selector: `&::details-content`,
+ ancestorRulesData: ["details {"],
+ declarations: [
+ { name: "--x", value: "tomato", overridden: true },
+ { name: "color", value: "dodgerblue", overridden: true },
+ { name: "background-color", value: "rgb(200 0 0 / 0.1)" },
+ ],
+ },
+ {
+ header: "This Element",
+ },
+ { selector: `element`, ancestorRulesData: null, declarations: [] },
+ {
+ selector: `details#in-summary`,
+ declarations: [{ name: "color", value: "cyan" }],
+ },
+ {
+ selector: `details`,
+ declarations: [
+ { name: "--x", value: "blue" },
+ { name: "color", value: "gold", overridden: true },
+ ],
+ },
+ {
+ header: "Inherited from summary",
+ },
+ {
+ selector: `& summary`,
+ ancestorRulesData: ["details {"],
+ inherited: true,
+ declarations: [{ name: "color", value: "violet", overridden: true }],
+ },
+ ]);
+
+ info("Check rules and declarations for nested summary");
await selectNode("details#in-summary summary", inspector);
- Assert.deepEqual(
- getInheritedHeadersText(view),
- ["Inherited from details#in-summary"],
- "Got expected inherited headers when nested <summary> is selected"
- );
+ await checkRuleViewContent(view, [
+ { selector: `element`, ancestorRulesData: null, declarations: [] },
+ {
+ selector: `& summary`,
+ ancestorRulesData: ["details#in-summary {"],
+ declarations: [{ name: "color", value: "hotpink" }],
+ },
+ {
+ selector: `& summary`,
+ ancestorRulesData: ["details {"],
+ declarations: [{ name: "color", value: "violet", overridden: true }],
+ },
+ {
+ header: "Inherited from details#in-summary",
+ },
+ {
+ selector: `details#in-summary`,
+ inherited: true,
+ declarations: [{ name: "color", value: "cyan", overridden: true }],
+ },
+ {
+ selector: `details`,
+ inherited: true,
+ declarations: [
+ { name: "--x", value: "blue" },
+ { name: "color", value: "gold", overridden: true },
+ ],
+ },
+ ]);
+
+ info("Check rules and declarations for nested <details> child");
await selectNode("details#in-summary p", inspector);
- Assert.deepEqual(
- getInheritedHeadersText(view),
- [
- "Inherited from details#in-summary::details-content",
- "Inherited from details#in-summary",
- "Inherited from summary",
- ],
- "Got expected inherited headers when nested <details> child is selected"
- );
-
- is(
- view.element.querySelector(
- ".ruleview-header + #pseudo-elements-container .ruleview-selector-pseudo-class"
- ).textContent,
- "::after",
- "The ::after pseudo element rules is properly displayed in its section"
- );
-
- ok(
- !isPropertyOverridden(view, 6, { color: "brown" }),
- "color property in #detail#in-summary::details-content is not overridden"
- );
- ok(
- isPropertyOverridden(view, 7, { color: "dodgerblue" }),
- "color property in ::details-content is overridden"
- );
- ok(
- isPropertyOverridden(view, 9, { color: "cyan" }),
- "color property in details#in-summary is overridden"
- );
- ok(
- isPropertyOverridden(view, 10, { color: "gold" }),
- "color property in details is overridden"
- );
- ok(
- isPropertyOverridden(view, 12, { color: "violet" }),
- "color property in summary is overridden"
- );
+ await checkRuleViewContent(view, [
+ {
+ header: "Pseudo-elements",
+ },
+ {
+ selector: `&::after`,
+ ancestorRulesData: [`p {`],
+ declarations: [
+ { name: "content", value: `" meow"` },
+ { name: "color", value: "green" },
+ ],
+ },
+ {
+ header: "This Element",
+ },
+ { selector: `element`, ancestorRulesData: null, declarations: [] },
+ {
+ selector: `p`,
+ declarations: [{ name: "outline-color", value: "var(--x)" }],
+ },
+ {
+ header: "Inherited from details#in-summary::details-content",
+ },
+ {
+ selector: `&::details-content`,
+ ancestorRulesData: [`details#in-summary {`],
+ inherited: true,
+ declarations: [
+ { name: "--x", value: "rebeccapurple" },
+ {
+ name: "color",
+ value: "brown",
+ },
+ ],
+ },
+ {
+ selector: `&::details-content`,
+ ancestorRulesData: [`details {`],
+ inherited: true,
+ declarations: [
+ { name: "--x", value: "tomato", overridden: true },
+ {
+ name: "color",
+ value: "dodgerblue",
+ overridden: true,
+ },
+ ],
+ },
+ {
+ header: "Inherited from details#in-summary",
+ },
+ {
+ selector: `details#in-summary`,
+ inherited: true,
+ declarations: [{ name: "color", value: "cyan", overridden: true }],
+ },
+ {
+ selector: `details`,
+ inherited: true,
+ declarations: [
+ { name: "--x", value: "blue", overridden: true },
+ { name: "color", value: "gold", overridden: true },
+ ],
+ },
+ {
+ header: "Inherited from summary",
+ },
+ {
+ selector: `& summary`,
+ ancestorRulesData: [`details {`],
+ inherited: true,
+ declarations: [
+ {
+ name: "color",
+ value: "violet",
+ overridden: true,
+ },
+ ],
+ },
+ ]);
checkCSSVariableOutput(
view,
@@ -197,117 +366,212 @@ add_task(async function () {
// when a <details> element has multiple <summary> children, only the first one is
// actually interactive. The other ones are placed inside the ::details-content
await selectNode("summary#non-functional-summary", inspector);
- Assert.deepEqual(
- getInheritedHeadersText(view),
- ["Inherited from details::details-content", "Inherited from details"],
- "Got expected inherited headers when non functional summary is selected"
- );
-
- ok(
- !isPropertyOverridden(view, 1, { color: "violet" }),
- "color property in summary is not overridden when non functional summary is selected"
- );
- ok(
- isPropertyOverridden(view, 3, { color: "dodgerblue" }),
- "color property in details::details-content is overridden when non functional summary is selected"
- );
- ok(
- isPropertyOverridden(view, 4, { color: "forestgreen" }),
- "color property in :where(body > details)::details-content is overridden when non functional summary is selected"
- );
- ok(
- isPropertyOverridden(view, 6, { color: "gold" }),
- "color property in details is overridden when non functional summary is selected"
- );
+ await checkRuleViewContent(view, [
+ { selector: `element`, declarations: [] },
+ {
+ selector: `& summary`,
+ ancestorRulesData: [`details {`],
+ declarations: [{ name: "color", value: "violet" }],
+ },
+ {
+ header: "Inherited from details::details-content",
+ },
+ {
+ selector: `&::details-content`,
+ ancestorRulesData: [`details {`],
+ inherited: true,
+ declarations: [
+ { name: "--x", value: "tomato" },
+ { name: "color", value: "dodgerblue", overridden: true },
+ ],
+ },
+ {
+ selector: `:where(body > details)::details-content`,
+ inherited: true,
+ declarations: [
+ {
+ name: "color",
+ value: "forestgreen",
+ overridden: true,
+ },
+ ],
+ },
+ {
+ header: "Inherited from details",
+ },
+ {
+ selector: `details`,
+ inherited: true,
+ declarations: [
+ {
+ name: "--x",
+ value: "blue",
+ overridden: true,
+ },
+ {
+ name: "color",
+ value: "gold",
+ overridden: true,
+ },
+ ],
+ },
+ ]);
info("Check rules and declarations for details in details");
await selectNode("details.in-details", inspector);
- Assert.deepEqual(
- getInheritedHeadersText(view),
- ["Inherited from details::details-content"],
- "Got expected inherited headers when <details> in <details> is selected"
- );
- ok(
- !isPropertyOverridden(view, 4, { color: "gold" }),
- "color property in details is not overridden for details in details"
- );
- ok(
- isPropertyOverridden(view, 6, { color: "forestgreen" }),
- "color property in where(body > details)::details-content is overridden for details in details"
- );
+ await checkRuleViewContent(view, [
+ {
+ header: "Pseudo-elements",
+ },
+ {
+ selector: `&::details-content`,
+ ancestorRulesData: ["details {"],
+ declarations: [
+ { name: "--x", value: "tomato" },
+ { name: "color", value: "dodgerblue" },
+ { name: "background-color", value: "rgb(200 0 0 / 0.1)" },
+ ],
+ },
+ {
+ header: "This Element",
+ },
+ { selector: `element`, ancestorRulesData: null, declarations: [] },
+ {
+ selector: `details`,
+ declarations: [
+ { name: "--x", value: "blue" },
+ { name: "color", value: "gold" },
+ ],
+ },
+ {
+ header: "Inherited from details::details-content",
+ },
+ {
+ selector: `:where(body > details)::details-content`,
+ inherited: true,
+ declarations: [{ name: "color", value: "forestgreen", overridden: true }],
+ },
+ ]);
info("Check rules and declarations for children of details in details");
await selectNode("details.in-details p", inspector);
- Assert.deepEqual(
- getInheritedHeadersText(view),
- [
+ await checkRuleViewContent(view, [
+ {
+ header: "Pseudo-elements",
+ },
+ {
+ selector: `&::after`,
+ ancestorRulesData: [`p {`],
+ declarations: [
+ { name: "content", value: `" meow"` },
+ { name: "color", value: "green" },
+ ],
+ },
+ {
+ header: "This Element",
+ },
+ { selector: `element`, ancestorRulesData: null, declarations: [] },
+ {
+ selector: `p`,
+ declarations: [{ name: "outline-color", value: "var(--x)" }],
+ },
+ {
// this is for the body > details > details::details-content pseudo
- "Inherited from details::details-content",
+ header: "Inherited from details::details-content",
+ },
+ {
+ selector: `&::details-content`,
+ ancestorRulesData: [`details {`],
+ inherited: true,
+ declarations: [
+ { name: "--x", value: "tomato" },
+ {
+ name: "color",
+ value: "dodgerblue",
+ },
+ ],
+ },
+ {
// this is for the body > details::details-content pseudo
- "Inherited from details::details-content",
- "Inherited from details",
- ],
- "Got expected inherited headers when children <details> in <details> is selected"
- );
-
- ok(
- !isPropertyOverridden(view, 6, { color: "dodgerblue" }),
- "color property in inherited details::details-content is not overridden for child of details in details"
- );
- ok(
- isPropertyOverridden(view, 8, { color: "forestgreen" }),
- "color property in inherited :where(body > details)::details-content is overridden for child of details in details"
- );
- ok(
- isPropertyOverridden(view, 10, { color: "gold" }),
- "color property in inherited details is overridden for child of details in details"
- );
+ header: "Inherited from details::details-content",
+ },
+ {
+ selector: `:where(body > details)::details-content`,
+ inherited: true,
+ declarations: [{ name: "color", value: "forestgreen", overridden: true }],
+ },
+ {
+ header: "Inherited from details",
+ },
+ {
+ selector: `details`,
+ inherited: true,
+ declarations: [
+ {
+ name: "--x",
+ value: "blue",
+ overridden: true,
+ },
+ {
+ name: "color",
+ value: "gold",
+ overridden: true,
+ },
+ ],
+ },
+ ]);
info(
"Check that properties in inherited element-backed pseudo element rules are properly picked when using !important"
);
await selectNode("#vip article", inspector);
- Assert.deepEqual(
- getInheritedHeadersText(view),
- [
- "Inherited from details#vip::details-content",
- "Inherited from details#vip",
- ],
- "Got expected inherited headers"
- );
-
- ok(
- isPropertyOverridden(view, 2, { color: "red" }),
- "non-important color property in #vip::details-content is overridden"
- );
- ok(
- !isPropertyOverridden(view, 3, { color: "blue" }),
- "important color property in #vip::details-content is not overridden"
- );
- ok(
- isPropertyOverridden(view, 4, { color: "dodgerblue" }),
- "non important color property in details::details-content is overridden"
- );
- ok(
- isPropertyOverridden(view, 5, { color: "forestgreen" }),
- "non important color property in :where(body > details)::details-content is overridden"
- );
- ok(
- isPropertyOverridden(view, 7, { color: "gold" }),
- "non important color property in details is overridden"
- );
+ await checkRuleViewContent(view, [
+ { selector: `element`, ancestorRulesData: null, declarations: [] },
+ {
+ header: "Inherited from details#vip::details-content",
+ },
+ {
+ selector: `details#vip::details-content`,
+ inherited: true,
+ declarations: [{ name: "color", value: "red", overridden: true }],
+ },
+ {
+ selector: `details#vip::details-content`,
+ inherited: true,
+ declarations: [{ name: "color", value: "blue !important" }],
+ },
+ {
+ selector: `&::details-content`,
+ ancestorRulesData: [`details {`],
+ inherited: true,
+ declarations: [
+ { name: "--x", value: "tomato" },
+ { name: "color", value: "dodgerblue", overridden: true },
+ ],
+ },
+ {
+ selector: `:where(body > details)::details-content`,
+ inherited: true,
+ declarations: [{ name: "color", value: "forestgreen", overridden: true }],
+ },
+ {
+ header: "Inherited from details#vip",
+ },
+ {
+ selector: `details`,
+ inherited: true,
+ declarations: [
+ {
+ name: "--x",
+ value: "blue",
+ overridden: true,
+ },
+ {
+ name: "color",
+ value: "gold",
+ overridden: true,
+ },
+ ],
+ },
+ ]);
});
-
-function getInheritedHeadersText(view) {
- return [...view.element.querySelectorAll(".ruleview-header-inherited")].map(
- el => el.textContent
- );
-}
-
-function isPropertyOverridden(view, ruleIndex, property) {
- return getTextProperty(
- view,
- ruleIndex,
- property
- ).editor.element.classList.contains("ruleview-overridden");
-}
diff --git a/devtools/client/inspector/rules/test/head.js b/devtools/client/inspector/rules/test/head.js
@@ -1392,11 +1392,7 @@ function getSmallIncrementKey() {
* Pseudo-elements, …), the text of said header.
*/
function checkRuleViewContent(view, expectedElements) {
- const elementsInView = Array.from(view.element.children).filter(
- // We don't check @property content for now
- el => !el.classList.contains("registered-properties")
- );
-
+ const elementsInView = _getRuleViewElements(view);
is(
elementsInView.length,
expectedElements.length,
@@ -1510,6 +1506,29 @@ function checkRuleViewContent(view, expectedElements) {
}
}
+/**
+ * Get the rule view elements for checkRuleViewContent
+ *
+ * @param {RuleView} view
+ * @returns {Element[]}
+ */
+function _getRuleViewElements(view) {
+ const elementsInView = [];
+ for (const el of view.element.children) {
+ if (el.classList.contains("registered-properties")) {
+ // We don't check @property content for now
+ continue;
+ }
+ // Gather all the children of expandable containers (e.g. Pseudo-element, @keyframe, …)
+ if (el.classList.contains("ruleview-expandable-container")) {
+ elementsInView.push(...el.children);
+ } else {
+ elementsInView.push(el);
+ }
+ }
+ return elementsInView;
+}
+
function getUnusedVariableButton(view, elementIndexInView) {
return view.element.children[elementIndexInView].querySelector(
".ruleview-show-unused-custom-css-properties"