tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

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 });