summaryrefslogtreecommitdiffstats
path: root/devtools/client/inspector/test/browser_inspector_menu-01-sensitivity.js
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--devtools/client/inspector/test/browser_inspector_menu-01-sensitivity.js388
1 files changed, 388 insertions, 0 deletions
diff --git a/devtools/client/inspector/test/browser_inspector_menu-01-sensitivity.js b/devtools/client/inspector/test/browser_inspector_menu-01-sensitivity.js
new file mode 100644
index 0000000000..9ac925db6e
--- /dev/null
+++ b/devtools/client/inspector/test/browser_inspector_menu-01-sensitivity.js
@@ -0,0 +1,388 @@
+/* Any copyright is dedicated to the Public Domain.
+http://creativecommons.org/publicdomain/zero/1.0/ */
+"use strict";
+
+// Test that context menu items are enabled / disabled correctly.
+
+const TEST_URL = URL_ROOT + "doc_inspector_menu.html";
+
+const PASTE_MENU_ITEMS = [
+ "node-menu-pasteinnerhtml",
+ "node-menu-pasteouterhtml",
+ "node-menu-pastebefore",
+ "node-menu-pasteafter",
+ "node-menu-pastefirstchild",
+ "node-menu-pastelastchild",
+];
+
+const ACTIVE_ON_DOCTYPE_ITEMS = [
+ "node-menu-showdomproperties",
+ "node-menu-useinconsole",
+];
+
+const ACTIVE_ON_SHADOW_ROOT_ITEMS = [
+ "node-menu-pasteinnerhtml",
+ "node-menu-copyinner",
+ "node-menu-edithtml",
+].concat(ACTIVE_ON_DOCTYPE_ITEMS);
+
+const ALL_MENU_ITEMS = [
+ "node-menu-edithtml",
+ "node-menu-copyinner",
+ "node-menu-copyouter",
+ "node-menu-copyuniqueselector",
+ "node-menu-copycsspath",
+ "node-menu-copyxpath",
+ "node-menu-copyimagedatauri",
+ "node-menu-delete",
+ "node-menu-pseudo-hover",
+ "node-menu-pseudo-active",
+ "node-menu-pseudo-focus",
+ "node-menu-pseudo-focus-within",
+ "node-menu-scrollnodeintoview",
+ "node-menu-screenshotnode",
+ "node-menu-add-attribute",
+ "node-menu-copy-attribute",
+ "node-menu-edit-attribute",
+ "node-menu-remove-attribute",
+].concat(PASTE_MENU_ITEMS, ACTIVE_ON_DOCTYPE_ITEMS);
+
+const INACTIVE_ON_DOCTYPE_ITEMS = ALL_MENU_ITEMS.filter(
+ item => !ACTIVE_ON_DOCTYPE_ITEMS.includes(item)
+);
+
+const INACTIVE_ON_DOCUMENT_ITEMS = INACTIVE_ON_DOCTYPE_ITEMS;
+
+const INACTIVE_ON_SHADOW_ROOT_ITEMS = ALL_MENU_ITEMS.filter(
+ item => !ACTIVE_ON_SHADOW_ROOT_ITEMS.includes(item)
+);
+
+/**
+ * Test cases, each item of this array may define the following properties:
+ * desc: string that will be logged
+ * selector: selector of the node to be selected
+ * disabled: items that should have disabled state
+ * clipboardData: clipboard content
+ * clipboardDataType: clipboard content type
+ * attributeTrigger: attribute that will be used as context menu trigger
+ * shadowRoot: if true, selects the shadow root from the node, rather than
+ * the node itself.
+ */
+const TEST_CASES = [
+ {
+ desc: "doctype node with empty clipboard",
+ selector: null,
+ disabled: INACTIVE_ON_DOCTYPE_ITEMS,
+ },
+ {
+ desc: "doctype node with html on clipboard",
+ clipboardData: "<p>some text</p>",
+ clipboardDataType: "text",
+ selector: null,
+ disabled: INACTIVE_ON_DOCTYPE_ITEMS,
+ },
+ {
+ desc: "element node HTML on the clipboard",
+ clipboardData: "<p>some text</p>",
+ clipboardDataType: "text",
+ disabled: [
+ "node-menu-copyimagedatauri",
+ "node-menu-copy-attribute",
+ "node-menu-edit-attribute",
+ "node-menu-remove-attribute",
+ ],
+ selector: "#sensitivity",
+ },
+ {
+ desc: "<html> element",
+ clipboardData: "<p>some text</p>",
+ clipboardDataType: "text",
+ selector: "html",
+ disabled: [
+ "node-menu-copyimagedatauri",
+ "node-menu-pastebefore",
+ "node-menu-pasteafter",
+ "node-menu-pastefirstchild",
+ "node-menu-pastelastchild",
+ "node-menu-copy-attribute",
+ "node-menu-edit-attribute",
+ "node-menu-remove-attribute",
+ "node-menu-delete",
+ ],
+ },
+ {
+ desc: "<body> with HTML on clipboard",
+ clipboardData: "<p>some text</p>",
+ clipboardDataType: "text",
+ selector: "body",
+ disabled: [
+ "node-menu-copyimagedatauri",
+ "node-menu-pastebefore",
+ "node-menu-pasteafter",
+ "node-menu-copy-attribute",
+ "node-menu-edit-attribute",
+ "node-menu-remove-attribute",
+ ],
+ },
+ {
+ desc: "<img> with HTML on clipboard",
+ clipboardData: "<p>some text</p>",
+ clipboardDataType: "text",
+ selector: "img",
+ disabled: [
+ "node-menu-copy-attribute",
+ "node-menu-edit-attribute",
+ "node-menu-remove-attribute",
+ ],
+ },
+ {
+ desc: "<head> with HTML on clipboard",
+ clipboardData: "<p>some text</p>",
+ clipboardDataType: "text",
+ selector: "head",
+ disabled: [
+ "node-menu-copyimagedatauri",
+ "node-menu-pastebefore",
+ "node-menu-pasteafter",
+ "node-menu-screenshotnode",
+ "node-menu-copy-attribute",
+ "node-menu-edit-attribute",
+ "node-menu-remove-attribute",
+ ],
+ },
+ {
+ desc: "<head> with no html on clipboard",
+ selector: "head",
+ disabled: PASTE_MENU_ITEMS.concat([
+ "node-menu-copyimagedatauri",
+ "node-menu-screenshotnode",
+ "node-menu-copy-attribute",
+ "node-menu-edit-attribute",
+ "node-menu-remove-attribute",
+ ]),
+ },
+ {
+ desc: "<element> with text on clipboard",
+ clipboardData: "some text",
+ clipboardDataType: "text",
+ selector: "#paste-area",
+ disabled: [
+ "node-menu-copyimagedatauri",
+ "node-menu-copy-attribute",
+ "node-menu-edit-attribute",
+ "node-menu-remove-attribute",
+ ],
+ },
+ {
+ desc: "<element> with base64 encoded image data uri on clipboard",
+ clipboardData:
+ "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABC" +
+ "AAAAAA6fptVAAAACklEQVQYV2P4DwABAQEAWk1v8QAAAABJRU5ErkJggg==",
+ clipboardDataType: "image",
+ selector: "#paste-area",
+ disabled: PASTE_MENU_ITEMS.concat([
+ "node-menu-copyimagedatauri",
+ "node-menu-copy-attribute",
+ "node-menu-edit-attribute",
+ "node-menu-remove-attribute",
+ ]),
+ },
+ {
+ desc: "<element> with empty string on clipboard",
+ clipboardData: "",
+ clipboardDataType: "text",
+ selector: "#paste-area",
+ disabled: PASTE_MENU_ITEMS.concat([
+ "node-menu-copyimagedatauri",
+ "node-menu-copy-attribute",
+ "node-menu-edit-attribute",
+ "node-menu-remove-attribute",
+ ]),
+ },
+ {
+ desc: "<element> with whitespace only on clipboard",
+ clipboardData: " \n\n\t\n\n \n",
+ clipboardDataType: "text",
+ selector: "#paste-area",
+ disabled: PASTE_MENU_ITEMS.concat([
+ "node-menu-copyimagedatauri",
+ "node-menu-copy-attribute",
+ "node-menu-edit-attribute",
+ "node-menu-remove-attribute",
+ ]),
+ },
+ {
+ desc: "<element> that isn't visible on the page, empty clipboard",
+ selector: "#hiddenElement",
+ disabled: PASTE_MENU_ITEMS.concat([
+ "node-menu-copyimagedatauri",
+ "node-menu-screenshotnode",
+ "node-menu-copy-attribute",
+ "node-menu-edit-attribute",
+ "node-menu-remove-attribute",
+ ]),
+ },
+ {
+ desc: "<element> nested in another hidden element, empty clipboard",
+ selector: "#nestedHiddenElement",
+ disabled: PASTE_MENU_ITEMS.concat([
+ "node-menu-copyimagedatauri",
+ "node-menu-screenshotnode",
+ "node-menu-copy-attribute",
+ "node-menu-edit-attribute",
+ "node-menu-remove-attribute",
+ ]),
+ },
+ {
+ desc: "<element> with context menu triggered on attribute, empty clipboard",
+ selector: "#attributes",
+ disabled: PASTE_MENU_ITEMS.concat(["node-menu-copyimagedatauri"]),
+ attributeTrigger: "data-edit",
+ },
+ {
+ desc: "Shadow Root",
+ clipboardData: "<p>some text</p>",
+ clipboardDataType: "text",
+ disabled: INACTIVE_ON_SHADOW_ROOT_ITEMS,
+ selector: "#host",
+ shadowRoot: true,
+ },
+ {
+ desc: "Document node in iFrame",
+ disabled: INACTIVE_ON_DOCUMENT_ITEMS,
+ selector: "iframe",
+ documentNode: true,
+ },
+];
+
+var clipboard = require("resource://devtools/shared/platform/clipboard.js");
+registerCleanupFunction(() => {
+ clipboard.copyString("");
+ clipboard = null;
+});
+
+add_task(async function () {
+ const { inspector } = await openInspectorForURL(TEST_URL);
+ for (const test of TEST_CASES) {
+ const {
+ desc,
+ disabled,
+ selector,
+ attributeTrigger,
+ documentNode = false,
+ shadowRoot = false,
+ } = test;
+
+ info(`Test ${desc}`);
+ setupClipboard(test.clipboardData, test.clipboardDataType);
+
+ const front = await getNodeFrontForSelector(
+ selector,
+ inspector,
+ documentNode,
+ shadowRoot
+ );
+
+ info("Selecting the specified node.");
+ await selectNode(front, inspector);
+
+ info("Simulating context menu click on the selected node container.");
+ const nodeFrontContainer = getContainerForNodeFront(front, inspector);
+ const contextMenuTrigger = attributeTrigger
+ ? nodeFrontContainer.tagLine.querySelector(
+ `[data-attr="${attributeTrigger}"]`
+ )
+ : nodeFrontContainer.tagLine;
+
+ const allMenuItems = openContextMenuAndGetAllItems(inspector, {
+ target: contextMenuTrigger,
+ });
+
+ for (const id of ALL_MENU_ITEMS) {
+ const menuItem = allMenuItems.find(item => item.id === id);
+ const shouldBeDisabled = disabled.includes(id);
+ const shouldBeDisabledText = shouldBeDisabled ? "disabled" : "enabled";
+ is(
+ menuItem.disabled,
+ shouldBeDisabled,
+ `#${id} should be ${shouldBeDisabledText} for test case ${desc}`
+ );
+ }
+ }
+});
+
+/**
+ * A helper that fetches a front for a node that matches the given selector or
+ * doctype node if the selector is falsy.
+ */
+async function getNodeFrontForSelector(
+ selector,
+ inspector,
+ documentNode,
+ shadowRoot
+) {
+ if (selector) {
+ info("Retrieving front for selector " + selector);
+ const node = await getNodeFront(selector, inspector);
+ if (shadowRoot) {
+ return getShadowRoot(node, inspector);
+ }
+ if (documentNode) {
+ return getFrameDocument(node, inspector);
+ }
+ return node;
+ }
+
+ info("Retrieving front for doctype node");
+ const { nodes } = await inspector.walker.children(inspector.walker.rootNode);
+ return nodes[0];
+}
+
+/**
+ * A helper that populates the clipboard with data of given type. Clears the
+ * clipboard if data is falsy.
+ */
+function setupClipboard(data, type) {
+ if (!data) {
+ info("Clearing the clipboard.");
+ clipboard.copyString("");
+ } else if (type === "text") {
+ info("Populating clipboard with text.");
+ clipboard.copyString(data);
+ } else if (type === "image") {
+ info("Populating clipboard with image content");
+ copyImageToClipboard(data);
+ }
+}
+
+/**
+ * The code below is a simplified version of the sdk/clipboard helper set() method.
+ */
+function copyImageToClipboard(data) {
+ const imageTools = Cc["@mozilla.org/image/tools;1"].getService(Ci.imgITools);
+
+ // Image data is stored as base64 in the test.
+ const image = atob(data);
+
+ const imgPtr = Cc["@mozilla.org/supports-interface-pointer;1"].createInstance(
+ Ci.nsISupportsInterfacePointer
+ );
+ imgPtr.data = imageTools.decodeImageFromBuffer(
+ image,
+ image.length,
+ "image/png"
+ );
+
+ const xferable = Cc["@mozilla.org/widget/transferable;1"].createInstance(
+ Ci.nsITransferable
+ );
+ xferable.init(null);
+ xferable.addDataFlavor("image/png");
+ xferable.setTransferData("image/png", imgPtr);
+
+ Services.clipboard.setData(
+ xferable,
+ null,
+ Services.clipboard.kGlobalClipboard
+ );
+}