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 }