| <!DOCTYPE html> |
| <html> |
| <head> |
| <script src="../../http/tests/inspector/resources/inspector-test.js"></script> |
| <script> |
| |
| function test() |
| { |
| let suite = InspectorTest.createAsyncSuite("DOMNodeStyles.usedCSSVariables"); |
| |
| function addTestCase({name, description, selector, checkUsedCSSVariables}) |
| { |
| suite.addTestCase({ |
| name, |
| description, |
| async test() { |
| let documentNode = await WI.domManager.requestDocument(); |
| let nodeId = await documentNode.querySelector(selector); |
| let domNode = await WI.domManager.nodeForId(nodeId); |
| InspectorTest.assert(domNode, `Should find DOM Node for selector '${selector}'.`); |
| |
| let cssStyles = WI.cssManager.stylesForNode(domNode); |
| InspectorTest.assert(cssStyles, `Should find CSS Styles for DOM Node.`); |
| |
| await cssStyles.refreshIfNeeded(); |
| |
| await checkUsedCSSVariables(cssStyles.usedCSSVariables, cssStyles.allCSSVariables); |
| }, |
| }); |
| } |
| |
| addTestCase({ |
| name: "DOMNodeStyles.usedCSSVariables.InheritedUsed", |
| description: "A used inherited variable is found in the set of used variables", |
| selector: "#used-inherited-variable", |
| checkUsedCSSVariables(usedCSSVariables) { |
| InspectorTest.expectEqual(usedCSSVariables.size, 1, "Set should contain one used variable"); |
| InspectorTest.expectTrue(usedCSSVariables.has("--inherited-color"), "--inherited-color should be used"); |
| }, |
| }); |
| |
| addTestCase({ |
| name: "DOMNodeStyles.usedCSSVariables.InheritedUsedReferenced", |
| description: "An inherited variable referenced by another used variable is found in the set of used variables", |
| selector: "#used-referenced-inherited-variable", |
| checkUsedCSSVariables(usedCSSVariables) { |
| InspectorTest.expectEqual(usedCSSVariables.size, 2, "Set should contain two used variables"); |
| InspectorTest.expectTrue(usedCSSVariables.has("--inherited-color"), "--inherited-color should be used"); |
| InspectorTest.expectTrue(usedCSSVariables.has("--color"), "--color should be used"); |
| }, |
| }); |
| |
| addTestCase({ |
| name: "DOMNodeStyles.usedCSSVariables.InheritedNotUsed", |
| description: "Unused inherited variables are not found in the set of used variables", |
| selector: "#unused-inherited-variable", |
| checkUsedCSSVariables(usedCSSVariables) { |
| InspectorTest.expectEqual(usedCSSVariables.size, 1, "Set should contain one used variable"); |
| InspectorTest.expectTrue(usedCSSVariables.has("--color"), "--color should be used"); |
| InspectorTest.expectFalse(usedCSSVariables.has("--inherited-color"), "--inherited-color should not be used"); |
| }, |
| }); |
| |
| for (let [name, selector] of [["InheritedReverseOrder", "#used-reversed-inherited-variable-chain"], ["InheritedDifferentRules", "#used-inherited-variable-chain-across-rules"]]) { |
| addTestCase({ |
| name: `DOMNodeStyles.usedCSSVariables.${name}`, |
| description: "Inherited variable dependencies are independent of declaration order", |
| selector, |
| checkUsedCSSVariables(usedCSSVariables) { |
| InspectorTest.expectEqual(usedCSSVariables.size, 3, "The full inherited dependency chain should be used"); |
| for (let variableName of ["--theme-button-color", "--theme-accent-color", "--theme-base-color"]) |
| InspectorTest.expectTrue(usedCSSVariables.has(variableName), `${variableName} should be used`); |
| InspectorTest.expectFalse(usedCSSVariables.has("--theme-unused-color"), "The unrelated inherited variable should remain unused"); |
| }, |
| }); |
| } |
| |
| addTestCase({ |
| name: "DOMNodeStyles.usedCSSVariables.InheritedUnusedChain", |
| selector: "#unused-reversed-inherited-variable-chain", |
| checkUsedCSSVariables(usedCSSVariables) { |
| InspectorTest.expectEqual(usedCSSVariables.size, 0, "The unused inherited dependency chain should remain unused"); |
| }, |
| }); |
| |
| addTestCase({ |
| name: "DOMNodeStyles.usedCSSVariables.InheritedCyclicChain", |
| selector: "#used-cyclic-inherited-variable-chain", |
| checkUsedCSSVariables(usedCSSVariables) { |
| InspectorTest.expectShallowEqual([...usedCSSVariables].sort(), ["--theme-cycle-a", "--theme-cycle-b"], "The inherited dependency cycle should include each variable once"); |
| }, |
| }); |
| |
| addTestCase({ |
| name: "DOMNodeStyles.usedCSSVariables.InheritedUsedFunction", |
| description: "An inherited variable used in a function value is found in the set of used variables", |
| selector: "#used-inherited-variable-function", |
| checkUsedCSSVariables(usedCSSVariables) { |
| InspectorTest.expectEqual(usedCSSVariables.size, 1, "Set should contain one used variable"); |
| InspectorTest.expectTrue(usedCSSVariables.has("--inherited-color"), "--inherited-color should be used"); |
| }, |
| }); |
| |
| addTestCase({ |
| name: "DOMNodeStyles.usedCSSVariables.HighSpecificityUsed", |
| description: "A variable declared in a higher specificity rule but used in a lower specificity rule is found in the set of used variables", |
| selector: "#used-higher-specificity", |
| checkUsedCSSVariables(usedCSSVariables) { |
| InspectorTest.expectTrue(usedCSSVariables.has("--color"), "--color should be used"); |
| }, |
| }); |
| |
| addTestCase({ |
| name: "DOMNodeStyles.usedCSSVariables.InheritedHighSpecificityUsed", |
| description: "An inherited variable declared in a higher specificity rule but used in a lower specificity rule on an inheritable property (`color`) is found in the set of used variables", |
| selector: "#used-higher-specificity-inheritable > p", |
| checkUsedCSSVariables(usedCSSVariables) { |
| InspectorTest.expectEqual(usedCSSVariables.size, 1, "Set should contain one used variable"); |
| InspectorTest.expectTrue(usedCSSVariables.has("--color"), "--color should be used"); |
| }, |
| }); |
| |
| addTestCase({ |
| name: "DOMNodeStyles.usedCSSVariables.InheritedHighSpecificityNotUsed", |
| description: "An inherited variable declared in a higher specificity rule but used in a lower specificity rule on a non-inheritable property (`background-color`) is not found in the set of used variables", |
| selector: "#unused-higher-specificity-non-inheritable > p", |
| checkUsedCSSVariables(usedCSSVariables) { |
| InspectorTest.expectFalse(usedCSSVariables.has("--color"), "--color should not be used"); |
| }, |
| }); |
| |
| for (let [name, selector] of [["PseudoElement", "#used-with-pseudo-element"], ["Keyframes", "#used-with-keyframes"]]) { |
| addTestCase({ |
| name: `DOMNodeStyles.usedCSSVariables.${name}`, |
| description: "Processing pseudo elements or keyframes preserves the element's CSS variables", |
| selector, |
| checkUsedCSSVariables(usedCSSVariables, allCSSVariables) { |
| InspectorTest.expectEqual(usedCSSVariables.size, 1, "Set should contain one used variable"); |
| InspectorTest.expectTrue(usedCSSVariables.has("--color"), "--color should be used"); |
| InspectorTest.expectTrue(allCSSVariables.has("--color"), "--color should be available"); |
| InspectorTest.expectTrue(allCSSVariables.has("--inherited-color"), "--inherited-color should be available"); |
| InspectorTest.expectFalse(allCSSVariables.has("--pseudo-color"), "Pseudo element variables should not replace the element's variables"); |
| }, |
| }); |
| } |
| |
| addTestCase({ |
| name: "DOMNodeStyles.usedCSSVariables.KeyframesInheritedReference", |
| description: "Variables referenced only by an element's keyframes remain used", |
| selector: "#used-only-in-keyframes", |
| async checkUsedCSSVariables(usedCSSVariables, allCSSVariables) { |
| InspectorTest.expectEqual(usedCSSVariables.size, 2, "Set should include the animation variable and its inherited dependency"); |
| InspectorTest.expectTrue(usedCSSVariables.has("--animation-color"), "--animation-color should be used"); |
| InspectorTest.expectTrue(usedCSSVariables.has("--inherited-color"), "--inherited-color should be used"); |
| InspectorTest.expectTrue(allCSSVariables.has("--animation-color"), "--animation-color should be available"); |
| let color = await InspectorTest.evaluateInPage('getComputedStyle(document.getElementById("used-only-in-keyframes")).color'); |
| InspectorTest.expectEqual(color, "rgb(0, 128, 0)", "The animation should render the inherited variable value"); |
| }, |
| }); |
| |
| addTestCase({ |
| name: "DOMNodeStyles.usedCSSVariables.KeyframeDeclaration", |
| description: "A variable declared by an element's keyframes remains available", |
| selector: "#defined-only-in-keyframes", |
| async checkUsedCSSVariables(usedCSSVariables, allCSSVariables) { |
| InspectorTest.expectTrue(usedCSSVariables.has("--keyframe-color"), "--keyframe-color should be used"); |
| InspectorTest.expectTrue(allCSSVariables.has("--keyframe-color"), "--keyframe-color should be available"); |
| let color = await InspectorTest.evaluateInPage('getComputedStyle(document.getElementById("defined-only-in-keyframes")).color'); |
| InspectorTest.expectEqual(color, "rgb(0, 128, 0)", "The element should render the variable declared in keyframes"); |
| }, |
| }); |
| |
| suite.runTestCasesAndFinish(); |
| } |
| </script> |
| <style> |
| |
| html { |
| --inherited-color: green; |
| --animation-color: var(--inherited-color); |
| } |
| |
| div#used-inherited-variable { |
| color: var(--inherited-color, red); |
| } |
| |
| div#used-referenced-inherited-variable { |
| --color: var(--inherited-color); |
| color: var(--color, red); |
| } |
| |
| #reversed-inherited-variable-chain { |
| --theme-base-color: green; |
| --theme-accent-color: var(--theme-base-color); |
| --theme-button-color: var(--theme-accent-color); |
| --theme-unused-color: red; |
| } |
| |
| #used-reversed-inherited-variable-chain, |
| #used-inherited-variable-chain-across-rules { |
| background-color: var(--theme-button-color); |
| } |
| |
| #inherited-variable-chain-across-rules { |
| --theme-base-color: green; |
| --theme-unused-color: red; |
| } |
| |
| div.inherited-chain-middle { |
| --theme-accent-color: var(--theme-base-color); |
| } |
| |
| .inherited-chain-lowest { |
| --theme-button-color: var(--theme-accent-color); |
| } |
| |
| #cyclic-inherited-variable-chain { |
| --theme-cycle-a: var(--theme-cycle-b); |
| --theme-cycle-b: var(--theme-cycle-a); |
| } |
| |
| #used-cyclic-inherited-variable-chain { |
| background-color: var(--theme-cycle-a, green); |
| } |
| |
| div#unused-inherited-variable { |
| --color: green; |
| color: var(--color, red); |
| } |
| |
| div#used-inherited-variable-function { |
| background: linear-gradient(90deg, var(--inherited-color, red), white); |
| } |
| |
| div.used-lower-specificity { |
| background-color: var(--color, red); |
| } |
| |
| div#used-higher-specificity { |
| --color: green; |
| } |
| |
| div.used-lower-specificity-inheritable { |
| color: var(--color, red); |
| } |
| |
| div#used-higher-specificity-inheritable { |
| --color: green; |
| } |
| |
| div.unused-lower-specificity-non-inheritable { |
| background-color: var(--color, red); |
| } |
| |
| div#unused-higher-specificity-non-inheritable { |
| --color: green; |
| } |
| |
| div#used-with-pseudo-element, |
| div#used-with-keyframes { |
| --color: green; |
| color: var(--color); |
| } |
| |
| div#used-with-pseudo-element::before { |
| content: ""; |
| --pseudo-color: blue; |
| color: var(--pseudo-color); |
| } |
| |
| div#used-with-keyframes { |
| animation: fade 1s infinite; |
| } |
| |
| @keyframes fade { |
| from { opacity: 0; } |
| to { opacity: 1; } |
| } |
| |
| #used-only-in-keyframes { |
| animation: inherited-variables 1s linear paused; |
| } |
| |
| @keyframes inherited-variables { |
| from { color: var(--animation-color); } |
| to { color: var(--animation-color); } |
| } |
| |
| #defined-only-in-keyframes { |
| animation: keyframe-variable 1s linear paused; |
| color: var(--keyframe-color); |
| } |
| |
| @keyframes keyframe-variable { |
| from { --keyframe-color: green; } |
| to { --keyframe-color: green; } |
| } |
| |
| </style> |
| </head> |
| <body onload="runTest();"> |
| <p>Test for DOMNodeStyles.usedCSSVariables</p> |
| <div> |
| <div id="used-inherited-variable"></div> |
| <div id="used-referenced-inherited-variable"></div> |
| <div id="unused-inherited-variable"></div> |
| <div id="used-inherited-variable-function"></div> |
| <div id="used-with-pseudo-element"></div> |
| <div id="used-with-keyframes"></div> |
| <div id="used-only-in-keyframes"></div> |
| <div id="defined-only-in-keyframes"></div> |
| <div id="used-higher-specificity" class="used-lower-specificity"></div> |
| <div id="used-higher-specificity-inheritable" class="used-lower-specificity-inheritable"> |
| <p></p> |
| </div> |
| <div id="unused-higher-specificity-non-inheritable" class="unused-lower-specificity-non-inheritable"> |
| <p></p> |
| </div> |
| </div> |
| <div id="reversed-inherited-variable-chain"> |
| <div id="used-reversed-inherited-variable-chain"></div> |
| <div id="unused-reversed-inherited-variable-chain"></div> |
| </div> |
| <div id="inherited-variable-chain-across-rules" class="inherited-chain-middle inherited-chain-lowest"> |
| <div id="used-inherited-variable-chain-across-rules"></div> |
| </div> |
| <div id="cyclic-inherited-variable-chain"> |
| <div id="used-cyclic-inherited-variable-chain"></div> |
| </div> |
| </body> |
| </html> |