tor-browser

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

browser_panel_keyboard_navigation.js (9369B)


      1 "use strict";
      2 
      3 /**
      4 * Test keyboard navigation in the app menu panel.
      5 */
      6 
      7 const kHelpButtonId = "appMenu-help-button2";
      8 
      9 function getEnabledNavigableElementsForView(panelView) {
     10  return Array.from(
     11    panelView.querySelectorAll("button,toolbarbutton,menulist,.text-link")
     12  ).filter(element => {
     13    let bounds = element.getBoundingClientRect();
     14    return !element.disabled && bounds.width > 0 && bounds.height > 0;
     15  });
     16 }
     17 
     18 add_task(async function testUpDownKeys() {
     19  await gCUITestUtils.openMainMenu();
     20 
     21  let buttons = getEnabledNavigableElementsForView(PanelUI.mainView);
     22 
     23  for (let button of buttons) {
     24    if (button.disabled) {
     25      continue;
     26    }
     27    EventUtils.synthesizeKey("KEY_ArrowDown");
     28    Assert.equal(
     29      document.commandDispatcher.focusedElement,
     30      button,
     31      "The correct button should be focused after navigating downward"
     32    );
     33  }
     34 
     35  EventUtils.synthesizeKey("KEY_ArrowDown");
     36  Assert.equal(
     37    document.commandDispatcher.focusedElement,
     38    buttons[0],
     39    "Pressing upwards should cycle around and select the first button again"
     40  );
     41 
     42  for (let i = buttons.length - 1; i >= 0; --i) {
     43    let button = buttons[i];
     44    if (button.disabled) {
     45      continue;
     46    }
     47    EventUtils.synthesizeKey("KEY_ArrowUp");
     48    Assert.equal(
     49      document.commandDispatcher.focusedElement,
     50      button,
     51      "The first button should be focused after navigating upward"
     52    );
     53  }
     54 
     55  await gCUITestUtils.hideMainMenu();
     56 });
     57 
     58 add_task(async function testHomeEndKeys() {
     59  await gCUITestUtils.openMainMenu();
     60 
     61  let buttons = getEnabledNavigableElementsForView(PanelUI.mainView);
     62  let enabledButtons = buttons.filter(btn => !btn.disabled);
     63  let firstButton = enabledButtons[0];
     64  let lastButton = enabledButtons.pop();
     65 
     66  Assert.notEqual(firstButton, lastButton, "There is more than one button");
     67 
     68  EventUtils.synthesizeKey("KEY_End");
     69  Assert.equal(
     70    document.commandDispatcher.focusedElement,
     71    lastButton,
     72    "The last button should be focused after pressing End"
     73  );
     74 
     75  EventUtils.synthesizeKey("KEY_Home");
     76  Assert.equal(
     77    document.commandDispatcher.focusedElement,
     78    firstButton,
     79    "The first button should be focused after pressing Home"
     80  );
     81 
     82  await gCUITestUtils.hideMainMenu();
     83 });
     84 
     85 add_task(async function testEnterKeyBehaviors() {
     86  await gCUITestUtils.openMainMenu();
     87 
     88  let buttons = getEnabledNavigableElementsForView(PanelUI.mainView);
     89 
     90  // Navigate to the 'Help' button, which points to a subview.
     91  EventUtils.synthesizeKey("KEY_ArrowUp");
     92  let focusedElement = document.commandDispatcher.focusedElement;
     93  Assert.equal(
     94    focusedElement,
     95    buttons[buttons.length - 1],
     96    "The last button should be focused after navigating upward"
     97  );
     98 
     99  // Make sure the Help button is in focus.
    100  while (
    101    !focusedElement ||
    102    !focusedElement.id ||
    103    focusedElement.id != kHelpButtonId
    104  ) {
    105    EventUtils.synthesizeKey("KEY_ArrowUp");
    106    focusedElement = document.commandDispatcher.focusedElement;
    107  }
    108  EventUtils.synthesizeKey("KEY_Enter");
    109 
    110  let helpView = document.getElementById("PanelUI-helpView");
    111  await BrowserTestUtils.waitForEvent(helpView, "ViewShown");
    112 
    113  let helpButtons = getEnabledNavigableElementsForView(helpView);
    114  Assert.ok(
    115    helpButtons[0].classList.contains("subviewbutton-back"),
    116    "First button in help view should be a back button"
    117  );
    118 
    119  // For posterity, check navigating the subview using up/ down arrow keys as well.
    120  // When opening a subview, the first control *after* the Back button gets
    121  // focus.
    122  EventUtils.synthesizeKey("KEY_ArrowUp");
    123  focusedElement = document.commandDispatcher.focusedElement;
    124  Assert.equal(
    125    focusedElement,
    126    helpButtons[0],
    127    "The Back button should be focused after navigating upward"
    128  );
    129  for (let i = helpButtons.length - 1; i >= 0; --i) {
    130    let button = helpButtons[i];
    131    if (button.disabled) {
    132      continue;
    133    }
    134    EventUtils.synthesizeKey("KEY_ArrowUp");
    135    focusedElement = document.commandDispatcher.focusedElement;
    136    Assert.equal(
    137      focusedElement,
    138      button,
    139      "The previous button should be focused after navigating upward"
    140    );
    141  }
    142 
    143  // Make sure the back button is in focus again.
    144  while (focusedElement != helpButtons[0]) {
    145    EventUtils.synthesizeKey("KEY_ArrowDown");
    146    focusedElement = document.commandDispatcher.focusedElement;
    147  }
    148 
    149  // The first button is the back button. Hittin Enter should navigate us back.
    150  let promise = BrowserTestUtils.waitForEvent(PanelUI.mainView, "ViewShown");
    151  EventUtils.synthesizeKey("KEY_Enter");
    152  await promise;
    153 
    154  // Let's test a 'normal' command button.
    155  focusedElement = document.commandDispatcher.focusedElement;
    156  const kFindButtonId = "appMenu-find-button2";
    157  while (
    158    !focusedElement ||
    159    !focusedElement.id ||
    160    focusedElement.id != kFindButtonId
    161  ) {
    162    EventUtils.synthesizeKey("KEY_ArrowUp");
    163    focusedElement = document.commandDispatcher.focusedElement;
    164  }
    165  let findBarPromise = gBrowser.isFindBarInitialized()
    166    ? null
    167    : BrowserTestUtils.waitForEvent(gBrowser.selectedTab, "TabFindInitialized");
    168  Assert.equal(
    169    focusedElement.id,
    170    kFindButtonId,
    171    "Find button should be selected"
    172  );
    173 
    174  await gCUITestUtils.hidePanelMultiView(PanelUI.panel, () =>
    175    EventUtils.synthesizeKey("KEY_Enter")
    176  );
    177 
    178  await findBarPromise;
    179  Assert.ok(!gFindBar.hidden, "Findbar should have opened");
    180  gFindBar.close();
    181 });
    182 
    183 add_task(async function testLeftRightKeys() {
    184  await gCUITestUtils.openMainMenu();
    185 
    186  // Navigate to the 'Help' button, which points to a subview.
    187  let focusedElement = document.commandDispatcher.focusedElement;
    188  while (
    189    !focusedElement ||
    190    !focusedElement.id ||
    191    focusedElement.id != kHelpButtonId
    192  ) {
    193    EventUtils.synthesizeKey("KEY_ArrowUp");
    194    focusedElement = document.commandDispatcher.focusedElement;
    195  }
    196  Assert.equal(
    197    focusedElement.id,
    198    kHelpButtonId,
    199    "The last button should be focused after navigating upward"
    200  );
    201 
    202  // Hitting ArrowRight on a button that points to a subview should navigate us
    203  // there.
    204  EventUtils.synthesizeKey("KEY_ArrowRight");
    205  let helpView = document.getElementById("PanelUI-helpView");
    206  await BrowserTestUtils.waitForEvent(helpView, "ViewShown");
    207 
    208  // Hitting ArrowLeft should navigate us back.
    209  let promise = BrowserTestUtils.waitForEvent(PanelUI.mainView, "ViewShown");
    210  EventUtils.synthesizeKey("KEY_ArrowLeft");
    211  await promise;
    212 
    213  focusedElement = document.commandDispatcher.focusedElement;
    214  Assert.equal(
    215    focusedElement.id,
    216    kHelpButtonId,
    217    "Help button should be focused again now that we're back in the main view"
    218  );
    219 
    220  await gCUITestUtils.hideMainMenu();
    221 });
    222 
    223 add_task(async function testTabKey() {
    224  await gCUITestUtils.openMainMenu();
    225 
    226  let buttons = getEnabledNavigableElementsForView(PanelUI.mainView);
    227 
    228  for (let button of buttons) {
    229    if (button.disabled) {
    230      continue;
    231    }
    232    EventUtils.synthesizeKey("KEY_Tab");
    233    Assert.equal(
    234      document.commandDispatcher.focusedElement,
    235      button,
    236      "The correct button should be focused after tabbing"
    237    );
    238  }
    239 
    240  EventUtils.synthesizeKey("KEY_Tab");
    241  Assert.equal(
    242    document.commandDispatcher.focusedElement,
    243    buttons[0],
    244    "Pressing tab should cycle around and select the first button again"
    245  );
    246 
    247  for (let i = buttons.length - 1; i >= 0; --i) {
    248    let button = buttons[i];
    249    if (button.disabled) {
    250      continue;
    251    }
    252    EventUtils.synthesizeKey("KEY_Tab", { shiftKey: true });
    253    Assert.equal(
    254      document.commandDispatcher.focusedElement,
    255      button,
    256      "The correct button should be focused after shift + tabbing"
    257    );
    258  }
    259 
    260  EventUtils.synthesizeKey("KEY_Tab", { shiftKey: true });
    261  Assert.equal(
    262    document.commandDispatcher.focusedElement,
    263    buttons[buttons.length - 1],
    264    "Pressing shift + tab should cycle around and select the last button again"
    265  );
    266 
    267  await gCUITestUtils.hideMainMenu();
    268 });
    269 
    270 add_task(async function testInterleavedTabAndArrowKeys() {
    271  await gCUITestUtils.openMainMenu();
    272 
    273  let buttons = getEnabledNavigableElementsForView(PanelUI.mainView);
    274  let tab = false;
    275 
    276  for (let button of buttons) {
    277    if (button.disabled) {
    278      continue;
    279    }
    280    if (tab) {
    281      EventUtils.synthesizeKey("KEY_Tab");
    282    } else {
    283      EventUtils.synthesizeKey("KEY_ArrowDown");
    284    }
    285    tab = !tab;
    286  }
    287 
    288  Assert.equal(
    289    document.commandDispatcher.focusedElement,
    290    buttons[buttons.length - 1],
    291    "The last button should be focused after a mix of Tab and ArrowDown"
    292  );
    293 
    294  await gCUITestUtils.hideMainMenu();
    295 });
    296 
    297 add_task(async function testSpaceDownAfterTabNavigation() {
    298  await gCUITestUtils.openMainMenu();
    299 
    300  let buttons = getEnabledNavigableElementsForView(PanelUI.mainView);
    301  let button;
    302 
    303  for (button of buttons) {
    304    if (button.disabled) {
    305      continue;
    306    }
    307    EventUtils.synthesizeKey("KEY_Tab");
    308    if (button.id == kHelpButtonId) {
    309      break;
    310    }
    311  }
    312 
    313  Assert.equal(
    314    document.commandDispatcher.focusedElement,
    315    button,
    316    "Help button should be focused after tabbing to it."
    317  );
    318 
    319  // Pressing down space on a button that points to a subview should navigate us
    320  // there, before keyup.
    321  EventUtils.synthesizeKey(" ", { type: "keydown" });
    322  let helpView = document.getElementById("PanelUI-helpView");
    323  await BrowserTestUtils.waitForEvent(helpView, "ViewShown");
    324 
    325  await gCUITestUtils.hideMainMenu();
    326 });