From 6bf0a5cb5034a7e684dcc3500e841785237ce2dd Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 19:32:43 +0200 Subject: Adding upstream version 1:115.7.0. Signed-off-by: Daniel Baumann --- .../browser_unified_extensions_accessibility.js | 302 +++++++++++++++++++++ 1 file changed, 302 insertions(+) create mode 100644 browser/components/extensions/test/browser/browser_unified_extensions_accessibility.js (limited to 'browser/components/extensions/test/browser/browser_unified_extensions_accessibility.js') diff --git a/browser/components/extensions/test/browser/browser_unified_extensions_accessibility.js b/browser/components/extensions/test/browser/browser_unified_extensions_accessibility.js new file mode 100644 index 0000000000..fccc77b8a9 --- /dev/null +++ b/browser/components/extensions/test/browser/browser_unified_extensions_accessibility.js @@ -0,0 +1,302 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +loadTestSubscript("head_unified_extensions.js"); + +add_task(async function test_keyboard_navigation_activeScript() { + const extension1 = ExtensionTestUtils.loadExtension({ + manifest: { + manifest_version: 3, + name: "1", + content_scripts: [ + { + matches: ["*://*/*"], + js: ["script.js"], + }, + ], + }, + files: { + "script.js": () => { + browser.test.fail("this script should NOT have been executed"); + }, + }, + useAddonManager: "temporary", + }); + const extension2 = ExtensionTestUtils.loadExtension({ + manifest: { + manifest_version: 3, + name: "2", + content_scripts: [ + { + matches: ["*://*/*"], + js: ["script.js"], + }, + ], + }, + files: { + "script.js": () => { + browser.test.sendMessage("script executed"); + }, + }, + useAddonManager: "temporary", + }); + + BrowserTestUtils.loadURIString( + gBrowser.selectedBrowser, + "https://example.org/" + ); + await BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser); + + await Promise.all([extension1.startup(), extension2.startup()]); + + // Open the extension panel. + await openExtensionsPanel(); + + let item = getUnifiedExtensionsItem(extension1.id); + ok(item, `expected item for ${extension1.id}`); + + info("moving focus to first item in the unified extensions panel"); + let actionButton = item.querySelector( + ".unified-extensions-item-action-button" + ); + let focused = BrowserTestUtils.waitForEvent(actionButton, "focus"); + EventUtils.synthesizeKey("VK_TAB", {}); + await focused; + is( + actionButton, + document.activeElement, + "expected action button of first extension item to be focused" + ); + + item = getUnifiedExtensionsItem(extension2.id); + ok(item, `expected item for ${extension2.id}`); + + info("moving focus to second item in the unified extensions panel"); + actionButton = item.querySelector(".unified-extensions-item-action-button"); + focused = BrowserTestUtils.waitForEvent(actionButton, "focus"); + EventUtils.synthesizeKey("KEY_ArrowDown", {}); + await focused; + is( + actionButton, + document.activeElement, + "expected action button of second extension item to be focused" + ); + + info("granting permission"); + const popupHidden = BrowserTestUtils.waitForEvent( + document, + "popuphidden", + true + ); + EventUtils.synthesizeKey(" ", {}); + await Promise.all([popupHidden, extension2.awaitMessage("script executed")]); + + await Promise.all([extension1.unload(), extension2.unload()]); +}); + +add_task(async function test_keyboard_navigation_opens_menu() { + const extension1 = ExtensionTestUtils.loadExtension({ + manifest: { + name: "1", + // activeTab and browser_action needed to enable the action button in mv2. + permissions: ["activeTab"], + browser_action: {}, + }, + useAddonManager: "temporary", + }); + const extension2 = ExtensionTestUtils.loadExtension({ + manifest: { + name: "2", + }, + useAddonManager: "temporary", + }); + const extension3 = ExtensionTestUtils.loadExtension({ + manifest: { + manifest_version: 3, + name: "3", + // activeTab enables the action button without a browser action in mv3. + permissions: ["activeTab"], + }, + useAddonManager: "temporary", + }); + + await extension1.startup(); + await extension2.startup(); + await extension3.startup(); + + // Open the extension panel. + await openExtensionsPanel(); + + let item = getUnifiedExtensionsItem(extension1.id); + ok(item, `expected item for ${extension1.id}`); + + let messageDeck = item.querySelector(".unified-extensions-item-message-deck"); + ok(messageDeck, "expected a message deck element"); + is( + messageDeck.selectedIndex, + gUnifiedExtensions.MESSAGE_DECK_INDEX_DEFAULT, + "expected selected message in the deck to be the default message" + ); + + info("moving focus to first item in the unified extensions panel"); + let actionButton = item.querySelector( + ".unified-extensions-item-action-button" + ); + let focused = BrowserTestUtils.waitForEvent(actionButton, "focus"); + EventUtils.synthesizeKey("VK_TAB", {}); + await focused; + is( + actionButton, + document.activeElement, + "expected action button of the first extension item to be focused" + ); + is( + messageDeck.selectedIndex, + gUnifiedExtensions.MESSAGE_DECK_INDEX_HOVER, + "expected selected message in the deck to be the hover message" + ); + + info( + "moving focus to menu button of the first item in the unified extensions panel" + ); + let menuButton = item.querySelector(".unified-extensions-item-menu-button"); + focused = BrowserTestUtils.waitForEvent(menuButton, "focus"); + ok(menuButton, "expected menu button"); + EventUtils.synthesizeKey("VK_TAB", {}); + await focused; + is( + menuButton, + document.activeElement, + "expected menu button in first extension item to be focused" + ); + is( + messageDeck.selectedIndex, + gUnifiedExtensions.MESSAGE_DECK_INDEX_MENU_HOVER, + "expected selected message in the deck to be the message when hovering the menu button" + ); + + info("opening menu of the first item"); + const contextMenu = document.getElementById( + "unified-extensions-context-menu" + ); + ok(contextMenu, "expected menu"); + const shown = BrowserTestUtils.waitForEvent(contextMenu, "popupshown"); + EventUtils.synthesizeKey(" ", {}); + await shown; + + await closeChromeContextMenu(contextMenu.id, null); + + info("moving focus back to the action button of the first item"); + focused = BrowserTestUtils.waitForEvent(actionButton, "focus"); + EventUtils.synthesizeKey("VK_TAB", { shiftKey: true }); + await focused; + is( + messageDeck.selectedIndex, + gUnifiedExtensions.MESSAGE_DECK_INDEX_HOVER, + "expected selected message in the deck to be the hover message" + ); + + // Moving to the third extension directly because the second extension cannot + // do anything on the current page and its action button is disabled. Note + // that this third extension does not have a browser action but it has + // "activeTab", which makes the extension "clickable". This allows us to + // verify the focus/blur behavior of custom elments. + info("moving focus to third item in the panel"); + item = getUnifiedExtensionsItem(extension3.id); + ok(item, `expected item for ${extension3.id}`); + actionButton = item.querySelector(".unified-extensions-item-action-button"); + ok(actionButton, `expected action button for ${extension3.id}`); + messageDeck = item.querySelector(".unified-extensions-item-message-deck"); + ok(messageDeck, `expected message deck for ${extension3.id}`); + is( + messageDeck.selectedIndex, + gUnifiedExtensions.MESSAGE_DECK_INDEX_DEFAULT, + "expected selected message in the deck to be the default message" + ); + // Now that we checked everything on this third extension, let's actually + // focus it with the arrow down key. + focused = BrowserTestUtils.waitForEvent(actionButton, "focus"); + EventUtils.synthesizeKey("KEY_ArrowDown", {}); + await focused; + is( + actionButton, + document.activeElement, + "expected action button of the third extension item to be focused" + ); + is( + messageDeck.selectedIndex, + gUnifiedExtensions.MESSAGE_DECK_INDEX_HOVER, + "expected selected message in the deck to be the hover message" + ); + + info( + "moving focus to menu button of the third item in the unified extensions panel" + ); + menuButton = item.querySelector(".unified-extensions-item-menu-button"); + focused = BrowserTestUtils.waitForEvent(menuButton, "focus"); + ok(menuButton, "expected menu button"); + EventUtils.synthesizeKey("VK_TAB", {}); + await focused; + is( + menuButton, + document.activeElement, + "expected menu button in third extension item to be focused" + ); + is( + messageDeck.selectedIndex, + gUnifiedExtensions.MESSAGE_DECK_INDEX_MENU_HOVER, + "expected selected message in the deck to be the message when hovering the menu button" + ); + + info("moving focus back to the action button of the third item"); + focused = BrowserTestUtils.waitForEvent(actionButton, "focus"); + EventUtils.synthesizeKey("VK_TAB", { shiftKey: true }); + await focused; + is( + messageDeck.selectedIndex, + gUnifiedExtensions.MESSAGE_DECK_INDEX_HOVER, + "expected selected message in the deck to be the hover message" + ); + + await closeExtensionsPanel(); + + await extension1.unload(); + await extension2.unload(); + await extension3.unload(); +}); + +add_task(async function test_open_panel_with_keyboard_navigation() { + const { button, panel } = gUnifiedExtensions; + ok(button, "expected button"); + ok(panel, "expected panel"); + + const listView = getListView(); + ok(listView, "expected list view"); + + // Force focus on the unified extensions button. + const forceFocusUnifiedExtensionsButton = () => { + button.setAttribute("tabindex", "-1"); + button.focus(); + button.removeAttribute("tabindex"); + }; + forceFocusUnifiedExtensionsButton(); + + // Use the "space" key to open the panel. + let viewShown = BrowserTestUtils.waitForEvent(listView, "ViewShown"); + EventUtils.synthesizeKey(" ", {}); + await viewShown; + + await closeExtensionsPanel(); + + // Force focus on the unified extensions button again. + forceFocusUnifiedExtensionsButton(); + + // Use the "return" key to open the panel. + viewShown = BrowserTestUtils.waitForEvent(listView, "ViewShown"); + EventUtils.synthesizeKey("KEY_Enter", {}); + await viewShown; + + await closeExtensionsPanel(); +}); -- cgit v1.2.3