browser_inspector_pseudoclass-lock.js (7057B)
1 /* Any copyright is dedicated to the Public Domain. 2 http://creativecommons.org/publicdomain/zero/1.0/ */ 3 /* globals getHighlighterTestFrontWithoutToolbox */ 4 "use strict"; 5 6 // Test that locking the pseudoclass displays correctly in the ruleview 7 8 const PSEUDO = ":hover"; 9 const TEST_URL = 10 "data:text/html;charset=UTF-8," + 11 "<head>" + 12 " <style>div {color:red;} div:hover {color:blue;}</style>" + 13 "</head>" + 14 "<body>" + 15 ' <div id="parent-div">' + 16 ' <div id="div-1">test div</div>' + 17 ' <div id="div-2">test div2</div>' + 18 " </div>" + 19 "</body>"; 20 21 add_task(async function () { 22 info("Creating the test tab and opening the rule-view"); 23 let { tab, toolbox, inspector, highlighterTestFront } = 24 await openInspectorForURL(TEST_URL); 25 26 info("Selecting the ruleview sidebar"); 27 inspector.sidebar.select("ruleview"); 28 29 const view = inspector.getPanel("ruleview").view; 30 31 info("Selecting the test node"); 32 await selectNode("#div-1", inspector); 33 34 await togglePseudoClass(inspector); 35 await assertPseudoAddedToNode( 36 inspector, 37 highlighterTestFront, 38 view, 39 "#div-1" 40 ); 41 42 await togglePseudoClass(inspector); 43 await assertPseudoRemovedFromNode(highlighterTestFront, "#div-1"); 44 await assertPseudoRemovedFromView( 45 inspector, 46 highlighterTestFront, 47 view, 48 "#div-1" 49 ); 50 51 await togglePseudoClass(inspector); 52 await testNavigate(inspector); 53 54 info("Toggle pseudo on the parent and ensure everything is toggled off"); 55 await selectNode("#parent-div", inspector); 56 await togglePseudoClass(inspector); 57 await assertPseudoRemovedFromNode(highlighterTestFront, "#div-1"); 58 await assertPseudoRemovedFromView( 59 inspector, 60 highlighterTestFront, 61 view, 62 "#div-1" 63 ); 64 65 await togglePseudoClass(inspector); 66 info("Assert pseudo is dismissed when toggling it on a sibling node"); 67 await selectNode("#div-2", inspector); 68 await togglePseudoClass(inspector); 69 await assertPseudoAddedToNode( 70 inspector, 71 highlighterTestFront, 72 view, 73 "#div-2" 74 ); 75 const hasLock = await hasPseudoClassLock("#div-1", PSEUDO); 76 ok( 77 !hasLock, 78 "pseudo-class lock has been removed for the previous locked node" 79 ); 80 81 info("Destroying the toolbox"); 82 await toolbox.destroy(); 83 84 // As the toolbox get destroyed, we need to fetch a new test-actor 85 highlighterTestFront = await getHighlighterTestFrontWithoutToolbox(tab); 86 87 await assertPseudoRemovedFromNode(highlighterTestFront, "#div-1"); 88 await assertPseudoRemovedFromNode(highlighterTestFront, "#div-2"); 89 }); 90 91 async function togglePseudoClass(inspector) { 92 info("Toggle the pseudoclass, wait for it to be applied"); 93 94 // Give the inspector panels a chance to update when the pseudoclass changes 95 const onPseudo = inspector.selection.once("pseudoclass"); 96 const onRefresh = inspector.once("rule-view-refreshed"); 97 98 // Walker uses SDK-events so calling walker.once does not return a promise. 99 const onMutations = once(inspector.walker, "mutations"); 100 101 await inspector.togglePseudoClass(PSEUDO); 102 103 await onPseudo; 104 await onRefresh; 105 await onMutations; 106 } 107 108 async function testNavigate(inspector) { 109 await selectNode("#parent-div", inspector); 110 111 info("Make sure the pseudoclass is still on after navigating to a parent"); 112 113 ok( 114 await hasPseudoClassLock("#div-1", PSEUDO), 115 "pseudo-class lock is still applied after inspecting ancestor" 116 ); 117 118 await selectNode("#div-2", inspector); 119 120 info( 121 "Make sure the pseudoclass is still set after navigating to a " + 122 "non-hierarchy node" 123 ); 124 ok( 125 await hasPseudoClassLock("#div-1", PSEUDO), 126 "pseudo-class lock is still on after inspecting sibling node" 127 ); 128 129 await selectNode("#div-1", inspector); 130 } 131 132 async function assertPseudoAddedToNode( 133 inspector, 134 highlighterTestFront, 135 ruleview, 136 selector 137 ) { 138 info( 139 "Make sure the pseudoclass lock is applied to " + 140 selector + 141 " and its ancestors" 142 ); 143 144 let hasLock = await hasPseudoClassLock(selector, PSEUDO); 145 ok(hasLock, "pseudo-class lock has been applied"); 146 hasLock = await hasPseudoClassLock("#parent-div", PSEUDO); 147 ok(hasLock, "pseudo-class lock has been applied"); 148 hasLock = await hasPseudoClassLock("body", PSEUDO); 149 ok(hasLock, "pseudo-class lock has been applied"); 150 151 info("Check that the ruleview contains the pseudo-class rule"); 152 const rules = ruleview.element.querySelectorAll(".ruleview-rule"); 153 is( 154 rules.length, 155 3, 156 "rule view is showing 3 rules for pseudo-class locked div" 157 ); 158 is( 159 rules[1]._ruleEditor.rule.selectorText, 160 "div:hover", 161 "rule view is showing " + PSEUDO + " rule" 162 ); 163 164 info("Show the highlighter on " + selector); 165 const nodeFront = await getNodeFront(selector, inspector); 166 await inspector.highlighters.showHighlighterTypeForNode( 167 inspector.highlighters.TYPES.BOXMODEL, 168 nodeFront 169 ); 170 171 info("Check that the infobar selector contains the pseudo-class"); 172 const value = await highlighterTestFront.getHighlighterNodeTextContent( 173 "box-model-infobar-pseudo-classes" 174 ); 175 is(value, PSEUDO, "pseudo-class in infobar selector"); 176 await inspector.highlighters.hideHighlighterType( 177 inspector.highlighters.TYPES.BOXMODEL 178 ); 179 } 180 181 async function assertPseudoRemovedFromNode(highlighterTestFront, selector) { 182 info( 183 "Make sure the pseudoclass lock is removed from #div-1 and its " + 184 "ancestors" 185 ); 186 187 let hasLock = await hasPseudoClassLock(selector, PSEUDO); 188 ok(!hasLock, "pseudo-class lock has been removed"); 189 hasLock = await hasPseudoClassLock("#parent-div", PSEUDO); 190 ok(!hasLock, "pseudo-class lock has been removed"); 191 hasLock = await hasPseudoClassLock("body", PSEUDO); 192 ok(!hasLock, "pseudo-class lock has been removed"); 193 } 194 195 async function assertPseudoRemovedFromView( 196 inspector, 197 highlighterTestFront, 198 ruleview, 199 selector 200 ) { 201 info("Check that the ruleview no longer contains the pseudo-class rule"); 202 const rules = ruleview.element.querySelectorAll(".ruleview-rule"); 203 is(rules.length, 2, "rule view is showing 2 rules after removing lock"); 204 205 const nodeFront = await getNodeFront(selector, inspector); 206 await inspector.highlighters.showHighlighterTypeForNode( 207 inspector.highlighters.TYPES.BOXMODEL, 208 nodeFront 209 ); 210 211 const value = await highlighterTestFront.getHighlighterNodeTextContent( 212 "box-model-infobar-pseudo-classes" 213 ); 214 is(value, "", "pseudo-class removed from infobar selector"); 215 await inspector.highlighters.hideHighlighterType( 216 inspector.highlighters.TYPES.BOXMODEL 217 ); 218 } 219 220 /** 221 * Check that an element currently has a pseudo-class lock. 222 * 223 * @param {string} selector The node selector to get the pseudo-class from 224 * @param {string} pseudo The pseudoclass to check for 225 * @return {Promise<boolean>} 226 */ 227 function hasPseudoClassLock(selector, pseudoClass) { 228 return SpecialPowers.spawn( 229 gBrowser.selectedBrowser, 230 [selector, pseudoClass], 231 (_selector, _pseudoClass) => { 232 const element = content.document.querySelector(_selector); 233 return InspectorUtils.hasPseudoClassLock(element, _pseudoClass); 234 } 235 ); 236 }