tor-browser

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

browser_autocomplete_popup.js (4092B)


      1 /* Any copyright is dedicated to the Public Domain.
      2 * http://creativecommons.org/publicdomain/zero/1.0/ */
      3 
      4 "use strict";
      5 
      6 add_task(async function () {
      7  const AutocompletePopup = require("resource://devtools/client/shared/autocomplete-popup.js");
      8 
      9  info("Create an autocompletion popup");
     10  const { doc } = await createHost();
     11  const input = doc.createElement("input");
     12  doc.body.appendChild(input);
     13 
     14  const autocompleteOptions = {
     15    position: "top",
     16    autoSelect: true,
     17  };
     18  const popup = new AutocompletePopup(doc, autocompleteOptions);
     19  input.focus();
     20 
     21  const items = [
     22    { label: "item0", value: "value0" },
     23    { label: "item1", value: "value1" },
     24    { label: "item2", value: "value2" },
     25  ];
     26 
     27  ok(!popup.isOpen, "popup is not open");
     28  ok(!input.hasAttribute("aria-activedescendant"), "no aria-activedescendant");
     29 
     30  const onPopupOpen = popup.once("popup-opened");
     31  popup.openPopup(input);
     32  await onPopupOpen;
     33 
     34  ok(popup.isOpen, "popup is open");
     35  is(popup.itemCount, 0, "no items");
     36  ok(!input.hasAttribute("aria-activedescendant"), "no aria-activedescendant");
     37 
     38  popup.setItems(items);
     39 
     40  is(popup.itemCount, items.length, "items added");
     41  is(
     42    JSON.stringify(popup.getItems()),
     43    JSON.stringify(items),
     44    "getItems returns back the same items"
     45  );
     46  is(popup.selectedIndex, 0, "Index of the first item from top is selected.");
     47  is(popup.selectedItem, items[0], "First item from top is selected");
     48  // Make sure the list containing the active descendant doesn't get rebuilt
     49  // when the selected item changes.
     50  const listClone = getListFromActiveDescendant(popup, input);
     51  checkActiveDescendant(popup, input, listClone);
     52 
     53  popup.selectItemAtIndex(1);
     54 
     55  is(popup.selectedIndex, 1, "index 1 is selected");
     56  is(popup.selectedItem, items[1], "item1 is selected");
     57  checkActiveDescendant(popup, input, listClone);
     58 
     59  popup.selectedItem = items[2];
     60 
     61  is(popup.selectedIndex, 2, "index 2 is selected");
     62  is(popup.selectedItem, items[2], "item2 is selected");
     63  checkActiveDescendant(popup, input, listClone);
     64 
     65  is(popup.selectPreviousItem(), items[1], "selectPreviousItem() works");
     66 
     67  is(popup.selectedIndex, 1, "index 1 is selected");
     68  is(popup.selectedItem, items[1], "item1 is selected");
     69  checkActiveDescendant(popup, input, listClone);
     70 
     71  is(popup.selectNextItem(), items[2], "selectNextItem() works");
     72 
     73  is(popup.selectedIndex, 2, "index 2 is selected");
     74  is(popup.selectedItem, items[2], "item2 is selected");
     75  checkActiveDescendant(popup, input, listClone);
     76 
     77  ok(popup.selectNextItem(), "selectNextItem() works");
     78 
     79  is(popup.selectedIndex, 0, "index 0 is selected");
     80  is(popup.selectedItem, items[0], "item0 is selected");
     81  checkActiveDescendant(popup, input, listClone);
     82 
     83  popup.clearItems();
     84  is(popup.itemCount, 0, "items cleared");
     85  ok(!input.hasAttribute("aria-activedescendant"), "no aria-activedescendant");
     86 
     87  const onPopupClose = popup.once("popup-closed");
     88  popup.hidePopup();
     89  await onPopupClose;
     90 });
     91 
     92 function stripNS(text) {
     93  return text.replace(RegExp(' xmlns="http://www.w3.org/1999/xhtml"', "g"), "");
     94 }
     95 
     96 function getListFromActiveDescendant(popup, input) {
     97  const activeElement = input.ownerDocument.activeElement;
     98  const descendantId = activeElement.getAttribute("aria-activedescendant");
     99  const cloneItem = input.ownerDocument.querySelector("#" + descendantId);
    100  return cloneItem.parentNode;
    101 }
    102 
    103 function checkActiveDescendant(popup, input, list) {
    104  const activeElement = input.ownerDocument.activeElement;
    105  const descendantId = activeElement.getAttribute("aria-activedescendant");
    106  const popupItem = popup.tooltip.panel.querySelector("#" + descendantId);
    107  const cloneItem = input.ownerDocument.querySelector("#" + descendantId);
    108 
    109  ok(popupItem, "Active descendant is found in the popup list");
    110  ok(cloneItem, "Active descendant is found in the list clone");
    111  is(
    112    cloneItem.parentNode,
    113    list,
    114    "Active descendant is a child of the expected list"
    115  );
    116  is(
    117    stripNS(popupItem.outerHTML),
    118    cloneItem.outerHTML,
    119    "Cloned item has the same HTML as the original element"
    120  );
    121 }