browser_markup_scrollable_badge_click.js (5487B)
1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 5 "use strict"; 6 7 // Tests that the correct elements show up and get highlighted in the markup view when the 8 // scrollable badge is clicked. 9 10 const TEST_URI = ` 11 <style type="text/css"> 12 .parent { 13 width: 200px; 14 height: 200px; 15 overflow: scroll; 16 } 17 .fixed { 18 width: 50px; 19 height: 50px; 20 } 21 .shift { 22 margin-left: 300px; 23 } 24 .has-before::before { 25 content: "-"; 26 } 27 </style> 28 <div id="top" class="parent"> 29 <div id="child1" class="fixed shift"> 30 <div id="child2" class="fixed"></div> 31 </div> 32 <div id="child3" class="shift has-before"> 33 <div id="child4" class="fixed"></div> 34 </div> 35 </div> 36 `; 37 38 add_task(async function () { 39 const { inspector } = await openInspectorForURL( 40 "data:text/html;charset=utf-8," + encodeURIComponent(TEST_URI) 41 ); 42 43 const container = await getContainerForSelector("#top", inspector); 44 const scrollableBage = container.elt.querySelector(".scrollable-badge"); 45 is( 46 scrollableBage.getAttribute("aria-pressed"), 47 "false", 48 "Scrollable badge is not pressed by default" 49 ); 50 51 info( 52 "Clicking on the scrollable badge so that the overflow causing elements show up in the markup view." 53 ); 54 scrollableBage.click(); 55 56 await waitForContainers(["#child1", "#child3", "#child4"], inspector); 57 58 await checkOverflowHighlight( 59 ["#child1", "#child4"], 60 ["#child2", "#child3"], 61 inspector 62 ); 63 64 ok(scrollableBage.classList.contains("active"), "Scrollable badge is active"); 65 is( 66 scrollableBage.getAttribute("aria-pressed"), 67 "true", 68 "Scrollable badge is pressed" 69 ); 70 71 checkTelemetry("devtools.markup.scrollable.badge.clicked", "", 1, "scalar"); 72 73 info( 74 "Changing CSS so elements update their overflow highlights accordingly." 75 ); 76 await toggleClass(inspector); 77 78 // By default, #child2 will not be visible in the markup view, 79 // so expand its parent to make it visible. 80 const child1 = await getContainerForSelector("#child1", inspector); 81 await expandContainer(inspector, child1); 82 83 await checkOverflowHighlight( 84 ["#child2", "#child3"], 85 ["#child1", "#child4"], 86 inspector 87 ); 88 89 info( 90 "Clicking on the scrollable badge again so that all the overflow highlight gets removed." 91 ); 92 scrollableBage.click(); 93 94 await checkOverflowHighlight( 95 [], 96 ["#child1", "#child2", "#child3", "#child4"], 97 inspector 98 ); 99 100 ok( 101 !scrollableBage.classList.contains("active"), 102 "Scrollable badge is not active" 103 ); 104 is( 105 scrollableBage.getAttribute("aria-pressed"), 106 "false", 107 "Scrollable badge is not pressed anymore" 108 ); 109 110 checkTelemetry("devtools.markup.scrollable.badge.clicked", "", 2, "scalar"); 111 112 info("Triggering badge with the keyboard"); 113 scrollableBage.focus(); 114 EventUtils.synthesizeKey("VK_RETURN", {}, scrollableBage.ownerGlobal); 115 await checkOverflowHighlight( 116 ["#child2", "#child3"], 117 ["#child1", "#child4"], 118 inspector 119 ); 120 ok( 121 scrollableBage.classList.contains("active"), 122 "badge can be activated with the keyboard" 123 ); 124 is( 125 scrollableBage.getAttribute("aria-pressed"), 126 "true", 127 "Scrollable badge is pressed" 128 ); 129 130 EventUtils.synthesizeKey("VK_RETURN", {}, scrollableBage.ownerGlobal); 131 await checkOverflowHighlight( 132 [], 133 ["#child1", "#child2", "#child3", "#child4"], 134 inspector 135 ); 136 ok( 137 !scrollableBage.classList.contains("active"), 138 "Scrollable badge can be deactivated with the keyboard" 139 ); 140 is( 141 scrollableBage.getAttribute("aria-pressed"), 142 "false", 143 "Scrollable badge is not pressed anymore" 144 ); 145 146 info("Double-click on the scrollable badge"); 147 EventUtils.sendMouseEvent({ type: "dblclick" }, scrollableBage); 148 ok( 149 container.expanded, 150 "Double clicking on the badge did not collapse the container" 151 ); 152 }); 153 154 async function getContainerForSelector(selector, inspector) { 155 const nodeFront = await getNodeFront(selector, inspector); 156 return getContainerForNodeFront(nodeFront, inspector); 157 } 158 159 async function waitForContainers(selectors, inspector) { 160 for (const selector of selectors) { 161 info(`Wait for markup container of ${selector}`); 162 await asyncWaitUntil(() => getContainerForSelector(selector, inspector)); 163 } 164 } 165 166 async function elementHasHighlight(selector, inspector) { 167 const container = await getContainerForSelector(selector, inspector); 168 return container?.tagState.classList.contains("overflow-causing-highlighted"); 169 } 170 171 async function checkOverflowHighlight( 172 selectorWithHighlight, 173 selectorWithNoHighlight, 174 inspector 175 ) { 176 for (const selector of selectorWithHighlight) { 177 ok( 178 await elementHasHighlight(selector, inspector), 179 `${selector} contains overflow highlight` 180 ); 181 } 182 for (const selector of selectorWithNoHighlight) { 183 ok( 184 !(await elementHasHighlight(selector, inspector)), 185 `${selector} does not contain overflow highlight` 186 ); 187 } 188 } 189 190 async function toggleClass(inspector) { 191 const onStateChanged = inspector.walker.once("overflow-change"); 192 193 await SpecialPowers.spawn(gBrowser.selectedBrowser, [], async function () { 194 content.document.querySelector("#child1").classList.toggle("fixed"); 195 content.document.querySelector("#child3").classList.toggle("fixed"); 196 }); 197 198 await onStateChanged; 199 }