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/browser_PageActions_contextMenus.js | 226 +++++++++++++++++++++ 1 file changed, 226 insertions(+) create mode 100644 browser/modules/test/browser/browser_PageActions_contextMenus.js (limited to 'browser/modules/test/browser/browser_PageActions_contextMenus.js') diff --git a/browser/modules/test/browser/browser_PageActions_contextMenus.js b/browser/modules/test/browser/browser_PageActions_contextMenus.js new file mode 100644 index 0000000000..a76a5bcb16 --- /dev/null +++ b/browser/modules/test/browser/browser_PageActions_contextMenus.js @@ -0,0 +1,226 @@ +"use strict"; + +// This is a test for PageActions.jsm, specifically the context menus. + +ChromeUtils.defineESModuleGetters(this, { + ExtensionCommon: "resource://gre/modules/ExtensionCommon.sys.mjs", +}); + +// Initialization. Must run first. +add_setup(async function () { + // The page action urlbar button, and therefore the panel, is only shown when + // the current tab is actionable -- i.e., a normal web page. about:blank is + // not, so open a new tab first thing, and close it when this test is done. + let tab = await BrowserTestUtils.openNewForegroundTab({ + gBrowser, + url: "http://example.com/", + }); + registerCleanupFunction(async () => { + BrowserTestUtils.removeTab(tab); + }); + + await initPageActionsTest(); +}); + +// Opens the context menu on a non-built-in action. (The context menu for +// built-in actions is tested in browser_page_action_menu.js.) +add_task(async function contextMenu() { + // Add an extension with a page action so we can test its context menu. + let extension = ExtensionTestUtils.loadExtension({ + manifest: { + name: "Page action test", + page_action: { show_matches: [""] }, + }, + useAddonManager: "temporary", + }); + await extension.startup(); + let actionId = ExtensionCommon.makeWidgetId(extension.id); + + // Open the main panel. + await promiseOpenPageActionPanel(); + let panelButton = BrowserPageActions.panelButtonNodeForActionID(actionId); + let cxmenu = document.getElementById("pageActionContextMenu"); + + let contextMenuPromise; + let menuItems; + + // Open the context menu again on the action's button in the panel. (The + // panel should still be open.) + contextMenuPromise = promisePanelShown("pageActionContextMenu"); + EventUtils.synthesizeMouseAtCenter(panelButton, { + type: "contextmenu", + button: 2, + }); + await contextMenuPromise; + menuItems = collectContextMenuItems(); + Assert.deepEqual(makeMenuItemSpecs(menuItems), makeContextMenuItemSpecs()); + + // Click the "manage extension" context menu item. about:addons should open. + let manageItemIndex = 0; + contextMenuPromise = promisePanelHidden("pageActionContextMenu"); + let aboutAddonsPromise = BrowserTestUtils.waitForNewTab( + gBrowser, + "about:addons" + ); + cxmenu.activateItem(menuItems[manageItemIndex]); + let values = await Promise.all([aboutAddonsPromise, contextMenuPromise]); + let aboutAddonsTab = values[0]; + BrowserTestUtils.removeTab(aboutAddonsTab); + + // Wait for the urlbar button to become visible again after about:addons is + // closed and the test tab becomes selected. + await BrowserTestUtils.waitForCondition(() => { + return BrowserPageActions.urlbarButtonNodeForActionID(actionId); + }, "Waiting for urlbar button to be added back"); + + // Open the context menu on the action's urlbar button. + let urlbarButton = BrowserPageActions.urlbarButtonNodeForActionID(actionId); + contextMenuPromise = promisePanelShown("pageActionContextMenu"); + EventUtils.synthesizeMouseAtCenter(urlbarButton, { + type: "contextmenu", + button: 2, + }); + await contextMenuPromise; + menuItems = collectContextMenuItems(); + Assert.deepEqual(makeMenuItemSpecs(menuItems), makeContextMenuItemSpecs()); + + // Click the "manage" context menu item. about:addons should open. + contextMenuPromise = promisePanelHidden("pageActionContextMenu"); + aboutAddonsPromise = BrowserTestUtils.waitForNewTab(gBrowser, "about:addons"); + cxmenu.activateItem(menuItems[manageItemIndex]); + values = await Promise.all([aboutAddonsPromise, contextMenuPromise]); + aboutAddonsTab = values[0]; + BrowserTestUtils.removeTab(aboutAddonsTab); + + // Wait for the urlbar button to become visible again after about:addons is + // closed and the test tab becomes selected. + await BrowserTestUtils.waitForCondition(() => { + return BrowserPageActions.urlbarButtonNodeForActionID(actionId); + }, "Waiting for urlbar button to be added back"); + + // Open the context menu on the action's urlbar button. + urlbarButton = BrowserPageActions.urlbarButtonNodeForActionID(actionId); + contextMenuPromise = promisePanelShown("pageActionContextMenu"); + EventUtils.synthesizeMouseAtCenter(urlbarButton, { + type: "contextmenu", + button: 2, + }); + await contextMenuPromise; + menuItems = collectContextMenuItems(); + Assert.deepEqual(makeMenuItemSpecs(menuItems), makeContextMenuItemSpecs()); + + // Below we'll click the "remove extension" context menu item, which first + // opens a prompt using the prompt service and requires confirming the prompt. + // Set up a mock prompt service that returns 0 to indicate that the user + // pressed the OK button. + let { prompt } = Services; + let promptService = { + QueryInterface: ChromeUtils.generateQI(["nsIPromptService"]), + confirmEx() { + return 0; + }, + }; + Services.prompt = promptService; + registerCleanupFunction(() => { + Services.prompt = prompt; + }); + + // Now click the "remove extension" context menu item. + let removeItemIndex = manageItemIndex + 1; + contextMenuPromise = promisePanelHidden("pageActionContextMenu"); + let promiseUninstalled = promiseAddonUninstalled(extension.id); + cxmenu.activateItem(menuItems[removeItemIndex]); + await contextMenuPromise; + await promiseUninstalled; + await extension.unload(); + Services.prompt = prompt; + + // urlbar tests that run after this one can break if the mouse is left over + // the area where the urlbar popup appears, which seems to happen due to the + // above synthesized mouse events. Move it over the urlbar. + EventUtils.synthesizeMouseAtCenter(gURLBar.inputField, { type: "mousemove" }); + gURLBar.focus(); +}); + +// The context menu shouldn't open on separators in the panel. +add_task(async function contextMenuOnSeparator() { + // Add a non-built-in action so the built-in separator will appear in the + // panel. + let action = PageActions.addAction( + new PageActions.Action({ + id: "contextMenuOnSeparator", + title: "contextMenuOnSeparator", + pinnedToUrlbar: true, + }) + ); + + // Open the panel and get the built-in separator. + await promiseOpenPageActionPanel(); + let separator = BrowserPageActions.panelButtonNodeForActionID( + PageActions.ACTION_ID_BUILT_IN_SEPARATOR + ); + Assert.ok(separator, "The built-in separator should be in the panel"); + + // Context-click it. popupshowing should be fired, but by the time the event + // reaches this listener, preventDefault should have been called on it. + let showingPromise = BrowserTestUtils.waitForEvent( + document.getElementById("pageActionContextMenu"), + "popupshowing", + false + ); + EventUtils.synthesizeMouseAtCenter(separator, { + type: "contextmenu", + button: 2, + }); + let event = await showingPromise; + Assert.ok( + event.defaultPrevented, + "defaultPrevented should be true on popupshowing event" + ); + + // Click the main button to hide the main panel. + EventUtils.synthesizeMouseAtCenter(BrowserPageActions.mainButtonNode, {}); + await promisePageActionPanelHidden(); + + action.remove(); + + // urlbar tests that run after this one can break if the mouse is left over + // the area where the urlbar popup appears, which seems to happen due to the + // above synthesized mouse events. Move it over the urlbar. + EventUtils.synthesizeMouseAtCenter(gURLBar.inputField, { type: "mousemove" }); + gURLBar.focus(); +}); + +function collectContextMenuItems() { + let contextMenu = document.getElementById("pageActionContextMenu"); + return Array.prototype.filter.call(contextMenu.children, node => { + return window.getComputedStyle(node).visibility == "visible"; + }); +} + +function makeMenuItemSpecs(elements) { + return elements.map(e => + e.localName == "menuseparator" ? {} : { label: e.label } + ); +} + +function makeContextMenuItemSpecs() { + let items = [ + { label: "Manage Extension\u2026" }, + { label: "Remove Extension" }, + ]; + return items; +} + +function promiseAddonUninstalled(addonId) { + return new Promise(resolve => { + let listener = {}; + listener.onUninstalled = addon => { + if (addon.id == addonId) { + AddonManager.removeAddonListener(listener); + resolve(); + } + }; + AddonManager.addAddonListener(listener); + }); +} -- cgit v1.2.3