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