browser_webconsole_split.js (11863B)
1 /* Any copyright is dedicated to the Public Domain. 2 * http://creativecommons.org/publicdomain/zero/1.0/ */ 3 4 "use strict"; 5 6 const TEST_URI = 7 "data:text/html;charset=utf-8,<!DOCTYPE html>Web Console test for splitting"; 8 9 // Test is slow on Linux EC2 instances - Bug 962931 10 requestLongerTimeout(4); 11 12 add_task(async function () { 13 let toolbox; 14 const getFluentString = await getFluentStringHelper([ 15 "devtools/client/toolbox.ftl", 16 ]); 17 const hideSplitConsoleLabel = getFluentString( 18 "toolbox-meatball-menu-hideconsole-label" 19 ); 20 21 await addTab(TEST_URI); 22 await testConsoleLoadOnDifferentPanel(); 23 await testKeyboardShortcuts(); 24 await checkAllTools(); 25 26 info("Testing host types"); 27 checkHostType(Toolbox.HostType.BOTTOM); 28 await checkToolboxUI(); 29 await toolbox.switchHost(Toolbox.HostType.RIGHT); 30 checkHostType(Toolbox.HostType.RIGHT); 31 await checkToolboxUI(); 32 await toolbox.switchHost(Toolbox.HostType.WINDOW); 33 34 // checkHostType, below, will open the meatball menu to read the "Split 35 // console" menu item label. However, if we've just opened a new window then 36 // on some platforms when we switch focus to the new window we might end up 37 // triggering the auto-close behavior on the menu popup. To avoid that, wait 38 // a moment before querying the menu. 39 await new Promise(resolve => requestIdleCallback(resolve)); 40 41 checkHostType(Toolbox.HostType.WINDOW); 42 await checkToolboxUI(); 43 await toolbox.switchHost(Toolbox.HostType.BOTTOM); 44 45 async function testConsoleLoadOnDifferentPanel() { 46 info("About to check console loads even when non-webconsole panel is open"); 47 48 await openPanel("inspector"); 49 const webconsoleReady = toolbox.once("webconsole-ready"); 50 await toolbox.toggleSplitConsole(); 51 await webconsoleReady; 52 ok( 53 true, 54 "Webconsole has been triggered as loaded while another tool is active" 55 ); 56 } 57 58 async function testKeyboardShortcuts() { 59 info("About to check that panel responds to ESCAPE keyboard shortcut"); 60 61 const splitConsoleReady = toolbox.once("split-console"); 62 EventUtils.sendKey("ESCAPE", toolbox.win); 63 await splitConsoleReady; 64 ok(true, "Split console has been triggered via ESCAPE keypress"); 65 } 66 67 async function checkAllTools() { 68 info("About to check split console with each panel individually."); 69 await openAndCheckPanel("jsdebugger"); 70 await openAndCheckPanel("inspector"); 71 await openAndCheckPanel("styleeditor"); 72 await openAndCheckPanel("performance"); 73 await openAndCheckPanel("netmonitor"); 74 75 await checkWebconsolePanelOpened(); 76 } 77 78 async function getCurrentUIState() { 79 const deck = toolbox.doc.querySelector("#toolbox-deck"); 80 const webconsolePanel = toolbox.webconsolePanel; 81 const splitter = toolbox.doc.querySelector("#toolbox-console-splitter"); 82 83 const containerHeight = deck.parentNode.getBoundingClientRect().height; 84 const deckHeight = deck.getBoundingClientRect().height; 85 const webconsoleHeight = webconsolePanel.getBoundingClientRect().height; 86 const splitterVisibility = !splitter.hidden; 87 // Splitter height will be 1px since the margin is negative. 88 const splitterHeight = splitterVisibility ? 1 : 0; 89 const openedConsolePanel = toolbox.currentToolId === "webconsole"; 90 const menuLabel = await getMenuLabel(toolbox); 91 const isConsoleVisible = 92 webconsolePanel.ownerGlobal.getComputedStyle(webconsolePanel) 93 .visibility == "visible"; 94 const isDeckVisible = 95 deck.ownerGlobal.getComputedStyle(deck).visibility == "visible"; 96 97 return { 98 deckHeight, 99 containerHeight, 100 webconsoleHeight, 101 splitterVisibility, 102 splitterHeight, 103 openedConsolePanel, 104 menuLabel, 105 isConsoleVisible, 106 isDeckVisible, 107 }; 108 } 109 110 async function getMenuLabel() { 111 const button = toolbox.doc.getElementById("toolbox-meatball-menu-button"); 112 const onPopupShown = new Promise( 113 resolve => { 114 toolbox.doc.addEventListener("popupshown", () => resolve()); 115 }, 116 { once: true } 117 ); 118 info("Click on menu and wait for the popup to be visible"); 119 AccessibilityUtils.setEnv({ 120 // Toobox toolbar buttons are handled with arrow keys. 121 nonNegativeTabIndexRule: false, 122 }); 123 EventUtils.sendMouseEvent({ type: "click" }, button); 124 AccessibilityUtils.resetEnv(); 125 await onPopupShown; 126 127 const menuItem = toolbox.doc.getElementById( 128 "toolbox-meatball-menu-splitconsole" 129 ); 130 131 // Return undefined if the menu item is not available 132 let label; 133 if (menuItem && menuItem.querySelector(".label")) { 134 label = 135 menuItem.querySelector(".label").textContent === hideSplitConsoleLabel 136 ? "hide" 137 : "split"; 138 } 139 140 // Wait for menu to close 141 const onPopupHide = new Promise(resolve => { 142 toolbox.doc.addEventListener( 143 "popuphidden", 144 () => { 145 resolve(label); 146 }, 147 { once: true } 148 ); 149 }); 150 info("Hit escape and wait for the popup to be closed"); 151 EventUtils.sendKey("ESCAPE", toolbox.win); 152 await onPopupHide; 153 154 return label; 155 } 156 157 async function checkWebconsolePanelOpened() { 158 info("About to check special cases when webconsole panel is open."); 159 160 // Start with console split, so we can test for transition to main panel. 161 await toolbox.toggleSplitConsole(); 162 163 let currentUIState = await getCurrentUIState(); 164 165 ok( 166 currentUIState.splitterVisibility, 167 "Splitter is visible when console is split" 168 ); 169 Assert.greater( 170 currentUIState.deckHeight, 171 0, 172 "Deck has a height > 0 when console is split" 173 ); 174 Assert.greater( 175 currentUIState.webconsoleHeight, 176 75, 177 "Web console height is at least set to its minimal height" 178 ); 179 ok(currentUIState.isDeckVisible, "Deck is visible when console is split"); 180 181 ok(currentUIState.isConsoleVisible, "Web console is visible"); 182 ok( 183 !currentUIState.openedConsolePanel, 184 "The console panel is not the current tool" 185 ); 186 is( 187 currentUIState.menuLabel, 188 "hide", 189 "The menu item indicates the console is split" 190 ); 191 192 await openPanel("webconsole"); 193 currentUIState = await getCurrentUIState(); 194 195 ok( 196 !currentUIState.splitterVisibility, 197 "Splitter is hidden when console is opened." 198 ); 199 is( 200 currentUIState.deckHeight, 201 currentUIState.webconsoleHeight, 202 "Deck has the same height as console" 203 ); 204 is( 205 currentUIState.webconsoleHeight, 206 currentUIState.containerHeight, 207 "Web console is full height." 208 ); 209 ok( 210 !currentUIState.isDeckVisible, 211 "Deck is hidden when the Web console is opened" 212 ); 213 ok(currentUIState.isConsoleVisible, "Web console is visible."); 214 ok( 215 currentUIState.openedConsolePanel, 216 "The console panel is the current tool" 217 ); 218 is( 219 currentUIState.menuLabel, 220 undefined, 221 "The menu item is hidden when console is opened" 222 ); 223 224 // Make sure splitting console does nothing while webconsole is opened 225 await toolbox.toggleSplitConsole(); 226 227 currentUIState = await getCurrentUIState(); 228 229 ok( 230 !currentUIState.splitterVisibility, 231 "Splitter is hidden when console is opened." 232 ); 233 is( 234 currentUIState.deckHeight, 235 currentUIState.webconsoleHeight, 236 "Deck has the same height as console" 237 ); 238 is( 239 currentUIState.webconsoleHeight, 240 currentUIState.containerHeight, 241 "Web console is full height." 242 ); 243 ok( 244 !currentUIState.isDeckVisible, 245 "Deck is hidden when the Web console is opened" 246 ); 247 ok(currentUIState.isConsoleVisible, "Web console is visible."); 248 ok( 249 currentUIState.openedConsolePanel, 250 "The console panel is the current tool" 251 ); 252 is( 253 currentUIState.menuLabel, 254 undefined, 255 "The menu item is hidden when console is opened" 256 ); 257 258 // Make sure that split state is saved after opening another panel 259 await openPanel("inspector"); 260 currentUIState = await getCurrentUIState(); 261 ok( 262 currentUIState.splitterVisibility, 263 "Splitter is visible when console is split" 264 ); 265 Assert.greater( 266 currentUIState.deckHeight, 267 0, 268 "Deck has a height > 0 when console is split" 269 ); 270 Assert.greater( 271 currentUIState.webconsoleHeight, 272 0, 273 "Web console has a height > 0 when console is split" 274 ); 275 ok(currentUIState.isDeckVisible, "Deck is visible when console is split"); 276 ok(currentUIState.isConsoleVisible, "Web console is visible."); 277 ok( 278 !currentUIState.openedConsolePanel, 279 "The console panel is not the current tool" 280 ); 281 is( 282 currentUIState.menuLabel, 283 "hide", 284 "The menu item still indicates the console is split" 285 ); 286 287 await toolbox.toggleSplitConsole(); 288 } 289 290 async function checkToolboxUI() { 291 let currentUIState = await getCurrentUIState(); 292 293 ok(!currentUIState.splitterVisibility, "Splitter is hidden by default"); 294 is( 295 currentUIState.deckHeight, 296 currentUIState.containerHeight, 297 "Deck has a height > 0 by default" 298 ); 299 ok( 300 currentUIState.isDeckVisible, 301 "Deck is visible when the Web console is closed" 302 ); 303 ok(!currentUIState.isConsoleVisible, "Web console is hidden."); 304 ok( 305 !currentUIState.openedConsolePanel, 306 "The console panel is not the current tool" 307 ); 308 is( 309 currentUIState.menuLabel, 310 "split", 311 "The menu item indicates the console is not split" 312 ); 313 314 await toolbox.toggleSplitConsole(); 315 316 currentUIState = await getCurrentUIState(); 317 318 ok( 319 currentUIState.splitterVisibility, 320 "Splitter is visible when console is split" 321 ); 322 Assert.greater( 323 currentUIState.deckHeight, 324 0, 325 "Deck has a height > 0 when console is split" 326 ); 327 Assert.greater( 328 currentUIState.webconsoleHeight, 329 0, 330 "Web console has a height > 0 when console is split" 331 ); 332 ok(currentUIState.isDeckVisible, "Deck is visible when console is split"); 333 ok(currentUIState.isConsoleVisible, "Web console is visible."); 334 is( 335 Math.round( 336 currentUIState.deckHeight + 337 currentUIState.webconsoleHeight + 338 currentUIState.splitterHeight 339 ), 340 Math.round(currentUIState.containerHeight), 341 "Everything adds up to container height" 342 ); 343 ok( 344 !currentUIState.openedConsolePanel, 345 "The console panel is not the current tool" 346 ); 347 is( 348 currentUIState.menuLabel, 349 "hide", 350 "The menu item indicates the console is split" 351 ); 352 353 await toolbox.toggleSplitConsole(); 354 355 currentUIState = await getCurrentUIState(); 356 357 ok(!currentUIState.splitterVisibility, "Splitter is hidden after toggling"); 358 is( 359 currentUIState.deckHeight, 360 currentUIState.containerHeight, 361 "Deck has a height > 0 after toggling" 362 ); 363 ok(currentUIState.isDeckVisible, "Deck is visible when console is closed"); 364 ok( 365 !currentUIState.isConsoleVisible, 366 "Web console is hidden after toggling." 367 ); 368 ok( 369 !currentUIState.openedConsolePanel, 370 "The console panel is not the current tool" 371 ); 372 is( 373 currentUIState.menuLabel, 374 "split", 375 "The menu item indicates the console is not split" 376 ); 377 } 378 379 async function openPanel(toolId) { 380 const tab = gBrowser.selectedTab; 381 toolbox = await gDevTools.showToolboxForTab(tab, { toolId }); 382 } 383 384 async function openAndCheckPanel(toolId) { 385 await openPanel(toolId); 386 await checkToolboxUI(toolbox.getCurrentPanel()); 387 } 388 389 function checkHostType(hostType) { 390 is(toolbox.hostType, hostType, "host type is " + hostType); 391 392 const pref = Services.prefs.getCharPref("devtools.toolbox.host"); 393 is(pref, hostType, "host pref is " + hostType); 394 } 395 });