"use strict"; /** * Test keyboard navigation in the app menu panel. */ const {PanelView} = Cu.import("resource:///modules/PanelMultiView.jsm", {}); const kHelpButtonId = "appMenu-help-button"; add_task(async function testUpDownKeys() { let promise = promisePanelShown(window); PanelUI.show(); await promise; let buttons = PanelView.forNode(PanelUI.mainView).getNavigableElements(); for (let button of buttons) { if (button.disabled) continue; EventUtils.synthesizeKey("KEY_ArrowDown", { code: "ArrowDown" }); Assert.equal(document.commandDispatcher.focusedElement, button, "The correct button should be focused after navigating downward"); } EventUtils.synthesizeKey("KEY_ArrowDown", { code: "ArrowDown" }); Assert.equal(document.commandDispatcher.focusedElement, buttons[0], "Pressing upwards should cycle around and select the first button again"); for (let i = buttons.length - 1; i >= 0; --i) { let button = buttons[i]; if (button.disabled) continue; EventUtils.synthesizeKey("KEY_ArrowUp", { code: "ArrowUp" }); Assert.equal(document.commandDispatcher.focusedElement, button, "The first button should be focused after navigating upward"); } promise = promisePanelHidden(window); PanelUI.hide(); await promise; }); add_task(async function testEnterKeyBehaviors() { let promise = promisePanelShown(window); PanelUI.show(); await promise; let buttons = PanelView.forNode(PanelUI.mainView).getNavigableElements(); // Navigate to the 'Help' button, which points to a subview. EventUtils.synthesizeKey("KEY_ArrowUp", { code: "ArrowUp" }); let focusedElement = document.commandDispatcher.focusedElement; Assert.equal(focusedElement, buttons[buttons.length - 1], "The last button should be focused after navigating upward"); promise = BrowserTestUtils.waitForEvent(PanelUI.helpView, "ViewShown"); // Make sure the Help button is in focus. while (!focusedElement || !focusedElement.id || focusedElement.id != kHelpButtonId) { EventUtils.synthesizeKey("KEY_ArrowUp", { code: "ArrowUp" }); focusedElement = document.commandDispatcher.focusedElement; } EventUtils.synthesizeKey("VK_RETURN", { code: "Enter" }); await promise; let helpButtons = PanelView.forNode(PanelUI.helpView).getNavigableElements(); Assert.ok(helpButtons[0].classList.contains("subviewbutton-back"), "First button in help view should be a back button"); // For posterity, check navigating the subview using up/ down arrow keys as well. for (let i = helpButtons.length - 1; i >= 0; --i) { let button = helpButtons[i]; if (button.disabled) continue; EventUtils.synthesizeKey("KEY_ArrowUp", { code: "ArrowUp" }); focusedElement = document.commandDispatcher.focusedElement; Assert.equal(focusedElement, button, "The first button should be focused after navigating upward"); } // Make sure the back button is in focus again. while (focusedElement != helpButtons[0]) { EventUtils.synthesizeKey("KEY_ArrowDown", { code: "ArrowDown" }); focusedElement = document.commandDispatcher.focusedElement; } // The first button is the back button. Hittin Enter should navigate us back. promise = BrowserTestUtils.waitForEvent(PanelUI.mainView, "ViewShown"); EventUtils.synthesizeKey("VK_RETURN", { code: "Enter" }); await promise; // Let's test a 'normal' command button. focusedElement = document.commandDispatcher.focusedElement; const kFindButtonId = "appMenu-find-button"; while (!focusedElement || !focusedElement.id || focusedElement.id != kFindButtonId) { EventUtils.synthesizeKey("KEY_ArrowUp", { code: "ArrowUp" }); focusedElement = document.commandDispatcher.focusedElement; } Assert.equal(focusedElement.id, kFindButtonId, "Find button should be selected"); promise = promisePanelHidden(window); EventUtils.synthesizeKey("VK_RETURN", { code: "Enter" }); await promise; Assert.ok(!gFindBar.hidden, "Findbar should have opened"); gFindBar.close(); }); add_task(async function testLeftRightKeys() { let promise = promisePanelShown(window); PanelUI.show(); await promise; // Navigate to the 'Help' button, which points to a subview. let focusedElement = document.commandDispatcher.focusedElement; while (!focusedElement || !focusedElement.id || focusedElement.id != kHelpButtonId) { EventUtils.synthesizeKey("KEY_ArrowUp", { code: "ArrowUp" }); focusedElement = document.commandDispatcher.focusedElement; } Assert.equal(focusedElement.id, kHelpButtonId, "The last button should be focused after navigating upward"); // Hitting ArrowRight on a button that points to a subview should navigate us // there. promise = BrowserTestUtils.waitForEvent(PanelUI.helpView, "ViewShown"); EventUtils.synthesizeKey("KEY_ArrowRight", { code: "ArrowRight" }); await promise; // Hitting ArrowLeft should navigate us back. promise = BrowserTestUtils.waitForEvent(PanelUI.mainView, "ViewShown"); EventUtils.synthesizeKey("KEY_ArrowLeft", { code: "ArrowLeft" }); await promise; focusedElement = document.commandDispatcher.focusedElement; Assert.equal(focusedElement.id, kHelpButtonId, "Help button should be focused again now that we're back in the main view"); promise = promisePanelHidden(window); PanelUI.hide(); await promise; }); add_task(async function testTabKey() { let promise = promisePanelShown(window); PanelUI.show(); await promise; let buttons = PanelView.forNode(PanelUI.mainView).getNavigableElements(); for (let button of buttons) { if (button.disabled) continue; EventUtils.synthesizeKey("KEY_Tab", { code: "Tab" }); Assert.equal(document.commandDispatcher.focusedElement, button, "The correct button should be focused after tabbing"); } EventUtils.synthesizeKey("KEY_Tab", { code: "Tab" }); Assert.equal(document.commandDispatcher.focusedElement, buttons[0], "Pressing tab should cycle around and select the first button again"); for (let i = buttons.length - 1; i >= 0; --i) { let button = buttons[i]; if (button.disabled) continue; EventUtils.synthesizeKey("Tab", { code: "Tab", shiftKey: true }); Assert.equal(document.commandDispatcher.focusedElement, button, "The correct button should be focused after shift + tabbing"); } EventUtils.synthesizeKey("KEY_Tab", { code: "Tab", shiftKey: true }); Assert.equal(document.commandDispatcher.focusedElement, buttons[buttons.length - 1], "Pressing shift + tab should cycle around and select the last button again"); promise = promisePanelHidden(window); PanelUI.hide(); await promise; }); add_task(async function testInterleavedTabAndArrowKeys() { let promise = promisePanelShown(window); PanelUI.show(); await promise; let buttons = PanelView.forNode(PanelUI.mainView).getNavigableElements(); let tab = false; for (let button of buttons) { if (button.disabled) continue; if (tab) { EventUtils.synthesizeKey("KEY_Tab", { code: "Tab" }); } else { EventUtils.synthesizeKey("KEY_ArrowDown", { code: "ArrowDown" }); } tab = !tab; } Assert.equal(document.commandDispatcher.focusedElement, buttons[buttons.length - 1], "The last button should be focused after a mix of Tab and ArrowDown"); promise = promisePanelHidden(window); PanelUI.hide(); await promise; }); add_task(async function testSpaceDownAfterTabNavigation() { let promise = promisePanelShown(window); PanelUI.show(); await promise; let buttons = PanelView.forNode(PanelUI.mainView).getNavigableElements(); let button; for (button of buttons) { if (button.disabled) continue; EventUtils.synthesizeKey("KEY_Tab", { code: "Tab" }); if (button.id == kHelpButtonId) { break; } } Assert.equal(document.commandDispatcher.focusedElement, button, "Help button should be focused after tabbing to it."); // Pressing down space on a button that points to a subview should navigate us // there, before keyup. promise = BrowserTestUtils.waitForEvent(PanelUI.helpView, "ViewShown"); EventUtils.synthesizeKey(" ", { code: "Space", type: "keydown" }); await promise; promise = promisePanelHidden(window); PanelUI.hide(); await promise; });