diff options
Diffstat (limited to 'devtools/client/framework/test/browser_toolbox_textbox_context_menu.js')
-rw-r--r-- | devtools/client/framework/test/browser_toolbox_textbox_context_menu.js | 137 |
1 files changed, 137 insertions, 0 deletions
diff --git a/devtools/client/framework/test/browser_toolbox_textbox_context_menu.js b/devtools/client/framework/test/browser_toolbox_textbox_context_menu.js new file mode 100644 index 0000000000..903d0c9912 --- /dev/null +++ b/devtools/client/framework/test/browser_toolbox_textbox_context_menu.js @@ -0,0 +1,137 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +// HTML inputs don't automatically get the 'edit' context menu, so we have +// a helper on the toolbox to do so. Make sure that shows menu items in the +// right state, and that it works for an input inside of a panel. + +const URL = "data:text/html;charset=utf8,test for textbox context menu"; +const textboxToolId = "testtool1"; + +registerCleanupFunction(() => { + gDevTools.unregisterTool(textboxToolId); +}); + +add_task(async function checkMenuEntryStates() { + info("Checking the state of edit menuitems with an empty clipboard"); + const toolbox = await openNewTabAndToolbox(URL, "inspector"); + + emptyClipboard(); + + // Make sure the focus is predictable. + const inspector = toolbox.getPanel("inspector"); + const onFocus = once(inspector.searchBox, "focus"); + inspector.searchBox.focus(); + await onFocus; + + info("Opening context menu"); + const onContextMenuPopup = toolbox.once("menu-open"); + synthesizeContextMenuEvent(inspector.searchBox); + await onContextMenuPopup; + + const textboxContextMenu = toolbox.getTextBoxContextMenu(); + ok(textboxContextMenu, "The textbox context menu is loaded in the toolbox"); + + const cmdUndo = textboxContextMenu.querySelector("#editmenu-undo"); + const cmdDelete = textboxContextMenu.querySelector("#editmenu-delete"); + const cmdSelectAll = textboxContextMenu.querySelector("#editmenu-selectAll"); + const cmdCut = textboxContextMenu.querySelector("#editmenu-cut"); + const cmdCopy = textboxContextMenu.querySelector("#editmenu-copy"); + const cmdPaste = textboxContextMenu.querySelector("#editmenu-paste"); + + is(cmdUndo.getAttribute("disabled"), "true", "cmdUndo is disabled"); + is(cmdDelete.getAttribute("disabled"), "true", "cmdDelete is disabled"); + is(cmdSelectAll.getAttribute("disabled"), "true", "cmdSelectAll is disabled"); + is(cmdCut.getAttribute("disabled"), "true", "cmdCut is disabled"); + is(cmdCopy.getAttribute("disabled"), "true", "cmdCopy is disabled"); + + if (isWindows()) { + // emptyClipboard only works on Windows (666254), assert paste only for this OS. + is(cmdPaste.getAttribute("disabled"), "true", "cmdPaste is disabled"); + } + + const onContextMenuHidden = toolbox.once("menu-close"); + if (Services.prefs.getBoolPref("widget.macos.native-context-menus", false)) { + info("Using hidePopup semantics because of macOS native context menus."); + textboxContextMenu.hidePopup(); + } else { + EventUtils.sendKey("ESCAPE", toolbox.win); + } + await onContextMenuHidden; +}); + +add_task(async function automaticallyBindTexbox() { + info( + "Registering a tool with an input field and making sure the context menu works" + ); + gDevTools.registerTool({ + id: textboxToolId, + isToolSupported: () => true, + url: CHROME_URL_ROOT + "doc_textbox_tool.html", + label: "Context menu works without tool intervention", + build(iframeWindow, toolbox) { + this.panel = createTestPanel(iframeWindow, toolbox); + return this.panel.open(); + }, + }); + + const toolbox = await openNewTabAndToolbox(URL, textboxToolId); + is(toolbox.currentToolId, textboxToolId, "The custom tool has been opened"); + + const doc = toolbox.getCurrentPanel().document; + await checkTextBox(doc.querySelector("input[type=text]"), toolbox); + await checkTextBox(doc.querySelector("textarea"), toolbox); + await checkTextBox(doc.querySelector("input[type=search]"), toolbox); + await checkTextBox(doc.querySelector("input:not([type])"), toolbox); + await checkNonTextInput(doc.querySelector("input[type=radio]"), toolbox); +}); + +async function checkNonTextInput(input, toolbox) { + let textboxContextMenu = toolbox.getTextBoxContextMenu(); + ok(!textboxContextMenu, "The menu is closed"); + + info( + "Simulating context click on the non text input and expecting no menu to open" + ); + const eventBubbledUp = new Promise(resolve => { + input.ownerDocument.addEventListener("contextmenu", resolve, { + once: true, + }); + }); + synthesizeContextMenuEvent(input); + info("Waiting for event"); + await eventBubbledUp; + + textboxContextMenu = toolbox.getTextBoxContextMenu(); + ok(!textboxContextMenu, "The menu is still closed"); +} + +async function checkTextBox(textBox, toolbox) { + let textboxContextMenu = toolbox.getTextBoxContextMenu(); + ok(!textboxContextMenu, "The menu is closed"); + + info( + "Simulating context click on the textbox and expecting the menu to open" + ); + const onContextMenu = toolbox.once("menu-open"); + synthesizeContextMenuEvent(textBox); + await onContextMenu; + + textboxContextMenu = toolbox.getTextBoxContextMenu(); + ok(textboxContextMenu, "The menu is now visible"); + + info("Closing the menu"); + const onContextMenuHidden = toolbox.once("menu-close"); + if (Services.prefs.getBoolPref("widget.macos.native-context-menus", false)) { + info("Using hidePopup semantics because of macOS native context menus."); + textboxContextMenu.hidePopup(); + } else { + EventUtils.sendKey("ESCAPE", toolbox.win); + } + await onContextMenuHidden; + + textboxContextMenu = toolbox.getTextBoxContextMenu(); + ok(!textboxContextMenu, "The menu is closed again"); +} |