/* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ "use strict"; // Test that the rule-view properly handles @starting-style rules. const TEST_URI = `

Hello @starting-style!

Testing override
`; add_task(async function () { await pushPref("layout.css.starting-style-at-rules.enabled", true); await addTab( "https://example.com/document-builder.sjs?html=" + encodeURIComponent(TEST_URI) ); const { inspector, view } = await openRuleView(); await assertRules("body", [ { selector: `element`, ancestorRulesData: null }, { selector: `body, [data-test="in-starting-style"]`, ancestorRulesData: ["@starting-style {"], }, { selector: `body, [data-test="in-starting-style-layer"]`, ancestorRulesData: ["@starting-style {", " @layer {"], }, ]); await assertRules("h1", [ { selector: `element`, ancestorRulesData: null }, { selector: `h1, [data-test="in-starting-style"]`, ancestorRulesData: ["@starting-style {"], }, { selector: ``, ancestorRulesData: [ `h1, [data-test="top-level"] {`, " @starting-style {", ], }, { selector: `h1, [data-test="top-level"]`, ancestorRulesData: null, }, ]); await assertRules("main", [ { selector: `element`, ancestorRulesData: null }, { selector: ``, ancestorRulesData: [ `main, [data-test="top-level"] {`, " @starting-style {", ], }, { selector: `main, [data-test="top-level"]`, ancestorRulesData: null, }, { selector: `main, [data-test="in-starting-style"]`, ancestorRulesData: ["@starting-style {"], }, { selector: `main, [data-test="in-starting-style-layer-2"]`, ancestorRulesData: [`@starting-style {`, " @layer {"], }, { selector: `main, [data-test="in-starting-style-layer"]`, ancestorRulesData: [`@starting-style {`, " @layer {"], }, ]); 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" ); ok( !isPropertyOverridden(view, 2, { "--my-color": "white" }), "--my-color value in top level rule is not overridden" ); info( "Check var() in regular rule for a variable set in both regular and starting-style rule" ); await assertVariableTooltipForProperty( view, `main, [data-test="top-level"]`, "color", { header: // prettier-ignore '' + '' + '' + 'white' + '', // Computed value isn't displayed when it's the same as we put in the header computed: null, // The starting-style value is displayed in the tooltip startingStyle: // prettier-ignore '' + '' + '' + 'black' + '', } ); info( "Check var() in starting-style rule for a variable set in both regular and starting-style rule" ); await assertVariableTooltipForProperty( view, `main, [data-test="in-starting-style"]`, "--check-my-color", { // The displayed value is the one set in the starting-style rule header: // prettier-ignore '' + '' + '' + 'black' + '', // Computed value isn't displayed in starting-style rule computed: null, // The starting-style section is not displayed when hovering starting-style rule startingStyle: null, } ); info( "Check var() in both regular and starting-style rule for a variable overridden in regular rule" ); ok( isPropertyOverridden(view, 3, { "--my-overridden-color": "black" }), "--my-overridden-color in top-level starting style rule is overridden" ); await assertVariableTooltipForProperty( view, `main, [data-test="top-level"]`, "--check-my-overridden-color", { header: // prettier-ignore '' + '' + '' + 'white' + '', computed: // prettier-ignore '' + '' + '' + 'white' + '', // The starting-style rule is overridden, so we don't show a starting-style section in the tooltip startingStyle: null, } ); await assertVariableTooltipForProperty( view, `main, [data-test="in-starting-style"]`, "--check-my-overridden-color", { // the value is the one from the regular rule, not the one from the starting-style rule header: // prettier-ignore '' + '' + '' + 'white' + '', // Computed value isn't displayed in starting-style rule computed: null, startingStyle: null, } ); info( "Check var() for a registered property in both regular and starting-style rule" ); await assertVariableTooltipForProperty( view, `main, [data-test="top-level"]`, "--check-my-registered-color", { header: // prettier-ignore '' + '' + '' + 'white' + '', computed: // prettier-ignore '' + '' + '' + 'rgb(255, 255, 255)' + '', // The starting-style value is displayed in the tooltip startingStyle: // prettier-ignore '' + '' + '' + 'black' + '', // registered property data is displayed registeredProperty: { syntax: `"<color>"`, inherits: "true", "initial-value": // prettier-ignore `` + `` + `` + `blue` + ``, }, } ); await assertVariableTooltipForProperty( view, `main, [data-test="in-starting-style"]`, "--check-my-registered-color", { // The displayed value is the one set in the starting-style rule header: // prettier-ignore '' + '' + '' + 'black' + '', // Computed value isn't displayed in starting-style rule computed: null, // The starting-style section is not displayed when hovering starting-style rule startingStyle: null, // registered property data is displayed registeredProperty: { syntax: `"<color>"`, inherits: "true", "initial-value": // prettier-ignore `` + `` + `` + `blue` + ``, }, } ); info("Check var() for a unset registered property in starting-style rule"); await assertVariableTooltipForProperty( view, `main, [data-test="in-starting-style"]`, "--check-my-unset-registered-color", { // The displayed value is the registered property initial value header: // prettier-ignore '' + '' + '' + 'lavender' + '', // The starting-style section is not displayed when hovering starting-style rule startingStyle: null, // registered property data is displayed registeredProperty: { syntax: `"<color>"`, inherits: "true", "initial-value": // prettier-ignore '' + '' + '' + 'lavender' + '', }, } ); info("Check var() for a empty variable in regular rule"); await assertVariableTooltipForProperty( view, `main, [data-test="top-level"]`, "--check-empty-start", { header: "1px", // The starting-style value is displayed in the tooltip startingStyle: "<empty>", 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) { return getTextProperty( view, ruleIndex, property ).editor.element.classList.contains("ruleview-overridden"); }