summaryrefslogtreecommitdiffstats
path: root/devtools/client/inspector/computed/test/browser_computed_matched-selectors-order.js
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--devtools/client/inspector/computed/test/browser_computed_matched-selectors-order.js889
1 files changed, 889 insertions, 0 deletions
diff --git a/devtools/client/inspector/computed/test/browser_computed_matched-selectors-order.js b/devtools/client/inspector/computed/test/browser_computed_matched-selectors-order.js
new file mode 100644
index 0000000000..b90e86a295
--- /dev/null
+++ b/devtools/client/inspector/computed/test/browser_computed_matched-selectors-order.js
@@ -0,0 +1,889 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// Tests for the order of matched selector in the computed view.
+const TEST_URI = URL_ROOT + "doc_matched_selectors.html";
+
+add_task(async function () {
+ await addTab(TEST_URI);
+ const { inspector, view } = await openComputedView();
+
+ const checkMatchedSelectors = options =>
+ checkBackgroundColorMatchedSelectors(inspector, view, options);
+
+ info("matching rules with different specificity");
+ await checkMatchedSelectors({
+ elementAttributes: {
+ id: "specificity",
+ class: "mySection",
+ },
+ style: `
+ #specificity.mySection {
+ --spec_highest: var(--winning-color);
+ background-color: var(--spec_highest);
+ }
+ #specificity {
+ background-color: var(--spec_lowest);
+ }`,
+ expectedMatchedSelectors: [
+ // Higher specificity wins
+ { selector: "#specificity.mySection", value: "var(--spec_highest)" },
+ { selector: "#specificity", value: "var(--spec_lowest)" },
+ ],
+ });
+
+ info("matching rules with same specificity");
+ await checkMatchedSelectors({
+ elementAttributes: {
+ id: "order-of-appearance",
+ },
+ style: `
+ #order-of-appearance {
+ background-color: var(--appearance-order_first);
+ }
+ #order-of-appearance {
+ --appearance-order_second: var(--winning-color);
+ background-color: var(--appearance-order_second);
+ }`,
+ expectedMatchedSelectors: [
+ // Last rule in stylesheet wins
+ {
+ selector: "#order-of-appearance",
+ value: "var(--appearance-order_second)",
+ },
+ {
+ selector: "#order-of-appearance",
+ value: "var(--appearance-order_first)",
+ },
+ ],
+ });
+
+ info("matching rules on element with style attribute");
+ await checkMatchedSelectors({
+ elementAttributes: {
+ id: "style-attr",
+ style: "background-color: var(--style-attr_in-attr)",
+ },
+ style: `
+ main {
+ --style-attr_in-attr: var(--winning-color);
+ }
+
+ #style-attr {
+ background-color: var(--style-attr_in-rule);
+ }
+ `,
+ expectedMatchedSelectors: [
+ // style attribute wins
+ { selector: "this.style", value: "var(--style-attr_in-attr)" },
+ { selector: "#style-attr", value: "var(--style-attr_in-rule)" },
+ ],
+ });
+
+ info("matching rules on different layers");
+ await checkMatchedSelectors({
+ elementAttributes: {
+ id: "layers",
+ class: "layers",
+ },
+ style: `
+ @layer second {
+ .layers {
+ --layers_in-second: var(--winning-color);
+ background-color: var(--layers_in-second);
+ }
+ }
+ @layer first {
+ #layers {
+ background-color: var(--layers_in-first);
+ }
+ }
+ `,
+ expectedMatchedSelectors: [
+ // rule in last declared layer wins
+ { selector: ".layers", value: "var(--layers_in-second)" },
+ { selector: "#layers", value: "var(--layers_in-first)" },
+ ],
+ });
+
+ info("matching rules on same layer, with same specificity");
+ await checkMatchedSelectors({
+ elementAttributes: {
+ id: "same-layers-order-of-appearance",
+ },
+ style: `
+ @layer second {
+ #same-layers-order-of-appearance {
+ background-color: var(--same-layers-appearance-order_first);
+ }
+
+ #same-layers-order-of-appearance {
+ --same-layers-appearance-order_second: var(--winning-color);
+ background-color: var(--same-layers-appearance-order_second);
+ }
+ }
+ `,
+ expectedMatchedSelectors: [
+ // last rule in the layer wins
+ {
+ selector: "#same-layers-order-of-appearance",
+ value: "var(--same-layers-appearance-order_second)",
+ },
+ {
+ selector: "#same-layers-order-of-appearance",
+ value: "var(--same-layers-appearance-order_first)",
+ },
+ ],
+ });
+
+ info("matching rules some in layers, some not");
+ await checkMatchedSelectors({
+ elementAttributes: {
+ id: "in-layer-and-no-layer",
+ },
+ style: `
+ @layer second {
+ #in-layer-and-no-layer {
+ background-color: var(--in-layer-and-no-layer_in-second);
+ }
+ }
+
+ @layer first {
+ #in-layer-and-no-layer {
+ background-color: var(--in-layer-and-no-layer_in-first);
+ }
+ }
+
+ #in-layer-and-no-layer {
+ --in-layer-and-no-layer_no-layer: var(--winning-color);
+ background-color: var(--in-layer-and-no-layer_no-layer);
+ }`,
+ expectedMatchedSelectors: [
+ // rule not in layer wins
+ {
+ selector: "#in-layer-and-no-layer",
+ value: "var(--in-layer-and-no-layer_no-layer)",
+ },
+ {
+ selector: "#in-layer-and-no-layer",
+ value: "var(--in-layer-and-no-layer_in-second)",
+ },
+ {
+ selector: "#in-layer-and-no-layer",
+ value: "var(--in-layer-and-no-layer_in-first)",
+ },
+ ],
+ });
+
+ info(
+ "matching rules with different specificity and one property declared with !important"
+ );
+ await checkMatchedSelectors({
+ elementAttributes: {
+ id: "important-specificity",
+ class: "myImportantSection",
+ },
+ style: `
+ #important-specificity.myImportantSection {
+ background-color: var(--important-spec_highest);
+ }
+ #important-specificity {
+ --important-spec_lowest-important: var(--winning-color);
+ background-color: var(--important-spec_lowest-important) !important;
+ }`,
+ expectedMatchedSelectors: [
+ // lesser specificity, but value was set with !important
+ {
+ selector: "#important-specificity",
+ value: "var(--important-spec_lowest-important)",
+ },
+ {
+ selector: "#important-specificity.myImportantSection",
+ value: "var(--important-spec_highest)",
+ },
+ ],
+ });
+
+ info(
+ "matching rules with different specificity and all properties declared with !important"
+ );
+ await checkMatchedSelectors({
+ elementAttributes: {
+ id: "all-important-specificity",
+ class: "myAllImportantSection",
+ },
+ style: `
+ #all-important-specificity.myAllImportantSection {
+ --all-important-spec_highest-important: var(--winning-color);
+ background-color: var(--all-important-spec_highest-important) !important;
+ }
+ #all-important-specificity {
+ background-color: var(--all-important-spec_lowest-important) !important;
+ }`,
+ expectedMatchedSelectors: [
+ // all values !important, so highest specificity rule wins
+ {
+ selector: "#all-important-specificity.myAllImportantSection",
+ value: "var(--all-important-spec_highest-important)",
+ },
+ {
+ selector: "#all-important-specificity",
+ value: "var(--all-important-spec_lowest-important)",
+ },
+ ],
+ });
+
+ info(
+ "matching rules with same specificity and one property declared with !important"
+ );
+ await checkMatchedSelectors({
+ elementAttributes: {
+ id: "important-order-of-appearance",
+ },
+ style: `
+ #important-order-of-appearance {
+ --important-appearance-order_first-important: var(--winning-color);
+ background-color: var(--important-appearance-order_first-important) !important;
+ }
+ #important-order-of-appearance {
+ background-color: var(--important-appearance-order_second);
+ }`,
+ expectedMatchedSelectors: [
+ // same specificity, but this value was set with !important
+ {
+ selector: "#important-order-of-appearance",
+ value: "var(--important-appearance-order_first-important)",
+ },
+ {
+ selector: "#important-order-of-appearance",
+ value: "var(--important-appearance-order_second)",
+ },
+ ],
+ });
+
+ info(
+ "matching rules with same specificity and all properties declared with !important"
+ );
+ await checkMatchedSelectors({
+ elementAttributes: {
+ id: "all-important-order-of-appearance",
+ },
+ style: `
+ #all-important-order-of-appearance {
+ background-color: var(--all-important-appearance-order_first-important) !important;
+ }
+ #all-important-order-of-appearance {
+ --all-important-appearance-order_second-important: var(--winning-color);
+ background-color: var(--all-important-appearance-order_second-important) !important;
+ }`,
+ expectedMatchedSelectors: [
+ // all values !important, so latest rule in stylesheet wins
+ {
+ selector: "#all-important-order-of-appearance",
+ value: "var(--all-important-appearance-order_second-important)",
+ },
+ {
+ selector: "#all-important-order-of-appearance",
+ value: "var(--all-important-appearance-order_first-important)",
+ },
+ ],
+ });
+
+ info(
+ "matching rules with important property on element with style attribute"
+ );
+ await checkMatchedSelectors({
+ elementAttributes: {
+ id: "important-style-attr",
+ style: "background-color: var(--important-style-attr_in-attr);",
+ },
+ style: `
+ #important-style-attr {
+ --important-style-attr_in-rule-important: var(--winning-color);
+ background-color: var(--important-style-attr_in-rule-important) !important;
+ }`,
+ expectedMatchedSelectors: [
+ // important property wins over style attribute
+ {
+ selector: "#important-style-attr",
+ value: "var(--important-style-attr_in-rule-important)",
+ },
+ { selector: "this.style", value: "var(--important-style-attr_in-attr)" },
+ ],
+ });
+
+ info(
+ "matching rules with important property on element with style attribute and important value"
+ );
+ await checkMatchedSelectors({
+ elementAttributes: {
+ id: "all-important-style-attr",
+ style:
+ "background-color: var(--all-important-style-attr_in-attr-important) !important;",
+ },
+ style: `
+ main {
+ --all-important-style-attr_in-attr-important: var(--winning-color);
+ }
+ #all-important-style-attr {
+ background-color: var(--all-important-style-attr_in-rule-important);
+ }`,
+ expectedMatchedSelectors: [
+ // both values are important, so style attribute wins
+ {
+ selector: "this.style",
+ value: "var(--all-important-style-attr_in-attr-important)",
+ },
+ {
+ selector: "#all-important-style-attr",
+ value: "var(--all-important-style-attr_in-rule-important)",
+ },
+ ],
+ });
+
+ info(
+ "matching rules on different layer, with same specificity and important values"
+ );
+ await checkMatchedSelectors({
+ elementAttributes: {
+ id: "important-layers",
+ },
+ style: `
+ @layer second {
+ #important-layers {
+ background-color: var(--important-layers_in-second);
+ }
+ }
+ @layer first {
+ #important-layers {
+ --important-layers_in-first-important: var(--winning-color);
+ background-color: var(--important-layers_in-first-important) !important;
+ }
+ }`,
+ expectedMatchedSelectors: [
+ // rule with important property wins
+ {
+ selector: "#important-layers",
+ value: "var(--important-layers_in-first-important)",
+ },
+ {
+ selector: "#important-layers",
+ value: "var(--important-layers_in-second)",
+ },
+ ],
+ });
+
+ info(
+ "matching rules on different layer, with same specificity and all important values"
+ );
+ await checkMatchedSelectors({
+ elementAttributes: {
+ id: "all-important-layers",
+ },
+ style: `
+ @layer second {
+ #all-important-layers {
+ background-color: var(--all-important-layers_in-second-important) !important;
+ }
+ }
+ @layer first {
+ #all-important-layers {
+ --all-important-layers_in-first-important: var(--winning-color);
+ background-color: var(--all-important-layers_in-first-important) !important;
+ }
+ }`,
+ expectedMatchedSelectors: [
+ // all properties are important, rule from first declared layer wins
+ {
+ selector: "#all-important-layers",
+ value: "var(--all-important-layers_in-first-important)",
+ },
+ {
+ selector: "#all-important-layers",
+ value: "var(--all-important-layers_in-second-important)",
+ },
+ ],
+ });
+
+ info(
+ "matching rules on same layer, with same specificity and important values"
+ );
+ await checkMatchedSelectors({
+ elementAttributes: {
+ id: "important-same-layers-order-of-appearance",
+ },
+ style: `
+ @layer second {
+ #important-same-layers-order-of-appearance {
+ --important-same-layers-appearance-order_first-important: var(--winning-color);
+ background-color: var(--important-same-layers-appearance-order_first-important) !important;
+ }
+
+ #important-same-layers-order-of-appearance {
+ background-color: var(--important-same-layers-appearance-order_second);
+ }
+ }`,
+ expectedMatchedSelectors: [
+ // rule with important property wins
+ {
+ selector: "#important-same-layers-order-of-appearance",
+ value: "var(--important-same-layers-appearance-order_first-important)",
+ },
+ {
+ selector: "#important-same-layers-order-of-appearance",
+ value: "var(--important-same-layers-appearance-order_second)",
+ },
+ ],
+ });
+
+ info(
+ "matching rules on same layer, with same specificity and all important values"
+ );
+ await checkMatchedSelectors({
+ elementAttributes: {
+ id: "all-important-same-layers-order-of-appearance",
+ },
+ style: `
+ @layer second {
+ #all-important-same-layers-order-of-appearance {
+ background-color: var(--all-important-same-layers-appearance-order_first-important) !important;
+ }
+
+ #all-important-same-layers-order-of-appearance {
+ --all-important-same-layers-appearance-order_second-important: var(--winning-color);
+ background-color: var(--all-important-same-layers-appearance-order_second-important) !important;
+ }
+ }`,
+ expectedMatchedSelectors: [
+ // last rule with important property wins
+ {
+ selector: "#all-important-same-layers-order-of-appearance",
+ value:
+ "var(--all-important-same-layers-appearance-order_second-important)",
+ },
+ {
+ selector: "#all-important-same-layers-order-of-appearance",
+ value:
+ "var(--all-important-same-layers-appearance-order_first-important)",
+ },
+ ],
+ });
+
+ info("matching rules ,some in layers, some not, important values in layers");
+ await checkMatchedSelectors({
+ elementAttributes: {
+ id: "important-in-layer-and-no-layer",
+ },
+ style: `
+ @layer second {
+ #important-in-layer-and-no-layer {
+ background-color: var(--important-in-layer-and-no-layer_in-second);
+ }
+ }
+
+ @layer first {
+ #important-in-layer-and-no-layer {
+ --important-in-layer-and-no-layer_in-first-important: var(--winning-color);
+ background-color: var(--important-in-layer-and-no-layer_in-first-important) !important;
+ }
+ }
+
+ #important-in-layer-and-no-layer {
+ background-color: var(--important-in-layer-and-no-layer_no-layer);
+ }`,
+ expectedMatchedSelectors: [
+ // rule with important property wins
+ {
+ selector: "#important-in-layer-and-no-layer",
+ value: "var(--important-in-layer-and-no-layer_in-first-important)",
+ },
+ // then rule not in layer
+ {
+ selector: "#important-in-layer-and-no-layer",
+ value: "var(--important-in-layer-and-no-layer_no-layer)",
+ },
+ {
+ selector: "#important-in-layer-and-no-layer",
+ value: "var(--important-in-layer-and-no-layer_in-second)",
+ },
+ ],
+ });
+
+ info("matching rules ,some in layers, some not, all important values");
+ await checkMatchedSelectors({
+ elementAttributes: {
+ id: "all-important-in-layer-and-no-layer",
+ },
+ style: `
+ @layer second {
+ #all-important-in-layer-and-no-layer {
+ background-color: var(--all-important-in-layer-and-no-layer_in-second-important) !important;
+ }
+ }
+
+ @layer first {
+ #all-important-in-layer-and-no-layer {
+ --all-important-in-layer-and-no-layer_in-first-important: var(--winning-color);
+ background-color: var(--all-important-in-layer-and-no-layer_in-first-important) !important;
+ }
+ }
+
+ #all-important-in-layer-and-no-layer {
+ background-color: var(--all-important-in-layer-and-no-layer_no-layer-important) !important;
+ }`,
+ expectedMatchedSelectors: [
+ // important properties in first declared layer wins
+ {
+ selector: "#all-important-in-layer-and-no-layer",
+ value: "var(--all-important-in-layer-and-no-layer_in-first-important)",
+ },
+ // then following important rules in layers
+ {
+ selector: "#all-important-in-layer-and-no-layer",
+ value: "var(--all-important-in-layer-and-no-layer_in-second-important)",
+ },
+ // then important rules not in layers
+ {
+ selector: "#all-important-in-layer-and-no-layer",
+ value: "var(--all-important-in-layer-and-no-layer_no-layer-important)",
+ },
+ ],
+ });
+
+ info(
+ "matching rules ,some in layers, some not, and style attribute all important values"
+ );
+ await checkMatchedSelectors({
+ elementAttributes: {
+ id: "all-important-in-layer-no-layer-style-attr",
+ style:
+ "background-color: var(--all-important-in-layer-no-layer-style-attr_in-attr-important) !important",
+ },
+ style: `
+ main {
+ --all-important-in-layer-no-layer-style-attr_in-attr-important: var(--winning-color);
+ }
+
+ @layer second {
+ #all-important-in-layer-no-layer-style-attr {
+ background-color: var(--all-important-in-layer-no-layer-style-attr_in-second-important) !important;
+ }
+ }
+
+ @layer first {
+ #all-important-in-layer-no-layer-style-attr {
+ background-color: var(--all-important-in-layer-no-layer-style-attr_in-first-important) !important;
+ }
+ }
+
+ #all-important-in-layer-no-layer-style-attr {
+ background-color: var(--all-important-in-layer-no-layer-style-attr_no-layer-important) !important;
+ }`,
+ expectedMatchedSelectors: [
+ // important properties in style attribute wins
+ {
+ selector: "this.style",
+ value:
+ "var(--all-important-in-layer-no-layer-style-attr_in-attr-important)",
+ },
+ // then important property in first declared layer
+ {
+ selector: "#all-important-in-layer-no-layer-style-attr",
+ value:
+ "var(--all-important-in-layer-no-layer-style-attr_in-first-important)",
+ },
+ // then following important property in layers
+ {
+ selector: "#all-important-in-layer-no-layer-style-attr",
+ value:
+ "var(--all-important-in-layer-no-layer-style-attr_in-second-important)",
+ },
+ // then important property not in layers
+ {
+ selector: "#all-important-in-layer-no-layer-style-attr",
+ value:
+ "var(--all-important-in-layer-no-layer-style-attr_no-layer-important)",
+ },
+ ],
+ });
+
+ info(
+ "matching rules on same layer but different rules and all important values"
+ );
+ await checkMatchedSelectors({
+ elementAttributes: {
+ id: "all-important-same-layer-different-rule",
+ },
+ style: `
+ @layer first {
+ #all-important-same-layer-different-rule {
+ background-color: var(--all-important-same-layer-different-rule_first-important) !important;
+ }
+ }
+
+ @layer first {
+ #all-important-same-layer-different-rule {
+ --all-important-same-layer-different-rule_second-important: var(--winning-color);
+ background-color: var(--all-important-same-layer-different-rule_second-important) !important;
+ }
+ }`,
+ expectedMatchedSelectors: [
+ // last rule for the layer with important property wins
+ {
+ selector: "#all-important-same-layer-different-rule",
+ value:
+ "var(--all-important-same-layer-different-rule_second-important)",
+ },
+ {
+ selector: "#all-important-same-layer-different-rule",
+ value: "var(--all-important-same-layer-different-rule_first-important)",
+ },
+ ],
+ });
+
+ info(
+ "matching rules on same layer but different nested rules and all important values"
+ );
+ await checkMatchedSelectors({
+ elementAttributes: {
+ id: "all-important-same-nested-layer-different-rule",
+ },
+ style: `
+ @layer first {
+ @layer {
+ @layer second {
+ #all-important-same-nested-layer-different-rule {
+ background-color: var(--all-important-same-nested-layer-different-rule_first-important) !important;
+ }
+ }
+
+ @layer second {
+ #all-important-same-nested-layer-different-rule {
+ --all-important-same-nested-layer-different-rule_second-important: var(--winning-color);
+ background-color: var(--all-important-same-nested-layer-different-rule_second-important) !important;
+ }
+ }
+ }
+ }`,
+ expectedMatchedSelectors: [
+ // last rule for the layer with important property wins
+ {
+ selector: "#all-important-same-nested-layer-different-rule",
+ value:
+ "var(--all-important-same-nested-layer-different-rule_second-important)",
+ },
+ {
+ selector: "#all-important-same-nested-layer-different-rule",
+ value:
+ "var(--all-important-same-nested-layer-different-rule_first-important)",
+ },
+ ],
+ });
+
+ info("matching rules on different nameless layers and all important values");
+ await checkMatchedSelectors({
+ elementAttributes: {
+ id: "all-important-different-nameless-layers",
+ },
+ style: `
+ @layer {
+ @layer first {
+ #all-important-different-nameless-layers {
+ --all-important-different-nameless-layers_first-important: var(--winning-color);
+ background-color: var(--all-important-different-nameless-layers_first-important) !important;
+ }
+ }
+ }
+ @layer {
+ @layer first {
+ #all-important-different-nameless-layers {
+ background-color: var(--all-important-different-nameless-layers_second-important) !important;
+ }
+ }
+ }`,
+ expectedMatchedSelectors: [
+ // rule with important property in first declared layer wins
+ {
+ selector: "#all-important-different-nameless-layers",
+ value: "var(--all-important-different-nameless-layers_first-important)",
+ },
+ {
+ selector: "#all-important-different-nameless-layers",
+ value:
+ "var(--all-important-different-nameless-layers_second-important)",
+ },
+ ],
+ });
+
+ info("matching rules on different imported layers");
+ // no provided style as rules are defined in doc_matched_selectors_imported_*.css
+ await checkMatchedSelectors({
+ elementAttributes: {
+ id: "imported-layers",
+ },
+ expectedMatchedSelectors: [
+ // rule in last declared layer wins
+ {
+ selector: "#imported-layers",
+ value: "var(--imported-layers_in-anonymous-second)",
+ },
+ {
+ selector: "#imported-layers",
+ value: "var(--imported-layers_in-nested-importedSecond)",
+ },
+ {
+ selector: "#imported-layers",
+ value: "var(--imported-layers_in-anonymous-first)",
+ },
+ {
+ selector: "#imported-layers",
+ value: "var(--imported-layers_in-importedSecond)",
+ },
+ {
+ selector: "#imported-layers",
+ value: "var(--imported-layers_in-importedFirst-second)",
+ },
+ {
+ selector: "#imported-layers",
+ value: "var(--imported-layers_in-importedFirst-first)",
+ },
+ ],
+ });
+
+ info("matching rules on different imported layers all with important values");
+ // no provided style as rules are defined in doc_matched_selectors_imported_*.css
+ await checkMatchedSelectors({
+ elementAttributes: {
+ id: "all-important-imported-layers",
+ },
+ expectedMatchedSelectors: [
+ // last important property in first declared layer wins
+ {
+ selector: "#all-important-imported-layers",
+ value:
+ "var(--all-important-imported-layers_in-importedFirst-second-important)",
+ },
+ // then earlier important property for first declared layer
+ {
+ selector: "#all-important-imported-layers",
+ value:
+ "var(--all-important-imported-layers_in-importedFirst-first-important)",
+ },
+ {
+ selector: "#all-important-imported-layers",
+ value:
+ "var(--all-important-imported-layers_in-importedSecond-important)",
+ },
+ {
+ selector: "#all-important-imported-layers",
+ value:
+ "var(--all-important-imported-layers_in-anonymous-first-important)",
+ },
+ {
+ selector: "#all-important-imported-layers",
+ value:
+ "var(--all-important-imported-layers_in-nested-importedSecond-important)",
+ },
+ {
+ selector: "#all-important-imported-layers",
+ value:
+ "var(--all-important-imported-layers_in-anonymous-second-important)",
+ },
+ ],
+ });
+});
+
+async function checkBackgroundColorMatchedSelectors(
+ inspector,
+ view,
+ { elementAttributes, style, expectedMatchedSelectors }
+) {
+ const elementId = await SpecialPowers.spawn(
+ gBrowser.selectedBrowser,
+ [elementAttributes, style],
+ (attr, _style) => {
+ const sectionEl = content.document.createElement("section");
+ for (const [name, value] of Object.entries(attr)) {
+ sectionEl.setAttribute(name, value);
+ }
+
+ if (_style) {
+ const styleEl = content.document.createElement("style");
+ styleEl.innerText = _style;
+ styleEl.setAttribute("id", `style-${sectionEl.id}`);
+ content.document.head.append(styleEl);
+ }
+ content.document.querySelector("main").append(sectionEl);
+
+ return sectionEl.id;
+ }
+ );
+ const selector = `#${elementId}`;
+ await selectNode(selector, inspector);
+
+ const bgColorComputedValue = await getComputedStyleProperty(
+ selector,
+ null,
+ "background-color"
+ );
+ is(
+ bgColorComputedValue,
+ "rgb(0, 0, 255)",
+ `The created element does have a "blue" background-color`
+ );
+
+ const propertyView = getPropertyView(view, "background-color");
+ ok(propertyView, "found PropertyView for background-color");
+ const valueNode = propertyView.valueNode.querySelector(".computed-color");
+ is(
+ valueNode.textContent,
+ "rgb(0, 0, 255)",
+ `The displayed computed value is the expected "blue"`
+ );
+
+ is(propertyView.hasMatchedSelectors, true, "hasMatchedSelectors is true");
+
+ info("Expanding the matched selectors");
+ propertyView.matchedExpanded = true;
+ await propertyView.refreshMatchedSelectors();
+
+ const selectorsEl =
+ propertyView.matchedSelectorsContainer.querySelectorAll(".rule-text");
+ is(
+ selectorsEl.length,
+ expectedMatchedSelectors.length,
+ "Expected number of selectors are displayed"
+ );
+
+ selectorsEl.forEach((selectorEl, index) => {
+ is(
+ selectorEl.querySelector(".fix-get-selection").innerText,
+ expectedMatchedSelectors[index].selector,
+ `Selector #${index} is the expected one`
+ );
+ is(
+ selectorEl.querySelector(".computed-other-property-value").innerText,
+ expectedMatchedSelectors[index].value,
+ `Selector #${index} has the expected background color`
+ );
+ const classToMatch = index === 0 ? "bestmatch" : "matched";
+ ok(
+ selectorEl.classList.contains(classToMatch),
+ `selector element has expected "${classToMatch}" class`
+ );
+ });
+
+ // cleanup
+ await SpecialPowers.spawn(gBrowser.selectedBrowser, [elementId], id => {
+ // Remove added element and stylesheet
+ content.document.getElementById(id).remove();
+ // Some test cases don't insert a style element
+ content.document.getElementById(`style-${id}`)?.remove();
+ });
+}
+
+function getPropertyView(computedView, name) {
+ return computedView.propertyViews.find(view => view.name === name);
+}