diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 00:47:55 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 00:47:55 +0000 |
commit | 26a029d407be480d791972afb5975cf62c9360a6 (patch) | |
tree | f435a8308119effd964b339f76abb83a57c29483 /devtools/client/inspector/rules/test/browser_rules_registered-custom-properties.js | |
parent | Initial commit. (diff) | |
download | firefox-26a029d407be480d791972afb5975cf62c9360a6.tar.xz firefox-26a029d407be480d791972afb5975cf62c9360a6.zip |
Adding upstream version 124.0.1.upstream/124.0.1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r-- | devtools/client/inspector/rules/test/browser_rules_registered-custom-properties.js | 490 |
1 files changed, 490 insertions, 0 deletions
diff --git a/devtools/client/inspector/rules/test/browser_rules_registered-custom-properties.js b/devtools/client/inspector/rules/test/browser_rules_registered-custom-properties.js new file mode 100644 index 0000000000..106ad6d412 --- /dev/null +++ b/devtools/client/inspector/rules/test/browser_rules_registered-custom-properties.js @@ -0,0 +1,490 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +// Tests that registed custom properties (@property/Css.registerProperty) are displayed +// in a dedicated section and that they are properly reflected in the `var()` popup. + +const CSS_NO_INHERIT_INITIAL_VALUE = "tomato"; +const CSS_INHERIT_INITIAL_VALUE = "gold"; +const CSS_NOT_DEFINED_INITIAL_VALUE = "purple"; +const JS_NO_INHERIT_INITIAL_VALUE = "42px"; + +const CSS_NO_INHERIT_MAIN_VALUE = "#0000FF"; +const CSS_INHERIT_MAIN_VALUE = "#FF0000"; +const JS_NO_INHERIT_MAIN_VALUE = "100%"; +const JS_INHERIT_MAIN_VALUE = "50vw"; + +const TEST_URI = `https://example.org/document-builder.sjs?html=${encodeURIComponent(` + <script> + CSS.registerProperty({ + name: "--js-no-inherit", + syntax: "<length>", + inherits: false, + initialValue: "${JS_NO_INHERIT_INITIAL_VALUE}", + }); + CSS.registerProperty({ + name: "--js-inherit", + syntax: "*", + inherits: true, + }); + </script> + <style> + @property --css-no-inherit { + syntax: "<color>"; + inherits: false; + initial-value: ${CSS_NO_INHERIT_INITIAL_VALUE}; + } + + @property --css-inherit { + syntax: "<color>"; + inherits: true; + initial-value: ${CSS_INHERIT_INITIAL_VALUE}; + } + + @property --css-not-defined { + syntax: "<color>"; + inherits: true; + initial-value: ${CSS_NOT_DEFINED_INITIAL_VALUE}; + } + + main { + --js-no-inherit: ${JS_NO_INHERIT_MAIN_VALUE}; + --js-inherit: ${JS_INHERIT_MAIN_VALUE}; + --css-no-inherit: ${CSS_NO_INHERIT_MAIN_VALUE}; + --css-inherit: ${CSS_INHERIT_MAIN_VALUE}; + } + + h1 { + background-color: var(--css-no-inherit); + color: var(--css-inherit); + border-color: var(--css-not-defined); + height: var(--js-no-inherit); + width: var(--js-inherit); + outline: 10px solid var(--constructed, green); + text-decoration-color: var(--js-not-defined, blue); + caret-color: var(--css-dynamic-registered, turquoise); + } + </style> + <main> + <h1>Hello world</h1> + <iframe src="https://example.com/document-builder.sjs?html=iframe"></iframe> + </main> +`)}`; + +add_task(async function () { + await pushPref("layout.css.properties-and-values.enabled", true); + const tab = await addTab(TEST_URI); + const { inspector, view } = await openRuleView(); + const doc = view.styleDocument; + await selectNode("h1", inspector); + + info("Check the content of the @property section"); + is( + doc.querySelector(".ruleview-expandable-header").textContent, + "@property", + "The @property section header is displayed" + ); + const registeredPropertiesContainer = doc.getElementById( + "registered-properties-container" + ); + ok(!!registeredPropertiesContainer, "The @property container is displayed"); + + const expectedProperties = [ + { + header: `--css-inherit {`, + propertyDefinition: [ + ` syntax: "<color>";`, + ` inherits: true;`, + ` initial-value: ${CSS_INHERIT_INITIAL_VALUE};`, + ], + }, + { + header: `--css-no-inherit {`, + propertyDefinition: [ + ` syntax: "<color>";`, + ` inherits: false;`, + ` initial-value: ${CSS_NO_INHERIT_INITIAL_VALUE};`, + ], + }, + { + header: `--css-not-defined {`, + propertyDefinition: [ + ` syntax: "<color>";`, + ` inherits: true;`, + ` initial-value: ${CSS_NOT_DEFINED_INITIAL_VALUE};`, + ], + }, + { + header: `--js-inherit {`, + propertyDefinition: [ + ` name: "--js-inherit",`, + ` syntax: "*",`, + ` inherits: true,`, + ], + }, + { + header: `--js-no-inherit {`, + propertyDefinition: [ + ` name: "--js-no-inherit",`, + ` syntax: "<length>",`, + ` inherits: false,`, + ` initialValue: "${JS_NO_INHERIT_INITIAL_VALUE}",`, + ], + }, + ]; + + checkRegisteredProperties(view, expectedProperties); + + info("Check that var() tooltips handle registered properties"); + await checkVariableTooltipForProperty( + view, + "h1", + "background-color", + // The variable value is the initial value since the variable does not inherit + `--css-no-inherit = ${CSS_NO_INHERIT_INITIAL_VALUE}` + ); + await checkVariableTooltipForProperty( + view, + "h1", + "color", + // The variable value is the value set in the main selector, since the variable does inherit + `--css-inherit = ${CSS_INHERIT_MAIN_VALUE}` + ); + await checkVariableTooltipForProperty( + view, + "h1", + "border-color", + // The variable value is the initial value since the variable is not set + `--css-not-defined = ${CSS_NOT_DEFINED_INITIAL_VALUE}` + ); + await checkVariableTooltipForProperty( + view, + "h1", + "height", + // The variable value is the initial value since the variable does not inherit + `--js-no-inherit = ${JS_NO_INHERIT_INITIAL_VALUE}` + ); + await checkVariableTooltipForProperty( + view, + "h1", + "width", + // The variable value is the value set in the main selector, since the variable does inherit + `--js-inherit = ${JS_INHERIT_MAIN_VALUE}` + ); + + info( + "Check that registered properties from new regular stylesheets are displayed" + ); + let onRuleViewRefreshed = view.once("ruleview-refreshed"); + await SpecialPowers.spawn(gBrowser.selectedBrowser, [], () => { + const s = content.wrappedJSObject.document.createElement("style"); + s.id = "added"; + s.textContent = ` + @property --css-dynamic-registered { + syntax: "<color>"; + inherits: false; + initial-value: orchid; + } + `; + + content.wrappedJSObject.document.head.append(s); + }); + info("Wait for the new registered property to be displayed"); + await onRuleViewRefreshed; + + checkRegisteredProperties( + view, + [ + ...expectedProperties, + { + header: `--css-dynamic-registered {`, + propertyDefinition: [ + ` syntax: "<color>";`, + ` inherits: false;`, + ` initial-value: orchid;`, + ], + }, + ].sort((a, b) => (a.header < b.header ? -1 : 1)) + ); + + // The var() tooltip should show the initial value of the new property + await checkVariableTooltipForProperty( + view, + "h1", + "caret-color", + `--css-dynamic-registered = orchid` + ); + + info("Check that updating property does update rules view"); + onRuleViewRefreshed = view.once("ruleview-refreshed"); + await SpecialPowers.spawn(gBrowser.selectedBrowser, [], () => { + content.wrappedJSObject.document.querySelector( + "style#added" + ).textContent = ` + @property --css-dynamic-registered { + syntax: "<color>"; + inherits: true; + initial-value: purple; + } + `; + }); + info("Wait for the rules view to be updated"); + await onRuleViewRefreshed; + + checkRegisteredProperties( + view, + [ + ...expectedProperties, + { + header: `--css-dynamic-registered {`, + propertyDefinition: [ + ` syntax: "<color>";`, + ` inherits: true;`, + ` initial-value: purple;`, + ], + }, + ].sort((a, b) => (a.header < b.header ? -1 : 1)) + ); + + // The var() tooltip should show the new initial value of the updated property + await checkVariableTooltipForProperty( + view, + "h1", + "caret-color", + `--css-dynamic-registered = purple` + ); + + info("Check that removing property does update rules view"); + await SpecialPowers.spawn(gBrowser.selectedBrowser, [], () => { + content.wrappedJSObject.document.querySelector("style#added").remove(); + }); + info("Wait for registered property to be removed"); + await waitFor( + () => + view.styleDocument.querySelector( + `[data-name="--css-dynamic-registered"]` + ) == null + ); + ok(true, `--css-dynamic-registered was removed`); + checkRegisteredProperties(view, expectedProperties); + + // The var() tooltip should indicate that the property isn't set anymore + await checkVariableTooltipForProperty( + view, + "h1", + "caret-color", + `--css-dynamic-registered is not set` + ); + + info( + "Check that registered properties from new constructed stylesheets are displayed" + ); + is( + getRuleViewProperty(view, "h1", "outline").valueSpan.querySelector( + ".ruleview-unmatched-variable" + ).textContent, + "--constructed", + "The --constructed variable is set as unmatched since it's not defined nor registered" + ); + + onRuleViewRefreshed = view.once("ruleview-refreshed"); + await SpecialPowers.spawn(gBrowser.selectedBrowser, [], () => { + const s = new content.wrappedJSObject.CSSStyleSheet(); + s.replaceSync(` + @property --constructed { + syntax: "<color>"; + inherits: true; + initial-value: aqua; + } + `); + content.wrappedJSObject.document.adoptedStyleSheets.push(s); + }); + await onRuleViewRefreshed; + + info("Wait for the new registered property to be displayed"); + checkRegisteredProperties( + view, + [ + ...expectedProperties, + { + header: `--constructed {`, + propertyDefinition: [ + ` syntax: "<color>";`, + ` inherits: true;`, + ` initial-value: aqua;`, + ], + }, + ].sort((a, b) => (a.header < b.header ? -1 : 1)) + ); + + // The `var()` tooltip should show the initial-value of the new property + await checkVariableTooltipForProperty( + view, + "h1", + "outline", + `--constructed = aqua` + ); + + info( + "Check that selecting a node in another document with no registered property hides the container" + ); + await selectNodeInFrames(["iframe", "body"], inspector); + is( + getRegisteredPropertiesContainer(view), + null, + "registered properties container isn't displayed" + ); + + info( + "Check that registering a property will cause the @property container to be displayed" + ); + const iframeBrowsingContext = await SpecialPowers.spawn( + tab.linkedBrowser, + [], + () => content.document.querySelector("iframe").browsingContext + ); + + await SpecialPowers.spawn(iframeBrowsingContext, [], () => { + content.CSS.registerProperty({ + name: "--js-iframe", + syntax: "<color>", + inherits: true, + initialValue: "turquoise", + }); + content.CSS.registerProperty({ + name: "--js-inherit", + syntax: "*", + inherits: true, + }); + }); + + await waitFor(() => getRegisteredPropertiesContainer(view)); + ok(true, "@property container is diplayed when registering a property"); + + // Wait for the 2 properties to be added. + await waitFor(() => getRegisteredPropertiesElements(view).length == 2); + checkRegisteredProperties(view, [ + { + header: `--js-iframe {`, + propertyDefinition: [ + ` name: "--js-iframe",`, + ` syntax: "<color>",`, + ` inherits: true,`, + ` initialValue: turquoise,`, + ], + }, + { + header: `--js-inherit {`, + propertyDefinition: [ + ` name: "--js-inherit",`, + ` syntax: "*",`, + ` inherits: true,`, + ], + }, + ]); + + info("Select a node from the top-level document"); + await selectNode("main", inspector); + + checkRegisteredProperties( + view, + [ + ...expectedProperties, + { + header: `--constructed {`, + propertyDefinition: [ + ` syntax: "<color>";`, + ` inherits: true;`, + ` initial-value: aqua;`, + ], + }, + ].sort((a, b) => (a.header < b.header ? -1 : 1)) + ); +}); + +function getRegisteredPropertiesContainer(view) { + return view.styleDocument.querySelector("#registered-properties-container"); +} + +function getRegisteredPropertiesElements(view) { + const container = getRegisteredPropertiesContainer(view); + if (!container) { + return []; + } + + return Array.from( + container.querySelectorAll( + "#registered-properties-container .ruleview-rule" + ) + ); +} + +function checkRegisteredProperties(view, expectedProperties) { + const registeredPropertiesEl = getRegisteredPropertiesElements(view); + + is( + registeredPropertiesEl.length, + expectedProperties.length, + "There are the expected number of registered properties" + ); + for (let i = 0; i < expectedProperties.length; i++) { + info(`Checking registered property #${i}`); + const { header, propertyDefinition } = expectedProperties[i]; + const registeredPropertyEl = registeredPropertiesEl[i]; + + is( + registeredPropertyEl.querySelector("header").textContent, + header, + `Registered property #${i} has the expected header text` + ); + const propertyDefinitionEl = Array.from( + registeredPropertyEl.querySelectorAll("div[role=listitem]") + ); + is( + propertyDefinitionEl.length, + propertyDefinition.length, + `Registered property #${i} have the expected number of items in its definition` + ); + for (let j = 0; j < expectedProperties.length; j++) { + is( + propertyDefinitionEl[j]?.textContent, + propertyDefinition[j], + `Registered property #${i} have the expected definition at index #${j}` + ); + } + } +} + +/** + * Check the content of a `var()` tooltip on a given rule and property name. + * + * @param {CssRuleView} view + * @param {String} ruleSelector + * @param {String} propertyName + * @param {String} expectedTooltipContent + */ +async function checkVariableTooltipForProperty( + view, + ruleSelector, + propertyName, + expectedTooltipContent +) { + // retrieve tooltip target + const variableEl = await waitFor(() => + getRuleViewProperty( + view, + ruleSelector, + propertyName + ).valueSpan.querySelector(".ruleview-variable,.ruleview-unmatched-variable") + ); + + const previewTooltip = await assertShowPreviewTooltip(view, variableEl); + is( + previewTooltip.panel.textContent, + expectedTooltipContent, + `CSS variable preview tooltip shows the expected value for ${propertyName} in ${ruleSelector}` + ); + await assertTooltipHiddenOnMouseOut(previewTooltip, variableEl); +} |