browser_rules_light_dark.js (4550B)
1 /* Any copyright is dedicated to the Public Domain. 2 http://creativecommons.org/publicdomain/zero/1.0/ */ 3 4 "use strict"; 5 6 // Test for light-dark() in rule view. 7 8 const TEST_URI = `data:text/html,<meta charset=utf8> 9 <style> 10 @media not (prefers-color-scheme: dark) { 11 html { 12 color-scheme: light; 13 } 14 } 15 16 @media (prefers-color-scheme: dark) { 17 html { 18 color-scheme: dark; 19 } 20 } 21 22 h1 { 23 background-color: light-dark(gold, tomato); 24 } 25 26 .light { 27 color-scheme: light; 28 color: light-dark(red, blue); 29 border-color: light-dark(pink, cyan); 30 } 31 32 .dark { 33 color-scheme: dark; 34 background: linear-gradient( 35 light-dark(blue, darkblue), 36 light-dark(red, darkred) 37 ); 38 } 39 </style> 40 <h1>Hello</h1> 41 <div class="light"> 42 <pre>color-scheme: light</pre> 43 <div class="dark"> 44 <pre>color-scheme: dark</pre> 45 </div> 46 </div>`; 47 48 add_task(async function () { 49 await addTab(TEST_URI); 50 const { inspector, view } = await openRuleView(); 51 52 info("Select node with color-scheme: light"); 53 await selectNode(".light", inspector); 54 55 // `color: light-dark(red, blue)` 56 assertColorSpans(view, ".light", "color", [ 57 { color: "red", matched: true }, 58 { color: "blue", matched: false }, 59 ]); 60 61 // `border-color: light-dark(pink, cyan)` 62 assertColorSpans(view, ".light", "border-color", [ 63 { color: "pink", matched: true }, 64 { color: "cyan", matched: false }, 65 ]); 66 67 info("Select node with color-scheme: dark"); 68 await selectNode(".dark", inspector); 69 70 // `background: linear-gradient(light-dark(blue, darkblue),light-dark(red, darkred))` 71 assertColorSpans(view, ".dark", "background", [ 72 { color: "blue", matched: false }, 73 { color: "darkblue", matched: true }, 74 { color: "red", matched: false }, 75 { color: "darkred", matched: true }, 76 ]); 77 78 // We show the inherited rule for color, which is matched by `.light`, so here, even if 79 // the node has a dark color scheme, light-dark should mark second parameters as unmatched 80 // `color: light-dark(red, blue)` 81 assertColorSpans(view, ".light", "color", [ 82 { color: "red", matched: true }, 83 { color: "blue", matched: false }, 84 ]); 85 86 info("Select node without explicit color-scheme property"); 87 // h1 has no color-scheme so it inherits from the html one, which depends on the actual 88 // media query value. light-dark in the associated rule should be updated when toggling 89 // simulation. 90 await selectNode("h1", inspector); 91 92 // Read the color scheme to know if we should click on the light or dark button 93 // to trigger a change. 94 info("Enable light mode simulation if needed"); 95 const isDarkScheme = await SpecialPowers.spawn( 96 gBrowser.selectedBrowser, 97 [], 98 () => { 99 return content.matchMedia("(prefers-color-scheme: dark)").matches; 100 } 101 ); 102 if (isDarkScheme) { 103 const onRuleViewRefreshed = view.once("ruleview-refreshed"); 104 inspector.panelDoc 105 .querySelector("#color-scheme-simulation-light-toggle") 106 .click(); 107 await onRuleViewRefreshed; 108 } 109 110 // `background-color: light-dark(gold, tomato)` 111 assertColorSpans(view, "h1", "background-color", [ 112 { color: "gold", matched: true }, 113 { color: "tomato", matched: false }, 114 ]); 115 116 info("Trigger dark mode simulation"); 117 const onRuleViewRefreshed = view.once("ruleview-refreshed"); 118 inspector.panelDoc 119 .querySelector("#color-scheme-simulation-dark-toggle") 120 .click(); 121 await onRuleViewRefreshed; 122 123 // `background-color: light-dark(gold, tomato)` 124 assertColorSpans(view, "h1", "background-color", [ 125 { color: "gold", matched: false }, 126 { color: "tomato", matched: true }, 127 ]); 128 }); 129 130 function assertColorSpans(view, ruleSelector, propertyName, expectedColors) { 131 const colorSpans = getRuleViewProperty( 132 view, 133 ruleSelector, 134 propertyName 135 ).valueSpan.querySelectorAll("span:has(> .ruleview-color)"); 136 is( 137 colorSpans.length, 138 expectedColors.length, 139 "Got expected number of color spans" 140 ); 141 for (let i = 0; i < expectedColors.length; i++) { 142 const colorSpan = colorSpans[i]; 143 const expectedColorData = expectedColors[i]; 144 is( 145 colorSpan.textContent, 146 expectedColorData.color, 147 `Expected color ${i} for ${ruleSelector} ${propertyName}` 148 ); 149 is( 150 !colorSpan.classList.contains("inspector-unmatched"), 151 expectedColorData.matched, 152 `Color ${i} for ${ruleSelector} ${propertyName} is ${ 153 expectedColorData.matched ? "matched" : "unmatched" 154 }` 155 ); 156 } 157 }