commit b288184a7e1cfb3718e65a018a01b107544f58bb
parent 7d882b5945badae6f14190c03afdd3000d0df4a2
Author: Nicolas Chevobbe <nchevobbe@mozilla.com>
Date: Thu, 20 Nov 2025 12:46:05 +0000
Bug 2001050 - [devtools] Assert unmatched selectors in checkRuleViewContent. r=devtools-reviewers,bomsy.
From the callsites, unmatched selectors are passed wrapped in `~~` (like in markdown
to strike through words)
Differential Revision: https://phabricator.services.mozilla.com/D273180
Diffstat:
5 files changed, 43 insertions(+), 27 deletions(-)
diff --git a/devtools/client/inspector/rules/test/browser_rules_at_scope.js b/devtools/client/inspector/rules/test/browser_rules_at_scope.js
@@ -55,7 +55,7 @@ add_task(async function () {
await checkRuleViewContent(view, [
{ selector: `element`, ancestorRulesData: null, declarations: [] },
{
- selector: `:scope, [data-test="scoped-inline-style"]`,
+ selector: `:scope, ~~[data-test="scoped-inline-style"]~~`,
ancestorRulesData: ["@scope {"],
declarations: [{ name: "border", value: "1px solid aqua" }],
},
@@ -65,7 +65,7 @@ add_task(async function () {
await checkRuleViewContent(view, [
{ selector: `element`, ancestorRulesData: null, declarations: [] },
{
- selector: `div, [data-test="scoped-inline-style"]`,
+ selector: `div, ~~[data-test="scoped-inline-style"]~~`,
ancestorRulesData: ["@scope {"],
declarations: [{ name: "background", value: "tomato" }],
},
@@ -75,7 +75,7 @@ add_task(async function () {
await checkRuleViewContent(view, [
{ selector: `element`, ancestorRulesData: null, declarations: [] },
{
- selector: `:scope, [data-test="nested-scoped-inline-style"]`,
+ selector: `:scope, ~~[data-test="nested-scoped-inline-style"]~~`,
ancestorRulesData: ["@scope {", " @scope (:scope section) {"],
declarations: [
{ name: "background", value: "gold" },
@@ -89,17 +89,17 @@ add_task(async function () {
await checkRuleViewContent(view, [
{ selector: `element`, ancestorRulesData: null, declarations: [] },
{
- selector: `div, [data-test="start-and-end-inherit"]`,
+ selector: `div, ~~[data-test="start-and-end-inherit"]~~`,
ancestorRulesData: ["@scope (aside) to (.limit) {"],
declarations: [{ name: "color", value: "salmon" }],
},
{
- selector: `div, [data-test="start-and-end"]`,
+ selector: `div, ~~[data-test="start-and-end"]~~`,
ancestorRulesData: ["@scope (aside) to (.limit) {"],
declarations: [{ name: "outline", value: "2px solid gold" }],
},
{
- selector: `div, [data-test="start-no-end"]`,
+ selector: `div, ~~[data-test="start-no-end"]~~`,
ancestorRulesData: ["@scope (aside) {"],
declarations: [{ name: "box-shadow", value: "60px -16px teal" }],
},
@@ -120,7 +120,7 @@ add_task(async function () {
header: "Inherited from div#b",
},
{
- selector: `div, [data-test="start-and-end-inherit"]`,
+ selector: `div, ~~[data-test="start-and-end-inherit"]~~`,
ancestorRulesData: ["@scope (aside) to (.limit) {"],
inherited: true,
declarations: [{ name: "color", value: "salmon", overridden: true }],
@@ -131,7 +131,7 @@ add_task(async function () {
await checkRuleViewContent(view, [
{ selector: `element`, ancestorRulesData: null, declarations: [] },
{
- selector: `div, [data-test="start-no-end"]`,
+ selector: `div, ~~[data-test="start-no-end"]~~`,
ancestorRulesData: ["@scope (aside) {"],
declarations: [{ name: "box-shadow", value: "60px -16px teal" }],
},
@@ -139,7 +139,7 @@ add_task(async function () {
header: "Inherited from div#b",
},
{
- selector: `div, [data-test="start-and-end-inherit"]`,
+ selector: `div, ~~[data-test="start-and-end-inherit"]~~`,
ancestorRulesData: ["@scope (aside) to (.limit) {"],
inherited: true,
declarations: [{ name: "color", value: "salmon" }],
@@ -153,7 +153,7 @@ add_task(async function () {
header: "Inherited from div#b",
},
{
- selector: `div, [data-test="start-and-end-inherit"]`,
+ selector: `div, ~~[data-test="start-and-end-inherit"]~~`,
ancestorRulesData: ["@scope (aside) to (.limit) {"],
inherited: true,
declarations: [{ name: "color", value: "salmon" }],
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
@@ -118,12 +118,12 @@ add_task(async function () {
await checkRuleViewContent(view, [
{ selector: `element`, ancestorRulesData: null, declarations: [] },
{
- selector: `body, [data-test="in-starting-style"]`,
+ selector: `body, ~~[data-test="in-starting-style"]~~`,
ancestorRulesData: ["@starting-style {"],
declarations: [{ name: "color", value: "navy" }],
},
{
- selector: `body, [data-test="in-starting-style-layer"]`,
+ selector: `body, ~~[data-test="in-starting-style-layer"]~~`,
ancestorRulesData: ["@starting-style {", " @layer {"],
declarations: [{ name: "color", value: "hotpink", overridden: true }],
},
@@ -134,7 +134,7 @@ add_task(async function () {
await checkRuleViewContent(view, [
{ selector: `element`, ancestorRulesData: null, declarations: [] },
{
- selector: `h1, [data-test="in-starting-style"]`,
+ selector: `h1, ~~[data-test="in-starting-style"]~~`,
ancestorRulesData: ["@starting-style {"],
declarations: [{ name: "background-color", value: "salmon" }],
},
@@ -147,7 +147,7 @@ add_task(async function () {
declarations: [{ name: "color", value: "gold" }],
},
{
- selector: `h1, [data-test="top-level"]`,
+ selector: `h1, ~~[data-test="top-level"]~~`,
ancestorRulesData: null,
declarations: [
{ name: "color", value: "tomato" },
@@ -198,7 +198,7 @@ add_task(async function () {
],
},
{
- selector: `main, [data-test="top-level"]`,
+ selector: `main, ~~[data-test="top-level"]~~`,
ancestorRulesData: null,
declarations: [
{ name: "--my-color", value: "white" },
@@ -247,7 +247,7 @@ add_task(async function () {
],
},
{
- selector: `main, [data-test="in-starting-style"]`,
+ selector: `main, ~~[data-test="in-starting-style"]~~`,
ancestorRulesData: ["@starting-style {"],
declarations: [
{ name: "--my-color", value: "black !important" },
@@ -296,7 +296,7 @@ add_task(async function () {
],
},
{
- selector: `main, [data-test="in-starting-style-layer-2"]`,
+ selector: `main, ~~[data-test="in-starting-style-layer-2"]~~`,
ancestorRulesData: [`@starting-style {`, " @layer {"],
declarations: [
{
@@ -327,7 +327,7 @@ add_task(async function () {
],
},
{
- selector: `main, [data-test="in-starting-style-layer"]`,
+ selector: `main, ~~[data-test="in-starting-style-layer"]~~`,
ancestorRulesData: [`@starting-style {`, " @layer {"],
declarations: [
{
diff --git a/devtools/client/inspector/rules/test/browser_rules_inherited-custom-properties.js b/devtools/client/inspector/rules/test/browser_rules_inherited-custom-properties.js
@@ -63,12 +63,12 @@ add_task(async function () {
},
{ header: "Inherited from main" },
{
- selector: `main, [test="unregistered"]`,
+ selector: `main, ~~[test="unregistered"]~~`,
inherited: true,
declarations: [{ name: "--myvar", value: "brown" }],
},
{
- selector: `main, [test="inherit"]`,
+ selector: `main, ~~[test="inherit"]~~`,
inherited: true,
declarations: [{ name: "--inherit", value: "red" }],
},
diff --git a/devtools/client/inspector/rules/test/browser_rules_pseudo-element_02.js b/devtools/client/inspector/rules/test/browser_rules_pseudo-element_02.js
@@ -326,7 +326,7 @@ add_task(async function () {
await selectNode(viewTransitionOldNodeFront, inspector);
checkRuleViewContent(view, [
{
- selector: `::view-transition-old(root), ::view-transition-new(root)`,
+ selector: `::view-transition-old(root), ~~::view-transition-new(root)~~`,
declarations: [
{ name: "animation-duration", value: `1000s` },
{ name: "top", value: `1em` },
@@ -367,7 +367,7 @@ add_task(async function () {
],
},
{
- selector: `::view-transition-old(root), ::view-transition-new(root)`,
+ selector: `~~::view-transition-old(root)~~, ::view-transition-new(root)`,
declarations: [
{ name: "animation-duration", value: `1000s`, overridden: true },
{
diff --git a/devtools/client/inspector/rules/test/head.js b/devtools/client/inspector/rules/test/head.js
@@ -1369,7 +1369,8 @@ function getSmallIncrementKey() {
*
* @param {RuleView} view
* @param {object[]} expectedElements
- * @param {string} expectedElements[].selector - The expected selector of the rule.
+ * @param {string} expectedElements[].selector - The expected selector of the rule. Wrap
+ * unmatched selector with `~~` characters (e.g. "div, ~~unmatched~~")
* @param {string[]|null} expectedElements[].ancestorRulesData - An array of the parent
* selectors of the rule, with their indentations and the opening brace.
* e.g. for the following rule `html { body { span {} } }`, for the `span` rule,
@@ -1425,10 +1426,25 @@ function checkRuleViewContent(view, expectedElements) {
return;
}
- const selector = elementInView.querySelector(
- ".ruleview-selectors-container"
- ).innerText;
- is(selector, expectedElement.selector, `Expected selector for ${selector}`);
+ const selector = [
+ ...elementInView.querySelectorAll(
+ // Get the selector parts (.ruleview-selector), as well as the `element` "fake" selector
+ ".ruleview-selectors-container .ruleview-selector, .ruleview-selectors-container.alternative-selector"
+ ),
+ ]
+ .map(selectorEl => {
+ let selectorPart = selectorEl.textContent;
+ if (selectorEl.classList.contains("unmatched")) {
+ selectorPart = `~~${selectorPart}~~`;
+ }
+ return selectorPart;
+ })
+ .join(", ");
+ is(
+ selector,
+ expectedElement.selector,
+ `Expected selector for element #${i}`
+ );
const ancestorData = elementInView.querySelector(
`.ruleview-rule-ancestor-data`