browser_rules_pseudo_lock_options.js (6884B)
1 /* Any copyright is dedicated to the Public Domain. 2 http://creativecommons.org/publicdomain/zero/1.0/ */ 3 4 "use strict"; 5 6 // Tests that the rule view pseudo lock options work properly. 7 8 const { 9 PSEUDO_CLASSES, 10 } = require("resource://devtools/shared/css/constants.js"); 11 const nodeConstants = require("resource://devtools/shared/dom-node-constants.js"); 12 13 const TEST_URI = ` 14 <style type='text/css'> 15 div { 16 color: red; 17 } 18 div:hover { 19 color: blue; 20 } 21 div:active { 22 color: yellow; 23 } 24 div:focus { 25 color: green; 26 } 27 div:focus-within { 28 color: papayawhip; 29 } 30 div:visited { 31 color: orange; 32 } 33 div:focus-visible { 34 color: wheat; 35 } 36 div:target { 37 color: crimson; 38 } 39 aside::after { 40 content: "-"; 41 } 42 </style> 43 <div>test div</div> 44 <aside>test pseudo</aside> 45 `; 46 47 add_task(async function () { 48 await addTab("data:text/html;charset=utf-8," + encodeURIComponent(TEST_URI)); 49 const { inspector, view } = await openRuleView(); 50 await selectNode("div", inspector); 51 52 info("Check that the toggle button exists"); 53 const button = inspector.panelDoc.getElementById("pseudo-class-panel-toggle"); 54 ok(button, "The pseudo-class panel toggle button exists"); 55 is( 56 view.pseudoClassToggle, 57 button, 58 "The rule-view refers to the right element" 59 ); 60 is( 61 inspector.panelDoc.getElementById(button.getAttribute("aria-controls")), 62 view.pseudoClassPanel, 63 "The pseudo-class panel toggle button has valid aria-controls attribute" 64 ); 65 66 await assertPseudoPanelClosed(view); 67 68 info("Toggle the pseudo class panel open"); 69 view.pseudoClassToggle.click(); 70 await assertPseudoPanelOpened(view); 71 72 info("Toggle each pseudo lock and check that the pseudo lock is added"); 73 for (const pseudo of PSEUDO_CLASSES) { 74 await togglePseudoClass(inspector, view, pseudo); 75 await assertPseudoAdded(inspector, view, pseudo, 3, 1); 76 await togglePseudoClass(inspector, view, pseudo); 77 await assertPseudoRemoved(inspector, view, 2); 78 } 79 80 info("Toggle all pseudo locks and check that the pseudo lock is added"); 81 await togglePseudoClass(inspector, view, ":hover"); 82 await togglePseudoClass(inspector, view, ":active"); 83 await togglePseudoClass(inspector, view, ":focus"); 84 await togglePseudoClass(inspector, view, ":target"); 85 await assertPseudoAdded(inspector, view, ":target", 6, 1); 86 await assertPseudoAdded(inspector, view, ":focus", 6, 2); 87 await assertPseudoAdded(inspector, view, ":active", 6, 3); 88 await assertPseudoAdded(inspector, view, ":hover", 6, 4); 89 await togglePseudoClass(inspector, view, ":hover"); 90 await togglePseudoClass(inspector, view, ":active"); 91 await togglePseudoClass(inspector, view, ":focus"); 92 await togglePseudoClass(inspector, view, ":target"); 93 await assertPseudoRemoved(inspector, view, 2); 94 95 info( 96 "Check that all pseudo locks are unchecked and disabled when selection is null" 97 ); 98 await view.selectElement(null); 99 assertPseudoClassCheckboxesState(view, false); 100 101 info("Check that selecting an element again re-enable the checkboxes"); 102 await selectNode("aside", inspector); 103 assertPseudoClassCheckboxesState(view, true); 104 105 info( 106 "Check that all pseudo locks are unchecked and disabled when a text node is selected" 107 ); 108 const asideNodeFront = await getNodeFront("aside", inspector); 109 const asideChildren = await inspector.walker.children(asideNodeFront); 110 const [textNodeFront, afterNodeFront] = asideChildren.nodes; 111 await selectNode(textNodeFront, inspector); 112 // sanity check 113 is( 114 inspector.selection.nodeFront.nodeType, 115 nodeConstants.TEXT_NODE, 116 "We selected the text node" 117 ); 118 assertPseudoClassCheckboxesState(view, false); 119 120 info("Check that selecting an element again re-enable the checkboxes"); 121 await selectNode("aside", inspector); 122 assertPseudoClassCheckboxesState(view, true); 123 124 info( 125 "Check that all pseudo locks are unchecked and disabled when a pseudo element is selected" 126 ); 127 await selectNode(afterNodeFront, inspector); 128 is( 129 inspector.selection.nodeFront.displayName, 130 "::after", 131 "We selected the ::after pseudo element" 132 ); 133 assertPseudoClassCheckboxesState(view, false); 134 135 info("Toggle the pseudo class panel close"); 136 view.pseudoClassToggle.click(); 137 await assertPseudoPanelClosed(view); 138 }); 139 140 async function togglePseudoClass(inspector, view, pseudoClass) { 141 info(`Toggle the pseudo-class ${pseudoClass}, wait for it to be applied`); 142 const onRefresh = inspector.once("rule-view-refreshed"); 143 const checkbox = getPseudoClassCheckbox(view, pseudoClass); 144 if (checkbox) { 145 checkbox.click(); 146 } 147 await onRefresh; 148 } 149 150 function assertPseudoAdded(inspector, view, pseudoClass, numRules, childIndex) { 151 info("Check that the rule view contains the pseudo-class rule"); 152 is( 153 view.element.children.length, 154 numRules, 155 "Should have " + numRules + " rules." 156 ); 157 is( 158 getRuleViewRuleEditor(view, childIndex).rule.selectorText, 159 "div" + pseudoClass, 160 "rule view is showing " + pseudoClass + " rule" 161 ); 162 } 163 164 function assertPseudoRemoved(inspector, view, numRules) { 165 info("Check that the rule view no longer contains the pseudo-class rule"); 166 is( 167 view.element.children.length, 168 numRules, 169 "Should have " + numRules + " rules." 170 ); 171 is( 172 getRuleViewRuleEditor(view, 1).rule.selectorText, 173 "div", 174 "Second rule is div" 175 ); 176 } 177 178 function assertPseudoPanelOpened(view) { 179 info("Check the opened state of the pseudo class panel"); 180 ok(!view.pseudoClassPanel.hidden, "Pseudo Class Panel Opened"); 181 is( 182 view.pseudoClassToggle.getAttribute("aria-pressed"), 183 "true", 184 "The toggle button is pressed" 185 ); 186 187 for (const pseudo of PSEUDO_CLASSES) { 188 const checkbox = getPseudoClassCheckbox(view, pseudo); 189 ok(!checkbox.disabled, `${pseudo} checkbox is not disabled`); 190 is( 191 checkbox.getAttribute("tabindex"), 192 "0", 193 `${pseudo} checkbox has a tabindex of 0` 194 ); 195 } 196 } 197 198 function assertPseudoPanelClosed(view) { 199 info("Check the closed state of the pseudo clas panel"); 200 ok(view.pseudoClassPanel.hidden, "Pseudo Class Panel Hidden"); 201 is( 202 view.pseudoClassToggle.getAttribute("aria-pressed"), 203 "false", 204 "The toggle button is not pressed" 205 ); 206 207 for (const pseudo of PSEUDO_CLASSES) { 208 const checkbox = getPseudoClassCheckbox(view, pseudo); 209 is( 210 checkbox.getAttribute("tabindex"), 211 "-1", 212 `${pseudo} checkbox has a tabindex of -1` 213 ); 214 } 215 } 216 217 function assertPseudoClassCheckboxesState(view, enabled) { 218 for (const pseudo of PSEUDO_CLASSES) { 219 const checkbox = getPseudoClassCheckbox(view, pseudo); 220 if (enabled) { 221 ok(!checkbox.disabled, `${pseudo} checkbox is not disabled`); 222 } else { 223 ok( 224 !checkbox.checked && checkbox.disabled, 225 `${pseudo} checkbox is unchecked and disabled` 226 ); 227 } 228 } 229 }