tor-browser

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

browser_sidebar_switcher.js (9058B)


      1 /* Any copyright is dedicated to the Public Domain.
      2 * https://creativecommons.org/publicdomain/zero/1.0/ */
      3 
      4 "use strict";
      5 
      6 add_setup(async function () {
      7  /* This test exercises the sidebar switcher -
      8  which is only available under the legacy sidebar. */
      9  await SpecialPowers.pushPrefEnv({
     10    set: [["sidebar.revamp", false]],
     11  });
     12 });
     13 
     14 registerCleanupFunction(() => {
     15  SidebarController.hide();
     16 });
     17 
     18 /**
     19 * Helper function that opens a sidebar switcher panel popup menu
     20 *
     21 * @returns Promise that resolves when the switcher panel popup is shown
     22 *          without any action from a user/test
     23 */
     24 function showSwitcherPanelPromise() {
     25  return new Promise(resolve => {
     26    SidebarController._switcherPanel.addEventListener(
     27      "popupshown",
     28      () => {
     29        resolve();
     30      },
     31      { once: true }
     32    );
     33    SidebarController.showSwitcherPanel();
     34  });
     35 }
     36 
     37 /**
     38 * Helper function that waits for a sidebar switcher panel's "popupshown" event
     39 *
     40 * @returns Promise which resolves when the popup menu is opened
     41 */
     42 async function waitForSwitcherPopupShown() {
     43  return BrowserTestUtils.waitForEvent(
     44    SidebarController._switcherPanel,
     45    "popupshown"
     46  );
     47 }
     48 
     49 /**
     50 * Helper function that sends a mouse click to a specific menu item or a key
     51 * event to a active menu item of the sidebar switcher menu popup. Provide a
     52 * querySelector parameter when a click behavior is needed.
     53 *
     54 * @param {string} [querySelector=null]  An HTML attribute of the menu item
     55 *                                       to be clicked
     56 * @returns Promise that resolves when both the menu popup is hidden and
     57 *          the sidebar itself is focused
     58 */
     59 function pickSwitcherMenuitem(querySelector = null) {
     60  let sidebarPopup = document.querySelector("#sidebarMenu-popup");
     61  let hideSwitcherPanelPromise = Promise.all([
     62    BrowserTestUtils.waitForEvent(window, "SidebarFocused"),
     63    BrowserTestUtils.waitForEvent(sidebarPopup, "popuphidden"),
     64  ]);
     65  if (querySelector) {
     66    document.querySelector(querySelector).click();
     67  } else {
     68    EventUtils.synthesizeKey("KEY_Enter", {});
     69  }
     70  return hideSwitcherPanelPromise;
     71 }
     72 
     73 /**
     74 * Helper function to test a key handling of sidebar menu popup items used to
     75 * access a specific sidebar
     76 *
     77 * @param {string} key           Event.key to open the switcher menu popup
     78 * @param {string} sidebarTitle  Title of the sidebar that is to be activated
     79 *                               during the test (capitalized one word versions),
     80 *                               i.e. "History" or "Tabs"
     81 */
     82 async function testSidebarMenuKeyToggle(key, sidebarTitle) {
     83  info(`Testing "${key}" key handling of sidebar menu popup items
     84  to access ${sidebarTitle} sidebar`);
     85 
     86  Assert.ok(SidebarController.isOpen, "Sidebar is open");
     87 
     88  let sidebarSwitcher = document.querySelector("#sidebar-switcher-target");
     89  let sidebar = document.getElementById("sidebar");
     90  let searchBox = sidebar.firstElementChild;
     91 
     92  // If focus is on the search field (i.e. on the History sidebar),
     93  // or if the focus is on the awesomebar (bug 1835899),
     94  // move it to the switcher target:
     95 
     96  if (searchBox && searchBox.matches(":focus")) {
     97    EventUtils.synthesizeKey("KEY_Tab", { shiftKey: true, repeat: 2 });
     98  } else if (!sidebarSwitcher.matches(":focus")) {
     99    sidebarSwitcher.focus();
    100  }
    101 
    102  Assert.equal(
    103    document.activeElement,
    104    sidebarSwitcher,
    105    "The sidebar switcher target button is focused"
    106  );
    107  Assert.ok(
    108    sidebarSwitcher.matches(":focus"),
    109    "The sidebar switcher target button is focused"
    110  );
    111  Assert.equal(
    112    SidebarController._switcherPanel.state,
    113    "closed",
    114    "Sidebar menu popup is closed"
    115  );
    116 
    117  let promisePopupShown = waitForSwitcherPopupShown();
    118 
    119  // Activate sidebar switcher target to open its sidebar menu popup:
    120  EventUtils.synthesizeKey(key, {});
    121 
    122  await promisePopupShown;
    123 
    124  Assert.equal(
    125    SidebarController._switcherPanel.state,
    126    "open",
    127    "Sidebar menu popup is open"
    128  );
    129 
    130  info("Testing keyboard navigation between sidebar menu popup controls");
    131 
    132  let arrowDown = async (menuitemId, msg) => {
    133    let menuItemActive = BrowserTestUtils.waitForEvent(
    134      SidebarController._switcherPanel,
    135      "DOMMenuItemActive"
    136    );
    137    EventUtils.synthesizeKey("KEY_ArrowDown", {});
    138    await menuItemActive;
    139    Assert.ok(
    140      document.getElementById(menuitemId).hasAttribute("_moz-menuactive"),
    141      msg
    142    );
    143  };
    144 
    145  // Move to the first sidebar switcher option:
    146  await arrowDown(
    147    "sidebar-switcher-bookmarks",
    148    "The 1st sidebar menu item (Bookmarks) is active"
    149  );
    150 
    151  // Move to the next sidebar switcher option:
    152  await arrowDown(
    153    "sidebar-switcher-history",
    154    "The 2nd sidebar menu item (History) is active"
    155  );
    156 
    157  if (sidebarTitle === "Tabs") {
    158    await arrowDown(
    159      "sidebar-switcher-tabs",
    160      "The 3rd sidebar menu item (Synced Tabs) is active"
    161    );
    162  }
    163 
    164  // Activate the tested sidebar switcher option to open the tested sidebar:
    165  let sidebarShown = BrowserTestUtils.waitForEvent(window, "SidebarShown");
    166  await pickSwitcherMenuitem(/* querySelector = */ null);
    167  await sidebarShown;
    168 
    169  info("Testing keyboard navigation when a sidebar menu popup is closed");
    170 
    171  Assert.equal(
    172    SidebarController._switcherPanel.state,
    173    "closed",
    174    "Sidebar menu popup is closed"
    175  );
    176  // Test the sidebar panel is updated
    177  Assert.equal(
    178    SidebarController._box.getAttribute("sidebarcommand"),
    179    `view${sidebarTitle}Sidebar` /* e.g. "viewHistorySidebar" */,
    180    `${sidebarTitle} sidebar loaded`
    181  );
    182  Assert.equal(
    183    SidebarController.currentID,
    184    `view${sidebarTitle}Sidebar` /* e.g. "viewHistorySidebar" */,
    185    `${sidebarTitle}'s current ID is updated to a target view`
    186  );
    187 }
    188 
    189 add_task(async function markup() {
    190  // If a sidebar is already open, close it.
    191  if (!document.getElementById("sidebar-box").hidden) {
    192    Assert.ok(
    193      false,
    194      "Unexpected sidebar found - a previous test failed to cleanup correctly"
    195    );
    196    SidebarController.hide();
    197  }
    198 
    199  let sidebarPopup = document.querySelector("#sidebarMenu-popup");
    200  let sidebarSwitcher = document.querySelector("#sidebar-switcher-target");
    201  let sidebarTitle = document.querySelector("#sidebar-title");
    202 
    203  info("Test default markup of the sidebar switcher control");
    204 
    205  Assert.equal(
    206    sidebarSwitcher.tagName,
    207    "toolbarbutton",
    208    "Sidebar switcher target control is a toolbarbutton"
    209  );
    210  Assert.equal(
    211    sidebarSwitcher.children[1],
    212    sidebarTitle,
    213    "Sidebar switcher target control has a child label element"
    214  );
    215  Assert.equal(
    216    sidebarTitle.tagName,
    217    "label",
    218    "Sidebar switcher target control has a label element (that is expected to provide its accessible name"
    219  );
    220  Assert.equal(
    221    sidebarSwitcher.getAttribute("aria-expanded"),
    222    "false",
    223    "Sidebar switcher button is collapsed by default"
    224  );
    225 
    226  info("Test dynamic changes in the markup of the sidebar switcher control");
    227 
    228  await SidebarController.show("viewBookmarksSidebar");
    229  await showSwitcherPanelPromise();
    230 
    231  Assert.equal(
    232    sidebarSwitcher.getAttribute("aria-expanded"),
    233    "true",
    234    "Sidebar switcher button is expanded when a sidebar menu is shown"
    235  );
    236 
    237  let waitForPopupHidden = BrowserTestUtils.waitForEvent(
    238    sidebarPopup,
    239    "popuphidden"
    240  );
    241 
    242  // Close on Escape anywhere
    243  EventUtils.synthesizeKey("KEY_Escape", {});
    244  await waitForPopupHidden;
    245 
    246  Assert.equal(
    247    sidebarSwitcher.getAttribute("aria-expanded"),
    248    "false",
    249    "Sidebar switcher button is collapsed when a sidebar menu is dismissed"
    250  );
    251 
    252  SidebarController.hide();
    253 });
    254 
    255 add_task(async function keynav() {
    256  // If a sidebar is already open, close it.
    257  if (SidebarController.isOpen) {
    258    Assert.ok(
    259      false,
    260      "Unexpected sidebar found - a previous test failed to cleanup correctly"
    261    );
    262    SidebarController.hide();
    263  }
    264 
    265  await SidebarController.show("viewBookmarksSidebar");
    266 
    267  await testSidebarMenuKeyToggle("KEY_Enter", "History");
    268  await testSidebarMenuKeyToggle(" ", "Tabs");
    269 
    270  SidebarController.hide();
    271 });
    272 
    273 add_task(async function mouse() {
    274  // If a sidebar is already open, close it.
    275  if (!document.getElementById("sidebar-box").hidden) {
    276    Assert.ok(
    277      false,
    278      "Unexpected sidebar found - a previous test failed to cleanup correctly"
    279    );
    280    SidebarController.hide();
    281  }
    282 
    283  let sidebar = document.querySelector("#sidebar-box");
    284  await SidebarController.show("viewBookmarksSidebar");
    285 
    286  await showSwitcherPanelPromise();
    287  await pickSwitcherMenuitem("#sidebar-switcher-history");
    288  Assert.equal(
    289    sidebar.getAttribute("sidebarcommand"),
    290    "viewHistorySidebar",
    291    "History sidebar loaded"
    292  );
    293 
    294  await showSwitcherPanelPromise();
    295  await pickSwitcherMenuitem("#sidebar-switcher-tabs");
    296  Assert.equal(
    297    sidebar.getAttribute("sidebarcommand"),
    298    "viewTabsSidebar",
    299    "Tabs sidebar loaded"
    300  );
    301 
    302  await showSwitcherPanelPromise();
    303  await pickSwitcherMenuitem("#sidebar-switcher-bookmarks");
    304  Assert.equal(
    305    sidebar.getAttribute("sidebarcommand"),
    306    "viewBookmarksSidebar",
    307    "Bookmarks sidebar loaded"
    308  );
    309 });