commit 37b89fd45fb7083a6292bcd8ad031975e62cc314
parent 8c15e05f81970d6d2aec9807c7d427cbe7773eda
Author: Nicolas Chevobbe <nchevobbe@mozilla.com>
Date: Tue, 4 Nov 2025 14:39:00 +0000
Bug 1997520 - [devtools] Use checkRuleViewContent in browser_rules_at_starting-style.js. r=devtools-reviewers,ochameau.
This allows us to remove the checks that we were doing for overridden properties as those are included in checkRuleViewContent.
checkRuleViewContent is slightly modified: we filter out .registered-properties for now, and we tweak the assertion messages
so failures are easier to debug.
Differential Revision: https://phabricator.services.mozilla.com/D270809
Diffstat:
2 files changed, 207 insertions(+), 156 deletions(-)
diff --git a/devtools/client/inspector/rules/test/browser_rules_at_starting-style.js b/devtools/client/inspector/rules/test/browser_rules_at_starting-style.js
@@ -113,23 +113,30 @@ add_task(async function () {
encodeURIComponent(TEST_URI)
);
const { inspector, view } = await openRuleView();
- await assertRules("body", [
- { selector: `element`, ancestorRulesData: null },
+
+ await selectNode("body", inspector);
+ await checkRuleViewContent(view, [
+ { selector: `element`, ancestorRulesData: null, declarations: [] },
{
selector: `body, [data-test="in-starting-style"]`,
ancestorRulesData: ["@starting-style {"],
+ declarations: [{ name: "color", value: "navy" }],
},
{
selector: `body, [data-test="in-starting-style-layer"]`,
ancestorRulesData: ["@starting-style {", " @layer {"],
+ declarations: [{ name: "color", value: "hotpink", overridden: true }],
},
+ { header: "@property" },
]);
- await assertRules("h1", [
- { selector: `element`, ancestorRulesData: null },
+ await selectNode("h1", inspector);
+ await checkRuleViewContent(view, [
+ { selector: `element`, ancestorRulesData: null, declarations: [] },
{
selector: `h1, [data-test="in-starting-style"]`,
ancestorRulesData: ["@starting-style {"],
+ declarations: [{ name: "background-color", value: "salmon" }],
},
{
selector: ``,
@@ -137,131 +144,222 @@ add_task(async function () {
`h1, [data-test="top-level"] {`,
" @starting-style {",
],
+ declarations: [{ name: "color", value: "gold" }],
},
{
selector: `h1, [data-test="top-level"]`,
ancestorRulesData: null,
+ declarations: [
+ { name: "color", value: "tomato" },
+ { name: "transition", value: "all 1s" },
+ ],
},
+ { header: "@property" },
]);
- await assertRules("main", [
- { selector: `element`, ancestorRulesData: null },
+ await selectNode("main", inspector);
+ await checkRuleViewContent(view, [
+ { selector: `element`, ancestorRulesData: null, declarations: [] },
{
selector: ``,
ancestorRulesData: [
`main, [data-test="top-level"] {`,
" @starting-style {",
],
+ declarations: [
+ { name: "--empty-start", value: "" },
+ {
+ name: "background-color",
+ value: "goldenrod",
+ // background-color value in last starting-style rule is not overridden
+ overridden: false,
+ },
+ {
+ name: "padding-top",
+ value: "3px",
+ // padding-top value in last starting-style rule is overridden by the !important
+ // set on the top level rule
+ overridden: true,
+ },
+ {
+ name: "margin-top",
+ value: "3px",
+ // margin-top value in last starting-style rule is overridden by the !important set
+ // on another starting-style rule
+ overridden: true,
+ },
+ {
+ name: "outline-color",
+ value: "goldenrod",
+ // outline-color value in last starting-style rule is overridden by the !important
+ // set on another starting-style rule
+ overridden: true,
+ },
+ ],
},
{
selector: `main, [data-test="top-level"]`,
ancestorRulesData: null,
+ declarations: [
+ { name: "--my-color", value: "white" },
+ { name: "--my-overridden-color", value: "white !important" },
+ { name: "--my-registered-color", value: "white" },
+ { name: "--empty-start", value: "1px" },
+ {
+ name: "--check-my-overridden-color",
+ value: "var(--my-overridden-color)",
+ },
+ {
+ name: "--check-my-registered-color",
+ value: "var(--my-registered-color)",
+ },
+ { name: "--check-empty-start", value: "var(--empty-start)" },
+ { name: "color", value: "var(--my-color)" },
+ {
+ name: "background-color",
+ value: "firebrick",
+ // background-color value in top level rule is not overridden, even if the
+ // property is also set in a starting style rule
+ overridden: false,
+ },
+ {
+ name: "padding-top",
+ value: "2px !important",
+ // padding-top value in top level rule is not overridden
+ overridden: false,
+ },
+ {
+ name: "margin-top",
+ value: "2px",
+ // margin-top value in top level rule is not overridden
+ overridden: false,
+ },
+ { name: "transition", value: "all 1s 1000s" },
+ {
+ name: "outline-color",
+ value: "firebrick",
+ // outline-color value in top level rule is not overridden
+ overridden: false,
+ },
+ { name: "outline-width", value: "5px" },
+ { name: "outline-style", value: "solid" },
+ { name: "outline-offset", value: "10px" },
+ ],
},
{
selector: `main, [data-test="in-starting-style"]`,
ancestorRulesData: ["@starting-style {"],
+ declarations: [
+ { name: "--my-color", value: "black !important" },
+ { name: "--my-overridden-color", value: "black", overridden: true },
+ { name: "--my-registered-color", value: "black !important" },
+ { name: "--check-my-color", value: "var(--my-color)" },
+ {
+ name: "--check-my-overridden-color",
+ value: "var(--my-overridden-color)",
+ overridden: true,
+ },
+ {
+ name: "--check-my-registered-color",
+ value: "var(--my-registered-color)",
+ overridden: true,
+ },
+ {
+ name: "--check-my-unset-registered-color",
+ value: "var(--my-unset-registered-color)",
+ },
+ {
+ name: "background-color",
+ value: "dodgerblue",
+ // background-color value in top-level starting style rule is overridden
+ overridden: true,
+ },
+ {
+ name: "padding-top",
+ value: "1px",
+ // padding-top value in top-level starting style rule is overridden
+ overridden: true,
+ },
+ {
+ name: "margin-top",
+ value: "1px !important",
+ // margin-top value in top-level starting style rule is not overridden,
+ // since it's declared with !important
+ overridden: false,
+ },
+ {
+ name: "outline-color",
+ value: "dodgerblue",
+ // outline-color value in top-level starting style rule is overridden
+ overridden: true,
+ },
+ ],
},
{
selector: `main, [data-test="in-starting-style-layer-2"]`,
ancestorRulesData: [`@starting-style {`, " @layer {"],
+ declarations: [
+ {
+ name: "background-color",
+ value: "cyan",
+ // background-color value in second layer in starting style rule is overridden
+ overridden: true,
+ },
+ {
+ name: "padding-top",
+ value: "5px",
+ // padding-top value in second layer in starting style rule is overridden
+ overridden: true,
+ },
+ {
+ name: "margin-top",
+ value: "5px",
+ // margin-top value in second layer in starting style rule is overridden
+ overridden: true,
+ },
+ {
+ name: "outline-color",
+ value: "cyan !important",
+ // outline-color value in second layer in starting style rule is overridden even
+ // if it was declared with !important
+ overridden: true,
+ },
+ ],
},
{
selector: `main, [data-test="in-starting-style-layer"]`,
ancestorRulesData: [`@starting-style {`, " @layer {"],
+ declarations: [
+ {
+ name: "background-color",
+ value: "forestgreen",
+ // background-color value in first layer in starting style rule is overridden
+ overridden: true,
+ },
+ {
+ name: "padding-top",
+ value: "4px",
+ // padding-top value in first layer in starting style rule is overridden
+ overridden: true,
+ },
+ {
+ name: "margin-top",
+ value: "4px",
+ // margin-top value in first layer in starting style rule is overridden
+ overridden: true,
+ },
+ {
+ name: "outline-color",
+ value: "forestgreen !important",
+ // outline-color value in first layer in starting style rule is not overridden
+ // as it's declared with !important
+ overridden: false,
+ },
+ ],
},
+ { header: "@property" },
]);
- await selectNode("main", inspector);
-
- info("Check that we're handling overridden properties correctly");
- //Check background-color
- ok(
- !isPropertyOverridden(view, 1, { "background-color": "goldenrod" }),
- "background-color value in last starting-style rule is not overridden"
- );
- ok(
- !isPropertyOverridden(view, 2, { "background-color": "firebrick" }),
- "background-color value in top level rule is not overridden, even if the property is also set in a starting style rule"
- );
- ok(
- isPropertyOverridden(view, 3, { "background-color": "dodgerblue" }),
- "background-color value in top-level starting style rule is overridden"
- );
- ok(
- isPropertyOverridden(view, 4, { "background-color": "cyan" }),
- "background-color value in second layer in starting style rule is overridden"
- );
- ok(
- isPropertyOverridden(view, 5, { "background-color": "forestgreen" }),
- "background-color value in first layer in starting style rule is overridden"
- );
-
- //Check padding-top
- ok(
- isPropertyOverridden(view, 1, { "padding-top": "3px" }),
- "padding-top value in last starting-style rule is overridden by the !important set on the top level rule"
- );
- ok(
- !isPropertyOverridden(view, 2, { "padding-top": "2px" }),
- "padding-top value in top level rule is not overridden"
- );
- ok(
- isPropertyOverridden(view, 3, { "padding-top": "1px" }),
- "padding-top value in top-level starting style rule is overridden"
- );
- ok(
- isPropertyOverridden(view, 4, { "padding-top": "5px" }),
- "padding-top value in second layer in starting style rule is overridden"
- );
- ok(
- isPropertyOverridden(view, 5, { "padding-top": "4px" }),
- "padding-top value in first layer in starting style rule is overridden"
- );
-
- //Check margin-top
- ok(
- isPropertyOverridden(view, 1, { "margin-top": "3px" }),
- "margin-top value in last starting-style rule is overridden by the !important set on another starting-style rule"
- );
- ok(
- !isPropertyOverridden(view, 2, { "margin-top": "2px" }),
- "margin-top value in top level rule is not overridden"
- );
- ok(
- !isPropertyOverridden(view, 3, { "margin-top": "1px" }),
- "margin-top value in top-level starting style rule is not overridden, since it's declared with !important"
- );
- ok(
- isPropertyOverridden(view, 4, { "margin-top": "5px" }),
- "margin-top value in second layer in starting style rule is overridden"
- );
- ok(
- isPropertyOverridden(view, 5, { "margin-top": "4px" }),
- "margin-top value in first layer in starting style rule is overridden"
- );
-
- //Check outline-color
- ok(
- isPropertyOverridden(view, 1, { "outline-color": "goldenrod" }),
- "outline-color value in last starting-style rule is overridden by the !important set on another startint-style rule"
- );
- ok(
- !isPropertyOverridden(view, 2, { "outline-color": "firebrick" }),
- "outline-color value in top level rule is not overridden"
- );
- ok(
- isPropertyOverridden(view, 3, { "outline-color": "dodgerblue" }),
- "outline-color value in top-level starting style rule is overridden"
- );
- ok(
- isPropertyOverridden(view, 4, { "outline-color": "cyan" }),
- "outline-color value in second layer in starting style rule is overridden even if it was declared with !important"
- );
- ok(
- !isPropertyOverridden(view, 5, { "outline-color": "forestgreen" }),
- "outline-color value in first layer in starting style rule is not overridden as it's declared with !important"
- );
-
info(
"Check that CSS variables set in starting-style are not impacting the var() tooltip"
);
@@ -494,57 +592,6 @@ add_task(async function () {
startingStyleClasses: ["empty-css-variable"],
}
);
-
- async function assertRules(nodeSelector, expectedRules) {
- await selectNode(nodeSelector, inspector);
- const rulesInView = Array.from(
- // don't retrieve @property rules
- view.element.querySelectorAll(".ruleview-rule:not([data-name])")
- );
- is(
- rulesInView.length,
- expectedRules.length,
- `[${nodeSelector}] All expected rules are displayed`
- );
-
- for (let i = 0; i < expectedRules.length; i++) {
- const expectedRule = expectedRules[i];
- info(`[${nodeSelector}] Checking rule #${i}: ${expectedRule.selector}`);
-
- const selector = rulesInView[i].querySelector(
- ".ruleview-selectors-container"
- )?.innerText;
-
- is(
- selector,
- expectedRule.selector,
- `[${nodeSelector}] Expected selector for rule #${i}`
- );
-
- const isInherited = rulesInView[i].matches(
- ".ruleview-header-inherited + .ruleview-rule"
- );
- if (expectedRule.inherited) {
- ok(isInherited, `[${nodeSelector}] rule #${i} is inherited`);
- } else {
- ok(!isInherited, `[${nodeSelector}] rule #${i} is not inherited`);
- }
-
- if (expectedRule.ancestorRulesData == null) {
- is(
- getRuleViewAncestorRulesDataElementByIndex(view, i),
- null,
- `[${nodeSelector}] No ancestor rules data displayed for ${selector}`
- );
- } else {
- is(
- getRuleViewAncestorRulesDataTextByIndex(view, i),
- expectedRule.ancestorRulesData.join("\n"),
- `[${nodeSelector}] Expected ancestor rules data displayed for ${selector}`
- );
- }
- }
- }
});
function isPropertyOverridden(view, ruleIndex, property) {
diff --git a/devtools/client/inspector/rules/test/head.js b/devtools/client/inspector/rules/test/head.js
@@ -1392,9 +1392,13 @@ function getSmallIncrementKey() {
* Pseudo-elements, …), the text of said header.
*/
function checkRuleViewContent(view, expectedElements) {
- const rulesInView = Array.from(view.element.children);
+ const elementsInView = Array.from(view.element.children).filter(
+ // We don't check @property content for now
+ el => !el.classList.contains("registered-properties")
+ );
+
is(
- rulesInView.length,
+ elementsInView.length,
expectedElements.length,
"All expected elements are displayed"
);
@@ -1403,7 +1407,7 @@ function checkRuleViewContent(view, expectedElements) {
const expectedElement = expectedElements[i];
info(`Checking element #${i}: ${expectedElement.selector}`);
- const elementInView = rulesInView[i];
+ const elementInView = elementsInView[i];
if (expectedElement.header) {
is(
@@ -1447,7 +1451,7 @@ function checkRuleViewContent(view, expectedElements) {
is(
isInherited,
expectedElement.inherited ?? false,
- `Element #${i} (${selector}) is ${expectedElement.inherited ? "inherited" : "not inherited"}`
+ `Element #${i} ("${selector}") is ${expectedElement.inherited ? "inherited" : "not inherited"}`
);
const declarations = elementInView.querySelectorAll(".ruleview-property");
@@ -1483,24 +1487,24 @@ function checkRuleViewContent(view, expectedElements) {
is(
ruleViewPropertyElement.classList.contains("ruleview-overridden"),
!!expectedDeclaration?.overridden,
- `"${selector}" ${propName.innerText} is ${expectedDeclaration?.overridden ? "overridden" : "not overridden"} `
+ `Element #${i} ("${selector}") declaration #${j} ("${propName.innerText}: ${propValue.innerText}") is ${expectedDeclaration?.overridden ? "overridden" : "not overridden"} `
);
is(
!!ruleViewPropertyElement.querySelector(
".ruleview-warning:not([hidden])"
),
!!expectedDeclaration?.valid,
- `"${selector}" ${propName.innerText} is ${expectedDeclaration?.valid === false ? "not valid" : "valid"}`
+ `Element #${i} ("${selector}") declaration #${j} ("${propName.innerText}: ${propValue.innerText}") is ${expectedDeclaration?.valid === false ? "not valid" : "valid"}`
);
is(
!!ruleViewPropertyElement.hasAttribute("dirty"),
!!expectedDeclaration?.dirty,
- `"${selector}" ${propName.innerText} is ${expectedDeclaration?.dirty ? "dirty" : "not dirty"}`
+ `Element #${i} ("${selector}") declaration #${j} ("${propName.innerText}: ${propValue.innerText}") is ${expectedDeclaration?.dirty ? "dirty" : "not dirty"}`
);
is(
ruleViewPropertyElement.querySelector(".ruleview-highlight") !== null,
!!expectedDeclaration?.highlighted,
- `"${selector}" ${propName.innerText} is ${expectedDeclaration?.highlighted ? "highlighted" : "not highlighted"} `
+ `Element #${i} ("${selector}") declaration #${j} ("${propName.innerText}: ${propValue.innerText}") is ${expectedDeclaration?.highlighted ? "highlighted" : "not highlighted"} `
);
}
}