diff options
Diffstat (limited to 'addon-sdk/source/test/test-context-menu.js')
-rw-r--r-- | addon-sdk/source/test/test-context-menu.js | 3763 |
1 files changed, 0 insertions, 3763 deletions
diff --git a/addon-sdk/source/test/test-context-menu.js b/addon-sdk/source/test/test-context-menu.js deleted file mode 100644 index f1a955545..000000000 --- a/addon-sdk/source/test/test-context-menu.js +++ /dev/null @@ -1,3763 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - 'use strict'; - -require("sdk/context-menu"); - -const { defer } = require("sdk/core/promise"); -const { isTravisCI } = require("sdk/test/utils"); -const packaging = require('@loader/options'); - -// These should match the same constants in the module. -const OVERFLOW_THRESH_DEFAULT = 10; -const OVERFLOW_THRESH_PREF = - "extensions.addon-sdk.context-menu.overflowThreshold"; - -const TEST_DOC_URL = module.uri.replace(/\.js$/, ".html"); -const data = require("./fixtures"); - -const { TestHelper } = require("./context-menu/test-helper.js") - -// Tests that when present the separator is placed before the separator from -// the old context-menu module -exports.testSeparatorPosition = function (assert, done) { - let test = new TestHelper(assert, done); - let loader = test.newLoader(); - - // Create the old separator - let oldSeparator = test.contextMenuPopup.ownerDocument.createElement("menuseparator"); - oldSeparator.id = "jetpack-context-menu-separator"; - test.contextMenuPopup.appendChild(oldSeparator); - - // Create an item. - let item = new loader.cm.Item({ label: "item" }); - - test.showMenu(null, function (popup) { - assert.equal(test.contextMenuSeparator.nextSibling.nextSibling, oldSeparator, - "New separator should appear before the old one"); - test.contextMenuPopup.removeChild(oldSeparator); - test.done(); - }); -}; - -// Destroying items that were previously created should cause them to be absent -// from the menu. -exports.testConstructDestroy = function (assert, done) { - let test = new TestHelper(assert, done); - let loader = test.newLoader(); - - // Create an item. - let item = new loader.cm.Item({ label: "item" }); - assert.equal(item.parentMenu, loader.cm.contentContextMenu, - "item's parent menu should be correct"); - - test.showMenu(null, function (popup) { - - // It should be present when the menu is shown. - test.checkMenu([item], [], []); - popup.hidePopup(); - - // Destroy the item. Multiple destroys should be harmless. - item.destroy(); - item.destroy(); - test.showMenu(null, function (popup) { - - // It should be removed from the menu. - test.checkMenu([item], [], [item]); - test.done(); - }); - }); -}; - - -// Destroying an item twice should not cause an error. -exports.testDestroyTwice = function (assert, done) { - let test = new TestHelper(assert, done); - let loader = test.newLoader(); - - let item = new loader.cm.Item({ label: "item" }); - item.destroy(); - item.destroy(); - - test.pass("Destroying an item twice should not cause an error."); - test.done(); -}; - - -// CSS selector contexts should cause their items to be present in the menu -// when the menu is invoked on nodes that match the selectors. -exports.testSelectorContextMatch = function (assert, done) { - let test = new TestHelper(assert, done); - let loader = test.newLoader(); - - let item = new loader.cm.Item({ - label: "item", - data: "item", - context: loader.cm.SelectorContext("img") - }); - - test.withTestDoc(function (window, doc) { - test.showMenu("#image", function (popup) { - test.checkMenu([item], [], []); - test.done(); - }); - }); -}; - - -// CSS selector contexts should cause their items to be present in the menu -// when the menu is invoked on nodes that have ancestors that match the -// selectors. -exports.testSelectorAncestorContextMatch = function (assert, done) { - let test = new TestHelper(assert, done); - let loader = test.newLoader(); - - let item = new loader.cm.Item({ - label: "item", - data: "item", - context: loader.cm.SelectorContext("a[href]") - }); - - test.withTestDoc(function (window, doc) { - test.showMenu("#span-link", function (popup) { - test.checkMenu([item], [], []); - test.done(); - }); - }); -}; - - -// CSS selector contexts should cause their items to be absent from the menu -// when the menu is not invoked on nodes that match or have ancestors that -// match the selectors. -exports.testSelectorContextNoMatch = function (assert, done) { - let test = new TestHelper(assert, done); - let loader = test.newLoader(); - - let item = new loader.cm.Item({ - label: "item", - data: "item", - context: loader.cm.SelectorContext("img") - }); - - test.showMenu(null, function (popup) { - test.checkMenu([item], [item], []); - test.done(); - }); -}; - - -// Page contexts should cause their items to be present in the menu when the -// menu is not invoked on an active element. -exports.testPageContextMatch = function (assert, done) { - let test = new TestHelper(assert, done); - let loader = test.newLoader(); - - let items = [ - new loader.cm.Item({ - label: "item 0" - }), - new loader.cm.Item({ - label: "item 1", - context: undefined - }), - new loader.cm.Item({ - label: "item 2", - context: loader.cm.PageContext() - }), - new loader.cm.Item({ - label: "item 3", - context: [loader.cm.PageContext()] - }) - ]; - - test.showMenu(null, function (popup) { - test.checkMenu(items, [], []); - test.done(); - }); -}; - - -// Page contexts should cause their items to be absent from the menu when the -// menu is invoked on an active element. -exports.testPageContextNoMatch = function (assert, done) { - let test = new TestHelper(assert, done); - let loader = test.newLoader(); - - let items = [ - new loader.cm.Item({ - label: "item 0" - }), - new loader.cm.Item({ - label: "item 1", - context: undefined - }), - new loader.cm.Item({ - label: "item 2", - context: loader.cm.PageContext() - }), - new loader.cm.Item({ - label: "item 3", - context: [loader.cm.PageContext()] - }) - ]; - - test.withTestDoc(function (window, doc) { - test.showMenu("#image", function (popup) { - test.checkMenu(items, items, []); - test.done(); - }); - }); -}; - - -// Selection contexts should cause items to appear when a selection exists. -exports.testSelectionContextMatch = function (assert, done) { - let test = new TestHelper(assert, done); - let loader = test.newLoader(); - - let item = loader.cm.Item({ - label: "item", - context: loader.cm.SelectionContext() - }); - - test.withTestDoc(function (window, doc) { - window.getSelection().selectAllChildren(doc.body); - test.showMenu(null, function (popup) { - test.checkMenu([item], [], []); - test.done(); - }); - }); -}; - - -// Selection contexts should cause items to appear when a selection exists in -// a text field. -exports.testSelectionContextMatchInTextField = function (assert, done) { - let test = new TestHelper(assert, done); - let loader = test.newLoader(); - - let item = loader.cm.Item({ - label: "item", - context: loader.cm.SelectionContext() - }); - - test.withTestDoc(function (window, doc) { - test.selectRange("#textfield", 0, null); - test.showMenu("#textfield", function (popup) { - test.checkMenu([item], [], []); - test.done(); - }); - }); -}; - - -// Selection contexts should not cause items to appear when a selection does -// not exist in a text field. -exports.testSelectionContextNoMatchInTextField = function (assert, done) { - let test = new TestHelper(assert, done); - let loader = test.newLoader(); - - let item = loader.cm.Item({ - label: "item", - context: loader.cm.SelectionContext() - }); - - test.withTestDoc(function (window, doc) { - test.selectRange("#textfield", 0, 0); - test.showMenu("#textfield", function (popup) { - test.checkMenu([item], [item], []); - test.done(); - }); - }); -}; - - -// Selection contexts should not cause items to appear when a selection does -// not exist. -exports.testSelectionContextNoMatch = function (assert, done) { - let test = new TestHelper(assert, done); - let loader = test.newLoader(); - - let item = loader.cm.Item({ - label: "item", - context: loader.cm.SelectionContext() - }); - - test.showMenu(null, function (popup) { - test.checkMenu([item], [item], []); - test.done(); - }); -}; - - -// Selection contexts should cause items to appear when a selection exists even -// for newly opened pages -exports.testSelectionContextInNewTab = function (assert, done) { - let test = new TestHelper(assert, done); - let loader = test.newLoader(); - - let item = loader.cm.Item({ - label: "item", - context: loader.cm.SelectionContext() - }); - - test.withTestDoc(function (window, doc) { - let link = doc.getElementById("targetlink"); - link.click(); - - let tablistener = event => { - this.tabBrowser.tabContainer.removeEventListener("TabOpen", tablistener, false); - let tab = event.target; - let browser = tab.linkedBrowser; - this.loadFrameScript(browser); - this.delayedEventListener(browser, "load", () => { - let window = browser.contentWindow; - let doc = browser.contentDocument; - window.getSelection().selectAllChildren(doc.body); - - test.showMenu(null, function (popup) { - test.checkMenu([item], [], []); - popup.hidePopup(); - - test.tabBrowser.removeTab(test.tabBrowser.selectedTab); - test.tabBrowser.selectedTab = test.tab; - - test.showMenu(null, function (popup) { - test.checkMenu([item], [item], []); - test.done(); - }); - }); - }, true); - }; - this.tabBrowser.tabContainer.addEventListener("TabOpen", tablistener, false); - }); -}; - - -// Selection contexts should work when right clicking a form button -exports.testSelectionContextButtonMatch = function (assert, done) { - let test = new TestHelper(assert, done); - let loader = test.newLoader(); - - let item = loader.cm.Item({ - label: "item", - context: loader.cm.SelectionContext() - }); - - test.withTestDoc(function (window, doc) { - window.getSelection().selectAllChildren(doc.body); - test.showMenu("#button", function (popup) { - test.checkMenu([item], [], []); - test.done(); - }); - }); -}; - - -//Selection contexts should work when right clicking a form button -exports.testSelectionContextButtonNoMatch = function (assert, done) { - let test = new TestHelper(assert, done); - let loader = test.newLoader(); - - let item = loader.cm.Item({ - label: "item", - context: loader.cm.SelectionContext() - }); - - test.withTestDoc(function (window, doc) { - test.showMenu("#button", function (popup) { - test.checkMenu([item], [item], []); - test.done(); - }); - }); -}; - - -// URL contexts should cause items to appear on pages that match. -exports.testURLContextMatch = function (assert, done) { - let test = new TestHelper(assert, done); - let loader = test.newLoader(); - - let items = [ - loader.cm.Item({ - label: "item 0", - context: loader.cm.URLContext(TEST_DOC_URL) - }), - loader.cm.Item({ - label: "item 1", - context: loader.cm.URLContext([TEST_DOC_URL, "*.bogus.com"]) - }), - loader.cm.Item({ - label: "item 2", - context: loader.cm.URLContext([new RegExp(".*\\.html")]) - }) - ]; - - test.withTestDoc(function (window, doc) { - test.showMenu(null, function (popup) { - test.checkMenu(items, [], []); - test.done(); - }); - }); -}; - - -// URL contexts should not cause items to appear on pages that do not match. -exports.testURLContextNoMatch = function (assert, done) { - let test = new TestHelper(assert, done); - let loader = test.newLoader(); - - let items = [ - loader.cm.Item({ - label: "item 0", - context: loader.cm.URLContext("*.bogus.com") - }), - loader.cm.Item({ - label: "item 1", - context: loader.cm.URLContext(["*.bogus.com", "*.gnarly.com"]) - }), - loader.cm.Item({ - label: "item 2", - context: loader.cm.URLContext([new RegExp(".*\\.js")]) - }) - ]; - - test.withTestDoc(function (window, doc) { - test.showMenu(null, function (popup) { - test.checkMenu(items, items, []); - test.done(); - }); - }); -}; - - -// Loading a new page in the same tab should correctly start a new worker for -// any content scripts -exports.testPageReload = function (assert, done) { - let test = new TestHelper(assert, done); - let loader = test.newLoader(); - - let item = loader.cm.Item({ - label: "Item", - contentScript: "var doc = document; self.on('context', node => doc.body.getAttribute('showItem') == 'true');" - }); - - test.withTestDoc(function (window, doc) { - // Set a flag on the document that the item uses - doc.body.setAttribute("showItem", "true"); - - test.showMenu(null, function (popup) { - // With the attribute true the item should be visible in the menu - test.checkMenu([item], [], []); - test.hideMenu(function() { - let browser = this.tabBrowser.getBrowserForTab(this.tab) - test.delayedEventListener(browser, "load", function() { - test.delayedEventListener(browser, "load", function() { - window = browser.contentWindow; - doc = window.document; - - // Set a flag on the document that the item uses - doc.body.setAttribute("showItem", "false"); - - test.showMenu(null, function (popup) { - // In the new document with the attribute false the item should be - // hidden, but if the contentScript hasn't been reloaded it will - // still see the old value - test.checkMenu([item], [item], []); - - test.done(); - }); - }, true); - browser.loadURI(TEST_DOC_URL, null, null); - }, true); - // Required to make sure we load a new page in history rather than - // just reloading the current page which would unload it - browser.loadURI("about:blank", null, null); - }); - }); - }); -}; - -// Closing a page after it's been used with a worker should cause the worker -// to be destroyed -/*exports.testWorkerDestroy = function (assert, done) { - let test = new TestHelper(assert, done); - let loader = test.newLoader(); - - let loadExpected = false; - - let item = loader.cm.Item({ - label: "item", - contentScript: 'self.postMessage("loaded"); self.on("detach", function () { console.log("saw detach"); self.postMessage("detach") });', - onMessage: function (msg) { - switch (msg) { - case "loaded": - assert.ok(loadExpected, "Should have seen the load event at the right time"); - loadExpected = false; - break; - case "detach": - test.done(); - break; - } - } - }); - - test.withTestDoc(function (window, doc) { - loadExpected = true; - test.showMenu(null, function (popup) { - assert.ok(!loadExpected, "Should have seen a message"); - - test.checkMenu([item], [], []); - - test.closeTab(); - }); - }); -};*/ - - -// Content contexts that return true should cause their items to be present -// in the menu. -exports.testContentContextMatch = function (assert, done) { - let test = new TestHelper(assert, done); - let loader = test.newLoader(); - - let item = new loader.cm.Item({ - label: "item", - contentScript: 'self.on("context", () => true);' - }); - - test.showMenu(null, function (popup) { - test.checkMenu([item], [], []); - test.done(); - }); -}; - - -// Content contexts that return false should cause their items to be absent -// from the menu. -exports.testContentContextNoMatch = function (assert, done) { - let test = new TestHelper(assert, done); - let loader = test.newLoader(); - - let item = new loader.cm.Item({ - label: "item", - contentScript: 'self.on("context", () => false);' - }); - - test.showMenu(null, function (popup) { - test.checkMenu([item], [item], []); - test.done(); - }); -}; - - -// Content contexts that return undefined should cause their items to be absent -// from the menu. -exports.testContentContextUndefined = function (assert, done) { - let test = new TestHelper(assert, done); - let loader = test.newLoader(); - - let item = new loader.cm.Item({ - label: "item", - contentScript: 'self.on("context", function () {});' - }); - - test.showMenu(null, function (popup) { - test.checkMenu([item], [item], []); - test.done(); - }); -}; - - -// Content contexts that return an empty string should cause their items to be -// absent from the menu and shouldn't wipe the label -exports.testContentContextEmptyString = function (assert, done) { - let test = new TestHelper(assert, done); - let loader = test.newLoader(); - - let item = new loader.cm.Item({ - label: "item", - contentScript: 'self.on("context", () => "");' - }); - - test.showMenu(null, function (popup) { - test.checkMenu([item], [item], []); - assert.equal(item.label, "item", "Label should still be correct"); - test.done(); - }); -}; - - -// If any content contexts returns true then their items should be present in -// the menu. -exports.testMultipleContentContextMatch1 = function (assert, done) { - let test = new TestHelper(assert, done); - let loader = test.newLoader(); - - let item = new loader.cm.Item({ - label: "item", - contentScript: 'self.on("context", () => true); ' + - 'self.on("context", () => false);', - onMessage: function() { - test.fail("Should not have called the second context listener"); - } - }); - - test.showMenu(null, function (popup) { - test.checkMenu([item], [], []); - test.done(); - }); -}; - - -// If any content contexts returns true then their items should be present in -// the menu. -exports.testMultipleContentContextMatch2 = function (assert, done) { - let test = new TestHelper(assert, done); - let loader = test.newLoader(); - - let item = new loader.cm.Item({ - label: "item", - contentScript: 'self.on("context", () => false); ' + - 'self.on("context", () => true);' - }); - - test.showMenu(null, function (popup) { - test.checkMenu([item], [], []); - test.done(); - }); -}; - - -// If any content contexts returns a string then their items should be present -// in the menu. -exports.testMultipleContentContextString1 = function (assert, done) { - let test = new TestHelper(assert, done); - let loader = test.newLoader(); - - let item = new loader.cm.Item({ - label: "item", - contentScript: 'self.on("context", () => "new label"); ' + - 'self.on("context", () => false);' - }); - - test.showMenu(null, function (popup) { - test.checkMenu([item], [], []); - assert.equal(item.label, "new label", "Label should have changed"); - test.done(); - }); -}; - - -// If any content contexts returns a string then their items should be present -// in the menu. -exports.testMultipleContentContextString2 = function (assert, done) { - let test = new TestHelper(assert, done); - let loader = test.newLoader(); - - let item = new loader.cm.Item({ - label: "item", - contentScript: 'self.on("context", () => false); ' + - 'self.on("context", () => "new label");' - }); - - test.showMenu(null, function (popup) { - test.checkMenu([item], [], []); - assert.equal(item.label, "new label", "Label should have changed"); - test.done(); - }); -}; - - -// If many content contexts returns a string then the first should take effect -exports.testMultipleContentContextString3 = function (assert, done) { - let test = new TestHelper(assert, done); - let loader = test.newLoader(); - - let item = new loader.cm.Item({ - label: "item", - contentScript: 'self.on("context", () => "new label 1"); ' + - 'self.on("context", () => "new label 2");' - }); - - test.showMenu(null, function (popup) { - test.checkMenu([item], [], []); - assert.equal(item.label, "new label 1", "Label should have changed"); - test.done(); - }); -}; - - -// Content contexts that return true should cause their items to be present -// in the menu when context clicking an active element. -exports.testContentContextMatchActiveElement = function (assert, done) { - let test = new TestHelper(assert, done); - let loader = test.newLoader(); - - let items = [ - new loader.cm.Item({ - label: "item 1", - contentScript: 'self.on("context", () => true);' - }), - new loader.cm.Item({ - label: "item 2", - context: undefined, - contentScript: 'self.on("context", () => true);' - }), - // These items will always be hidden by the declarative usage of PageContext - new loader.cm.Item({ - label: "item 3", - context: loader.cm.PageContext(), - contentScript: 'self.on("context", () => true);' - }), - new loader.cm.Item({ - label: "item 4", - context: [loader.cm.PageContext()], - contentScript: 'self.on("context", () => true);' - }) - ]; - - test.withTestDoc(function (window, doc) { - test.showMenu("#image", function (popup) { - test.checkMenu(items, [items[2], items[3]], []); - test.done(); - }); - }); -}; - - -// Content contexts that return false should cause their items to be absent -// from the menu when context clicking an active element. -exports.testContentContextNoMatchActiveElement = function (assert, done) { - let test = new TestHelper(assert, done); - let loader = test.newLoader(); - - let items = [ - new loader.cm.Item({ - label: "item 1", - contentScript: 'self.on("context", () => false);' - }), - new loader.cm.Item({ - label: "item 2", - context: undefined, - contentScript: 'self.on("context", () => false);' - }), - // These items will always be hidden by the declarative usage of PageContext - new loader.cm.Item({ - label: "item 3", - context: loader.cm.PageContext(), - contentScript: 'self.on("context", () => false);' - }), - new loader.cm.Item({ - label: "item 4", - context: [loader.cm.PageContext()], - contentScript: 'self.on("context", () => false);' - }) - ]; - - test.withTestDoc(function (window, doc) { - test.showMenu("#image", function (popup) { - test.checkMenu(items, items, []); - test.done(); - }); - }); -}; - - -// Content contexts that return undefined should cause their items to be absent -// from the menu when context clicking an active element. -exports.testContentContextNoMatchActiveElement = function (assert, done) { - let test = new TestHelper(assert, done); - let loader = test.newLoader(); - - let items = [ - new loader.cm.Item({ - label: "item 1", - contentScript: 'self.on("context", () => {});' - }), - new loader.cm.Item({ - label: "item 2", - context: undefined, - contentScript: 'self.on("context", () => {});' - }), - // These items will always be hidden by the declarative usage of PageContext - new loader.cm.Item({ - label: "item 3", - context: loader.cm.PageContext(), - contentScript: 'self.on("context", () => {});' - }), - new loader.cm.Item({ - label: "item 4", - context: [loader.cm.PageContext()], - contentScript: 'self.on("context", () => {});' - }) - ]; - - test.withTestDoc(function (window, doc) { - test.showMenu("#image", function (popup) { - test.checkMenu(items, items, []); - test.done(); - }); - }); -}; - - -// Content contexts that return a string should cause their items to be present -// in the menu and the items' labels to be updated. -exports.testContentContextMatchString = function (assert, done) { - let test = new TestHelper(assert, done); - let loader = test.newLoader(); - - let item = new loader.cm.Item({ - label: "first label", - contentScript: 'self.on("context", () => "second label");' - }); - - test.showMenu(null, function (popup) { - test.checkMenu([item], [], []); - assert.equal(item.label, "second label", - "item's label should be updated"); - test.done(); - }); -}; - - -// Ensure that contentScriptFile is working correctly -exports.testContentScriptFile = function (assert, done) { - let test = new TestHelper(assert, done); - let loader = test.newLoader(); - let { defer, all } = require("sdk/core/promise"); - let itemScript = [defer(), defer()]; - let menuShown = defer(); - let menuPromises = itemScript.concat(menuShown).map(({promise}) => promise); - - // Reject remote files - assert.throws(function() { - new loader.cm.Item({ - label: "item", - contentScriptFile: "http://mozilla.com/context-menu.js" - }); - }, - /The `contentScriptFile` option must be a local URL or an array of URLs/, - "Item throws when contentScriptFile is a remote URL"); - - // But accept files from data folder - let item = new loader.cm.Item({ - label: "item", - contentScriptFile: data.url("test-contentScriptFile.js"), - onMessage: (message) => { - assert.equal(message, "msg from contentScriptFile", - "contentScriptFile loaded with absolute url"); - itemScript[0].resolve(); - } - }); - - let item2 = new loader.cm.Item({ - label: "item2", - contentScriptFile: "./test-contentScriptFile.js", - onMessage: (message) => { - assert.equal(message, "msg from contentScriptFile", - "contentScriptFile loaded with relative url"); - itemScript[1].resolve(); - } - }); - - test.showMenu(null, function (popup) { - test.checkMenu([item, item2], [], []); - menuShown.resolve(); - }); - - all(menuPromises).then(() => test.done()); -}; - - -// The args passed to context listeners should be correct. -exports.testContentContextArgs = function (assert, done) { - let test = new TestHelper(assert, done); - let loader = test.newLoader(); - let callbacks = 0; - - let item = new loader.cm.Item({ - label: "item", - contentScript: 'self.on("context", function (node) {' + - ' self.postMessage(node.tagName);' + - ' return false;' + - '});', - onMessage: function (tagName) { - assert.equal(tagName, "HTML", "node should be an HTML element"); - if (++callbacks == 2) test.done(); - } - }); - - test.showMenu(null, function () { - if (++callbacks == 2) test.done(); - }); -}; - -// Multiple contexts imply intersection, not union. -exports.testMultipleContexts = function (assert, done) { - let test = new TestHelper(assert, done); - let loader = test.newLoader(); - - let item = new loader.cm.Item({ - label: "item", - context: [loader.cm.SelectorContext("a[href]"), loader.cm.PageContext()], - }); - - test.withTestDoc(function (window, doc) { - test.showMenu("#span-link", function (popup) { - test.checkMenu([item], [item], []); - test.done(); - }); - }); -}; - -// Once a context is removed, it should no longer cause its item to appear. -exports.testRemoveContext = function (assert, done) { - let test = new TestHelper(assert, done); - let loader = test.newLoader(); - - let ctxt = loader.cm.SelectorContext("img"); - let item = new loader.cm.Item({ - label: "item", - context: ctxt - }); - - test.withTestDoc(function (window, doc) { - test.showMenu("#image", function (popup) { - - // The item should be present at first. - test.checkMenu([item], [], []); - popup.hidePopup(); - - // Remove the img context and check again. - item.context.remove(ctxt); - test.showMenu("#image", function (popup) { - test.checkMenu([item], [item], []); - test.done(); - }); - }); - }); -}; - -// Once a context is removed, it should no longer cause its item to appear. -exports.testSetContextRemove = function (assert, done) { - let test = new TestHelper(assert, done); - let loader = test.newLoader(); - - let ctxt = loader.cm.SelectorContext("img"); - let item = new loader.cm.Item({ - label: "item", - context: ctxt - }); - - test.withTestDoc(function (window, doc) { - test.showMenu("#image", function (popup) { - - // The item should be present at first. - test.checkMenu([item], [], []); - popup.hidePopup(); - - // Remove the img context and check again. - item.context = []; - test.showMenu("#image", function (popup) { - test.checkMenu([item], [item], []); - test.done(); - }); - }); - }); -}; - -// Once a context is added, it should affect whether the item appears. -exports.testAddContext = function (assert, done) { - let test = new TestHelper(assert, done); - let loader = test.newLoader(); - - let ctxt = loader.cm.SelectorContext("img"); - let item = new loader.cm.Item({ - label: "item" - }); - - test.withTestDoc(function (window, doc) { - test.showMenu("#image", function (popup) { - - // The item should not be present at first. - test.checkMenu([item], [item], []); - popup.hidePopup(); - - // Add the img context and check again. - item.context.add(ctxt); - test.showMenu("#image", function (popup) { - test.checkMenu([item], [], []); - test.done(); - }); - }); - }); -}; - -// Once a context is added, it should affect whether the item appears. -exports.testSetContextAdd = function (assert, done) { - let test = new TestHelper(assert, done); - let loader = test.newLoader(); - - let ctxt = loader.cm.SelectorContext("img"); - let item = new loader.cm.Item({ - label: "item" - }); - - test.withTestDoc(function (window, doc) { - test.showMenu("#image", function (popup) { - - // The item should not be present at first. - test.checkMenu([item], [item], []); - popup.hidePopup(); - - // Add the img context and check again. - item.context = [ctxt]; - test.showMenu("#image", function (popup) { - test.checkMenu([item], [], []); - test.done(); - }); - }); - }); -}; - -// Lots of items should overflow into the overflow submenu. -exports.testOverflow = function (assert, done) { - let test = new TestHelper(assert, done); - let loader = test.newLoader(); - - let items = []; - for (let i = 0; i < OVERFLOW_THRESH_DEFAULT + 1; i++) { - let item = new loader.cm.Item({ label: "item " + i }); - items.push(item); - } - - test.showMenu(null, function (popup) { - test.checkMenu(items, [], []); - test.done(); - }); -}; - - -// Module unload should cause all items to be removed. -exports.testUnload = function (assert, done) { - let test = new TestHelper(assert, done); - let loader = test.newLoader(); - - let item = new loader.cm.Item({ label: "item" }); - - test.showMenu(null, function (popup) { - - // The menu should contain the item. - test.checkMenu([item], [], []); - popup.hidePopup(); - - // Unload the module. - loader.unload(); - test.showMenu(null, function (popup) { - - // The item should be removed from the menu. - test.checkMenu([item], [], [item]); - test.done(); - }); - }); -}; - - -// Using multiple module instances to add items without causing overflow should -// work OK. Assumes OVERFLOW_THRESH_DEFAULT >= 2. -exports.testMultipleModulesAdd = function (assert, done) { - let test = new TestHelper(assert, done); - let loader0 = test.newLoader(); - let loader1 = test.newLoader(); - - // Use each module to add an item, then unload each module in turn. - let item0 = new loader0.cm.Item({ label: "item 0" }); - let item1 = new loader1.cm.Item({ label: "item 1" }); - - test.showMenu(null, function (popup) { - - // The menu should contain both items. - test.checkMenu([item0, item1], [], []); - popup.hidePopup(); - - // Unload the first module. - loader0.unload(); - test.showMenu(null, function (popup) { - - // The first item should be removed from the menu. - test.checkMenu([item0, item1], [], [item0]); - popup.hidePopup(); - - // Unload the second module. - loader1.unload(); - test.showMenu(null, function (popup) { - - // Both items should be removed from the menu. - test.checkMenu([item0, item1], [], [item0, item1]); - test.done(); - }); - }); - }); -}; - - -// Using multiple module instances to add items causing overflow should work OK. -exports.testMultipleModulesAddOverflow = function (assert, done) { - let test = new TestHelper(assert, done); - let loader0 = test.newLoader(); - let loader1 = test.newLoader(); - - // Use module 0 to add OVERFLOW_THRESH_DEFAULT items. - let items0 = []; - for (let i = 0; i < OVERFLOW_THRESH_DEFAULT; i++) { - let item = new loader0.cm.Item({ label: "item 0 " + i }); - items0.push(item); - } - - // Use module 1 to add one item. - let item1 = new loader1.cm.Item({ label: "item 1" }); - - let allItems = items0.concat(item1); - - test.showMenu(null, function (popup) { - - // The menu should contain all items in overflow. - test.checkMenu(allItems, [], []); - popup.hidePopup(); - - // Unload the first module. - loader0.unload(); - test.showMenu(null, function (popup) { - - // The first items should be removed from the menu, which should not - // overflow. - test.checkMenu(allItems, [], items0); - popup.hidePopup(); - - // Unload the second module. - loader1.unload(); - test.showMenu(null, function (popup) { - - // All items should be removed from the menu. - test.checkMenu(allItems, [], allItems); - test.done(); - }); - }); - }); -}; - - -// Using multiple module instances to modify the menu without causing overflow -// should work OK. This test creates two loaders and: -// loader0 create item -> loader1 create item -> loader0.unload -> -// loader1.unload -exports.testMultipleModulesDiffContexts1 = function (assert, done) { - let test = new TestHelper(assert, done); - let loader0 = test.newLoader(); - let loader1 = test.newLoader(); - - let item0 = new loader0.cm.Item({ - label: "item 0", - context: loader0.cm.SelectorContext("img") - }); - - let item1 = new loader1.cm.Item({ label: "item 1" }); - - test.showMenu(null, function (popup) { - - // The menu should contain item1. - test.checkMenu([item0, item1], [item0], []); - popup.hidePopup(); - - // Unload module 0. - loader0.unload(); - test.showMenu(null, function (popup) { - - // item0 should be removed from the menu. - test.checkMenu([item0, item1], [], [item0]); - popup.hidePopup(); - - // Unload module 1. - loader1.unload(); - test.showMenu(null, function (popup) { - - // Both items should be removed from the menu. - test.checkMenu([item0, item1], [], [item0, item1]); - test.done(); - }); - }); - }); -}; - - -// Using multiple module instances to modify the menu without causing overflow -// should work OK. This test creates two loaders and: -// loader1 create item -> loader0 create item -> loader0.unload -> -// loader1.unload -exports.testMultipleModulesDiffContexts2 = function (assert, done) { - let test = new TestHelper(assert, done); - let loader0 = test.newLoader(); - let loader1 = test.newLoader(); - - let item1 = new loader1.cm.Item({ label: "item 1" }); - - let item0 = new loader0.cm.Item({ - label: "item 0", - context: loader0.cm.SelectorContext("img") - }); - - test.showMenu(null, function (popup) { - - // The menu should contain item1. - test.checkMenu([item0, item1], [item0], []); - popup.hidePopup(); - - // Unload module 0. - loader0.unload(); - test.showMenu(null, function (popup) { - - // item0 should be removed from the menu. - test.checkMenu([item0, item1], [], [item0]); - popup.hidePopup(); - - // Unload module 1. - loader1.unload(); - test.showMenu(null, function (popup) { - - // Both items should be removed from the menu. - test.checkMenu([item0, item1], [], [item0, item1]); - test.done(); - }); - }); - }); -}; - - -// Using multiple module instances to modify the menu without causing overflow -// should work OK. This test creates two loaders and: -// loader0 create item -> loader1 create item -> loader1.unload -> -// loader0.unload -exports.testMultipleModulesDiffContexts3 = function (assert, done) { - let test = new TestHelper(assert, done); - let loader0 = test.newLoader(); - let loader1 = test.newLoader(); - - let item0 = new loader0.cm.Item({ - label: "item 0", - context: loader0.cm.SelectorContext("img") - }); - - let item1 = new loader1.cm.Item({ label: "item 1" }); - - test.showMenu(null, function (popup) { - - // The menu should contain item1. - test.checkMenu([item0, item1], [item0], []); - popup.hidePopup(); - - // Unload module 1. - loader1.unload(); - test.showMenu(null, function (popup) { - - // item1 should be removed from the menu. - test.checkMenu([item0, item1], [item0], [item1]); - popup.hidePopup(); - - // Unload module 0. - loader0.unload(); - test.showMenu(null, function (popup) { - - // Both items should be removed from the menu. - test.checkMenu([item0, item1], [], [item0, item1]); - test.done(); - }); - }); - }); -}; - - -// Using multiple module instances to modify the menu without causing overflow -// should work OK. This test creates two loaders and: -// loader1 create item -> loader0 create item -> loader1.unload -> -// loader0.unload -exports.testMultipleModulesDiffContexts4 = function (assert, done) { - let test = new TestHelper(assert, done); - let loader0 = test.newLoader(); - let loader1 = test.newLoader(); - - let item1 = new loader1.cm.Item({ label: "item 1" }); - - let item0 = new loader0.cm.Item({ - label: "item 0", - context: loader0.cm.SelectorContext("img") - }); - - test.showMenu(null, function (popup) { - - // The menu should contain item1. - test.checkMenu([item0, item1], [item0], []); - popup.hidePopup(); - - // Unload module 1. - loader1.unload(); - test.showMenu(null, function (popup) { - - // item1 should be removed from the menu. - test.checkMenu([item0, item1], [item0], [item1]); - popup.hidePopup(); - - // Unload module 0. - loader0.unload(); - test.showMenu(null, function (popup) { - - // Both items should be removed from the menu. - test.checkMenu([item0, item1], [], [item0, item1]); - test.done(); - }); - }); - }); -}; - - -// Test interactions between a loaded module, unloading another module, and the -// menu separator and overflow submenu. -exports.testMultipleModulesAddRemove = function (assert, done) { - let test = new TestHelper(assert, done); - let loader0 = test.newLoader(); - let loader1 = test.newLoader(); - - let item = new loader0.cm.Item({ label: "item" }); - - test.showMenu(null, function (popup) { - - // The menu should contain the item. - test.checkMenu([item], [], []); - popup.hidePopup(); - - // Remove the item. - item.destroy(); - test.showMenu(null, function (popup) { - - // The item should be removed from the menu. - test.checkMenu([item], [], [item]); - popup.hidePopup(); - - // Unload module 1. - loader1.unload(); - test.showMenu(null, function (popup) { - - // There shouldn't be any errors involving the menu separator or - // overflow submenu. - test.checkMenu([item], [], [item]); - test.done(); - }); - }); - }); -}; - - -// Checks that the order of menu items is correct when adding/removing across -// multiple modules. All items from a single module should remain in a group -exports.testMultipleModulesOrder = function (assert, done) { - let test = new TestHelper(assert, done); - let loader0 = test.newLoader(); - let loader1 = test.newLoader(); - - // Use each module to add an item, then unload each module in turn. - let item0 = new loader0.cm.Item({ label: "item 0" }); - let item1 = new loader1.cm.Item({ label: "item 1" }); - - test.showMenu(null, function (popup) { - - // The menu should contain both items. - test.checkMenu([item0, item1], [], []); - popup.hidePopup(); - - let item2 = new loader0.cm.Item({ label: "item 2" }); - - test.showMenu(null, function (popup) { - - // The new item should be grouped with the same items from loader0. - test.checkMenu([item0, item2, item1], [], []); - popup.hidePopup(); - - let item3 = new loader1.cm.Item({ label: "item 3" }); - - test.showMenu(null, function (popup) { - - // Same again - test.checkMenu([item0, item2, item1, item3], [], []); - test.done(); - }); - }); - }); -}; - - -// Checks that the order of menu items is correct when adding/removing across -// multiple modules when overflowing. All items from a single module should -// remain in a group -exports.testMultipleModulesOrderOverflow = function (assert, done) { - let test = new TestHelper(assert, done); - let loader0 = test.newLoader(); - let loader1 = test.newLoader(); - - let prefs = loader0.loader.require("sdk/preferences/service"); - prefs.set(OVERFLOW_THRESH_PREF, 0); - - // Use each module to add an item, then unload each module in turn. - let item0 = new loader0.cm.Item({ label: "item 0" }); - let item1 = new loader1.cm.Item({ label: "item 1" }); - - test.showMenu(null, function (popup) { - - // The menu should contain both items. - test.checkMenu([item0, item1], [], []); - popup.hidePopup(); - - let item2 = new loader0.cm.Item({ label: "item 2" }); - - test.showMenu(null, function (popup) { - - // The new item should be grouped with the same items from loader0. - test.checkMenu([item0, item2, item1], [], []); - popup.hidePopup(); - - let item3 = new loader1.cm.Item({ label: "item 3" }); - - test.showMenu(null, function (popup) { - - // Same again - test.checkMenu([item0, item2, item1, item3], [], []); - test.done(); - }); - }); - }); -}; - - -// Checks that if a module's items are all hidden then the overflow menu doesn't -// get hidden -exports.testMultipleModulesOverflowHidden = function (assert, done) { - let test = new TestHelper(assert, done); - let loader0 = test.newLoader(); - let loader1 = test.newLoader(); - - let prefs = loader0.loader.require("sdk/preferences/service"); - prefs.set(OVERFLOW_THRESH_PREF, 0); - - // Use each module to add an item, then unload each module in turn. - let item0 = new loader0.cm.Item({ label: "item 0" }); - let item1 = new loader1.cm.Item({ - label: "item 1", - context: loader1.cm.SelectorContext("a") - }); - - test.showMenu(null, function (popup) { - // One should be hidden - test.checkMenu([item0, item1], [item1], []); - test.done(); - }); -}; - - -// Checks that if a module's items are all hidden then the overflow menu doesn't -// get hidden (reverse order to above) -exports.testMultipleModulesOverflowHidden2 = function (assert, done) { - let test = new TestHelper(assert, done); - let loader0 = test.newLoader(); - let loader1 = test.newLoader(); - - let prefs = loader0.loader.require("sdk/preferences/service"); - prefs.set(OVERFLOW_THRESH_PREF, 0); - - // Use each module to add an item, then unload each module in turn. - let item0 = new loader0.cm.Item({ - label: "item 0", - context: loader0.cm.SelectorContext("a") - }); - let item1 = new loader1.cm.Item({ label: "item 1" }); - - test.showMenu(null, function (popup) { - // One should be hidden - test.checkMenu([item0, item1], [item0], []); - test.done(); - }); -}; - - -// Checks that we don't overflow if there are more items than the overflow -// threshold but not all of them are visible -exports.testOverflowIgnoresHidden = function (assert, done) { - let test = new TestHelper(assert, done); - let loader = test.newLoader(); - - let prefs = loader.loader.require("sdk/preferences/service"); - prefs.set(OVERFLOW_THRESH_PREF, 2); - - let allItems = [ - new loader.cm.Item({ - label: "item 0" - }), - new loader.cm.Item({ - label: "item 1" - }), - new loader.cm.Item({ - label: "item 2", - context: loader.cm.SelectorContext("a") - }) - ]; - - test.showMenu(null, function (popup) { - // One should be hidden - test.checkMenu(allItems, [allItems[2]], []); - test.done(); - }); -}; - - -// Checks that we don't overflow if there are more items than the overflow -// threshold but not all of them are visible -exports.testOverflowIgnoresHiddenMultipleModules1 = function (assert, done) { - let test = new TestHelper(assert, done); - let loader0 = test.newLoader(); - let loader1 = test.newLoader(); - - let prefs = loader0.loader.require("sdk/preferences/service"); - prefs.set(OVERFLOW_THRESH_PREF, 2); - - let allItems = [ - new loader0.cm.Item({ - label: "item 0" - }), - new loader0.cm.Item({ - label: "item 1" - }), - new loader1.cm.Item({ - label: "item 2", - context: loader1.cm.SelectorContext("a") - }), - new loader1.cm.Item({ - label: "item 3", - context: loader1.cm.SelectorContext("a") - }) - ]; - - test.showMenu(null, function (popup) { - // One should be hidden - test.checkMenu(allItems, [allItems[2], allItems[3]], []); - test.done(); - }); -}; - - -// Checks that we don't overflow if there are more items than the overflow -// threshold but not all of them are visible -exports.testOverflowIgnoresHiddenMultipleModules2 = function (assert, done) { - let test = new TestHelper(assert, done); - let loader0 = test.newLoader(); - let loader1 = test.newLoader(); - - let prefs = loader0.loader.require("sdk/preferences/service"); - prefs.set(OVERFLOW_THRESH_PREF, 2); - - let allItems = [ - new loader0.cm.Item({ - label: "item 0" - }), - new loader0.cm.Item({ - label: "item 1", - context: loader0.cm.SelectorContext("a") - }), - new loader1.cm.Item({ - label: "item 2" - }), - new loader1.cm.Item({ - label: "item 3", - context: loader1.cm.SelectorContext("a") - }) - ]; - - test.showMenu(null, function (popup) { - // One should be hidden - test.checkMenu(allItems, [allItems[1], allItems[3]], []); - test.done(); - }); -}; - - -// Checks that we don't overflow if there are more items than the overflow -// threshold but not all of them are visible -exports.testOverflowIgnoresHiddenMultipleModules3 = function (assert, done) { - let test = new TestHelper(assert, done); - let loader0 = test.newLoader(); - let loader1 = test.newLoader(); - - let prefs = loader0.loader.require("sdk/preferences/service"); - prefs.set(OVERFLOW_THRESH_PREF, 2); - - let allItems = [ - new loader0.cm.Item({ - label: "item 0", - context: loader0.cm.SelectorContext("a") - }), - new loader0.cm.Item({ - label: "item 1", - context: loader0.cm.SelectorContext("a") - }), - new loader1.cm.Item({ - label: "item 2" - }), - new loader1.cm.Item({ - label: "item 3" - }) - ]; - - test.showMenu(null, function (popup) { - // One should be hidden - test.checkMenu(allItems, [allItems[0], allItems[1]], []); - test.done(); - }); -}; - - -// Tests that we transition between overflowing to non-overflowing to no items -// and back again -exports.testOverflowTransition = function (assert, done) { - let test = new TestHelper(assert, done); - let loader = test.newLoader(); - - let prefs = loader.loader.require("sdk/preferences/service"); - prefs.set(OVERFLOW_THRESH_PREF, 2); - - let pItems = [ - new loader.cm.Item({ - label: "item 0", - context: loader.cm.SelectorContext("p") - }), - new loader.cm.Item({ - label: "item 1", - context: loader.cm.SelectorContext("p") - }) - ]; - - let aItems = [ - new loader.cm.Item({ - label: "item 2", - context: loader.cm.SelectorContext("a") - }), - new loader.cm.Item({ - label: "item 3", - context: loader.cm.SelectorContext("a") - }) - ]; - - let allItems = pItems.concat(aItems); - - test.withTestDoc(function (window, doc) { - test.showMenu("#link", function (popup) { - // The menu should contain all items and will overflow - test.checkMenu(allItems, [], []); - popup.hidePopup(); - - test.showMenu("#text", function (popup) { - // Only contains hald the items and will not overflow - test.checkMenu(allItems, aItems, []); - popup.hidePopup(); - - test.showMenu(null, function (popup) { - // None of the items will be visible - test.checkMenu(allItems, allItems, []); - popup.hidePopup(); - - test.showMenu("#text", function (popup) { - // Only contains hald the items and will not overflow - test.checkMenu(allItems, aItems, []); - popup.hidePopup(); - - test.showMenu("#link", function (popup) { - // The menu should contain all items and will overflow - test.checkMenu(allItems, [], []); - popup.hidePopup(); - - test.showMenu(null, function (popup) { - // None of the items will be visible - test.checkMenu(allItems, allItems, []); - popup.hidePopup(); - - test.showMenu("#link", function (popup) { - // The menu should contain all items and will overflow - test.checkMenu(allItems, [], []); - test.done(); - }); - }); - }); - }); - }); - }); - }); - }); -}; - - -// An item's command listener should work. -exports.testItemCommand = function (assert, done) { - let test = new TestHelper(assert, done); - let loader = test.newLoader(); - - let item = new loader.cm.Item({ - label: "item", - data: "item data", - contentScript: 'self.on("click", function (node, data) {' + - ' self.postMessage({' + - ' tagName: node.tagName,' + - ' data: data' + - ' });' + - '});', - onMessage: function (data) { - assert.equal(this, item, "`this` inside onMessage should be item"); - assert.equal(data.tagName, "HTML", "node should be an HTML element"); - assert.equal(data.data, item.data, "data should be item data"); - test.done(); - } - }); - - test.showMenu(null, function (popup) { - test.checkMenu([item], [], []); - let elt = test.getItemElt(popup, item); - - // create a command event - let evt = elt.ownerDocument.createEvent('Event'); - evt.initEvent('command', true, true); - elt.dispatchEvent(evt); - }); -}; - - -// A menu's click listener should work and receive bubbling 'command' events from -// sub-items appropriately. This also tests menus and ensures that when a CSS -// selector context matches the clicked node's ancestor, the matching ancestor -// is passed to listeners as the clicked node. -exports.testMenuCommand = function (assert, done) { - // Create a top-level menu, submenu, and item, like this: - // topMenu -> submenu -> item - // Click the item and make sure the click bubbles. - let test = new TestHelper(assert, done); - let loader = test.newLoader(); - - let item = new loader.cm.Item({ - label: "submenu item", - data: "submenu item data", - context: loader.cm.SelectorContext("a"), - }); - - let submenu = new loader.cm.Menu({ - label: "submenu", - context: loader.cm.SelectorContext("a"), - items: [item] - }); - - let topMenu = new loader.cm.Menu({ - label: "top menu", - contentScript: 'self.on("click", function (node, data) {' + - ' self.postMessage({' + - ' tagName: node.tagName,' + - ' data: data' + - ' });' + - '});', - onMessage: function (data) { - assert.equal(this, topMenu, "`this` inside top menu should be menu"); - assert.equal(data.tagName, "A", "Clicked node should be anchor"); - assert.equal(data.data, item.data, - "Clicked item data should be correct"); - test.done(); - }, - items: [submenu], - context: loader.cm.SelectorContext("a") - }); - - test.withTestDoc(function (window, doc) { - test.showMenu("#span-link", function (popup) { - test.checkMenu([topMenu], [], []); - let topMenuElt = test.getItemElt(popup, topMenu); - let topMenuPopup = topMenuElt.firstChild; - let submenuElt = test.getItemElt(topMenuPopup, submenu); - let submenuPopup = submenuElt.firstChild; - let itemElt = test.getItemElt(submenuPopup, item); - - // create a command event - let evt = itemElt.ownerDocument.createEvent('Event'); - evt.initEvent('command', true, true); - itemElt.dispatchEvent(evt); - }); - }); -}; - - -// Click listeners should work when multiple modules are loaded. -exports.testItemCommandMultipleModules = function (assert, done) { - let test = new TestHelper(assert, done); - let loader0 = test.newLoader(); - let loader1 = test.newLoader(); - - let item0 = loader0.cm.Item({ - label: "loader 0 item", - contentScript: 'self.on("click", self.postMessage);', - onMessage: function () { - test.fail("loader 0 item should not emit click event"); - } - }); - let item1 = loader1.cm.Item({ - label: "loader 1 item", - contentScript: 'self.on("click", self.postMessage);', - onMessage: function () { - test.pass("loader 1 item clicked as expected"); - test.done(); - } - }); - - test.showMenu(null, function (popup) { - test.checkMenu([item0, item1], [], []); - let item1Elt = test.getItemElt(popup, item1); - - // create a command event - let evt = item1Elt.ownerDocument.createEvent('Event'); - evt.initEvent('command', true, true); - item1Elt.dispatchEvent(evt); - }); -}; - - - - -// An item's click listener should work. -exports.testItemClick = function (assert, done) { - let test = new TestHelper(assert, done); - let loader = test.newLoader(); - - let item = new loader.cm.Item({ - label: "item", - data: "item data", - contentScript: 'self.on("click", function (node, data) {' + - ' self.postMessage({' + - ' tagName: node.tagName,' + - ' data: data' + - ' });' + - '});', - onMessage: function (data) { - assert.equal(this, item, "`this` inside onMessage should be item"); - assert.equal(data.tagName, "HTML", "node should be an HTML element"); - assert.equal(data.data, item.data, "data should be item data"); - test.done(); - } - }); - - test.showMenu(null, function (popup) { - test.checkMenu([item], [], []); - let elt = test.getItemElt(popup, item); - elt.click(); - }); -}; - - -// A menu's click listener should work and receive bubbling clicks from -// sub-items appropriately. This also tests menus and ensures that when a CSS -// selector context matches the clicked node's ancestor, the matching ancestor -// is passed to listeners as the clicked node. -exports.testMenuClick = function (assert, done) { - // Create a top-level menu, submenu, and item, like this: - // topMenu -> submenu -> item - // Click the item and make sure the click bubbles. - let test = new TestHelper(assert, done); - let loader = test.newLoader(); - - let item = new loader.cm.Item({ - label: "submenu item", - data: "submenu item data", - context: loader.cm.SelectorContext("a"), - }); - - let submenu = new loader.cm.Menu({ - label: "submenu", - context: loader.cm.SelectorContext("a"), - items: [item] - }); - - let topMenu = new loader.cm.Menu({ - label: "top menu", - contentScript: 'self.on("click", function (node, data) {' + - ' self.postMessage({' + - ' tagName: node.tagName,' + - ' data: data' + - ' });' + - '});', - onMessage: function (data) { - assert.equal(this, topMenu, "`this` inside top menu should be menu"); - assert.equal(data.tagName, "A", "Clicked node should be anchor"); - assert.equal(data.data, item.data, - "Clicked item data should be correct"); - test.done(); - }, - items: [submenu], - context: loader.cm.SelectorContext("a") - }); - - test.withTestDoc(function (window, doc) { - test.showMenu("#span-link", function (popup) { - test.checkMenu([topMenu], [], []); - let topMenuElt = test.getItemElt(popup, topMenu); - let topMenuPopup = topMenuElt.firstChild; - let submenuElt = test.getItemElt(topMenuPopup, submenu); - let submenuPopup = submenuElt.firstChild; - let itemElt = test.getItemElt(submenuPopup, item); - itemElt.click(); - }); - }); -}; - -// Click listeners should work when multiple modules are loaded. -exports.testItemClickMultipleModules = function (assert, done) { - let test = new TestHelper(assert, done); - let loader0 = test.newLoader(); - let loader1 = test.newLoader(); - - let item0 = loader0.cm.Item({ - label: "loader 0 item", - contentScript: 'self.on("click", self.postMessage);', - onMessage: function () { - test.fail("loader 0 item should not emit click event"); - } - }); - let item1 = loader1.cm.Item({ - label: "loader 1 item", - contentScript: 'self.on("click", self.postMessage);', - onMessage: function () { - test.pass("loader 1 item clicked as expected"); - test.done(); - } - }); - - test.showMenu(null, function (popup) { - test.checkMenu([item0, item1], [], []); - let item1Elt = test.getItemElt(popup, item1); - item1Elt.click(); - }); -}; - - -// Adding a separator to a submenu should work OK. -exports.testSeparator = function (assert, done) { - let test = new TestHelper(assert, done); - let loader = test.newLoader(); - - let menu = new loader.cm.Menu({ - label: "submenu", - items: [new loader.cm.Separator()] - }); - - test.showMenu(null, function (popup) { - test.checkMenu([menu], [], []); - test.done(); - }); -}; - - -// The parentMenu option should work -exports.testParentMenu = function (assert, done) { - let test = new TestHelper(assert, done); - let loader = test.newLoader(); - - let menu = new loader.cm.Menu({ - label: "submenu", - items: [loader.cm.Item({ label: "item 1" })], - parentMenu: loader.cm.contentContextMenu - }); - - let item = loader.cm.Item({ - label: "item 2", - parentMenu: menu, - }); - - assert.equal(menu.items[1], item, "Item should be in the sub menu"); - - test.showMenu(null, function (popup) { - test.checkMenu([menu], [], []); - test.done(); - }); -}; - - -// Existing context menu modifications should apply to new windows. -exports.testNewWindow = function (assert, done) { - let test = new TestHelper(assert, done); - let loader = test.newLoader(); - - let item = new loader.cm.Item({ label: "item" }); - - test.withNewWindow(function () { - test.showMenu(null, function (popup) { - test.checkMenu([item], [], []); - test.done(); - }); - }); -}; - - -// When a new window is opened, items added by an unloaded module should not -// be present in the menu. -exports.testNewWindowMultipleModules = function (assert, done) { - let test = new TestHelper(assert, done); - let loader = test.newLoader(); - let item = new loader.cm.Item({ label: "item" }); - - test.showMenu(null, function (popup) { - test.checkMenu([item], [], []); - popup.hidePopup(); - loader.unload(); - test.withNewWindow(function () { - test.showMenu(null, function (popup) { - test.checkMenu([item], [], [item]); - test.done(); - }); - }); - }); -}; - - -// Existing context menu modifications should not apply to new private windows. -exports.testNewPrivateWindow = function (assert, done) { - let test = new TestHelper(assert, done); - let loader = test.newLoader(); - - let item = new loader.cm.Item({ label: "item" }); - - test.showMenu(null, function (popup) { - test.checkMenu([item], [], []); - popup.hidePopup(); - - test.withNewPrivateWindow(function () { - test.showMenu(null, function (popup) { - test.checkMenu([], [], []); - test.done(); - }); - }); - }); -}; - - -// Existing context menu modifications should apply to new private windows when -// private browsing support is enabled. -exports.testNewPrivateEnabledWindow = function (assert, done) { - let test = new TestHelper(assert, done); - let loader = test.newPrivateLoader(); - - let item = new loader.cm.Item({ label: "item" }); - - test.showMenu(null, function (popup) { - test.checkMenu([item], [], []); - popup.hidePopup(); - - test.withNewPrivateWindow(function () { - test.showMenu(null, function (popup) { - test.checkMenu([item], [], []); - test.done(); - }); - }); - }); -}; - - -// Existing context menu modifications should apply to new private windows when -// private browsing support is enabled unless unloaded. -exports.testNewPrivateEnabledWindowUnloaded = function (assert, done) { - let test = new TestHelper(assert, done); - let loader = test.newPrivateLoader(); - - let item = new loader.cm.Item({ label: "item" }); - - test.showMenu(null, function (popup) { - test.checkMenu([item], [], []); - popup.hidePopup(); - - loader.unload(); - - test.withNewPrivateWindow(function () { - test.showMenu(null, function (popup) { - test.checkMenu([], [], []); - test.done(); - }); - }); - }); -}; - - -// Items in the context menu should be sorted according to locale. -exports.testSorting = function (assert, done) { - let test = new TestHelper(assert, done); - let loader = test.newLoader(); - - // Make an unsorted items list. It'll look like this: - // item 1, item 0, item 3, item 2, item 5, item 4, ... - let items = []; - for (let i = 0; i < OVERFLOW_THRESH_DEFAULT; i += 2) { - items.push(new loader.cm.Item({ label: "item " + (i + 1) })); - items.push(new loader.cm.Item({ label: "item " + i })); - } - - test.showMenu(null, function (popup) { - test.checkMenu(items, [], []); - test.done(); - }); -}; - - -// Items in the overflow menu should be sorted according to locale. -exports.testSortingOverflow = function (assert, done) { - let test = new TestHelper(assert, done); - let loader = test.newLoader(); - - // Make an unsorted items list. It'll look like this: - // item 1, item 0, item 3, item 2, item 5, item 4, ... - let items = []; - for (let i = 0; i < OVERFLOW_THRESH_DEFAULT * 2; i += 2) { - items.push(new loader.cm.Item({ label: "item " + (i + 1) })); - items.push(new loader.cm.Item({ label: "item " + i })); - } - - test.showMenu(null, function (popup) { - test.checkMenu(items, [], []); - test.done(); - }); -}; - - -// Multiple modules shouldn't interfere with sorting. -exports.testSortingMultipleModules = function (assert, done) { - let test = new TestHelper(assert, done); - let loader0 = test.newLoader(); - let loader1 = test.newLoader(); - - let items0 = []; - let items1 = []; - for (let i = 0; i < OVERFLOW_THRESH_DEFAULT; i++) { - if (i % 2) { - let item = new loader0.cm.Item({ label: "item " + i }); - items0.push(item); - } - else { - let item = new loader1.cm.Item({ label: "item " + i }); - items1.push(item); - } - } - let allItems = items0.concat(items1); - - test.showMenu(null, function (popup) { - - // All items should be present and sorted. - test.checkMenu(allItems, [], []); - popup.hidePopup(); - loader0.unload(); - loader1.unload(); - test.showMenu(null, function (popup) { - - // All items should be removed. - test.checkMenu(allItems, [], allItems); - test.done(); - }); - }); -}; - - -// Content click handlers and context handlers should be able to communicate, -// i.e., they're eval'ed in the same worker and sandbox. -exports.testContentCommunication = function (assert, done) { - let test = new TestHelper(assert, done); - let loader = test.newLoader(); - - let item = new loader.cm.Item({ - label: "item", - contentScript: 'var potato;' + - 'self.on("context", function () {' + - ' potato = "potato";' + - ' return true;' + - '});' + - 'self.on("click", function () {' + - ' self.postMessage(potato);' + - '});', - }); - - item.on("message", function (data) { - assert.equal(data, "potato", "That's a lot of potatoes!"); - test.done(); - }); - - test.showMenu(null, function (popup) { - test.checkMenu([item], [], []); - let elt = test.getItemElt(popup, item); - elt.click(); - }); -}; - - -// When the context menu is invoked on a tab that was already open when the -// module was loaded, it should contain the expected items and content workers -// should function as expected. -exports.testLoadWithOpenTab = function (assert, done) { - let test = new TestHelper(assert, done); - test.withTestDoc(function (window, doc) { - let loader = test.newLoader(); - let item = new loader.cm.Item({ - label: "item", - contentScript: - 'self.on("click", () => self.postMessage("click"));', - onMessage: function (msg) { - if (msg === "click") - test.done(); - } - }); - test.showMenu(null, function (popup) { - test.checkMenu([item], [], []); - test.getItemElt(popup, item).click(); - }); - }); -}; - -// Bug 732716: Ensure that the node given in `click` event works fine -// (i.e. is correctly wrapped) -exports.testDrawImageOnClickNode = function (assert, done) { - let test = new TestHelper(assert, done); - test.withTestDoc(function (window, doc) { - let loader = test.newLoader(); - let item = new loader.cm.Item({ - label: "item", - context: loader.cm.SelectorContext("img"), - contentScript: "new " + function() { - self.on("click", function (img, data) { - let ctx = document.createElement("canvas").getContext("2d"); - ctx.drawImage(img, 1, 1, 1, 1); - self.postMessage("done"); - }); - }, - onMessage: function (msg) { - if (msg === "done") - test.done(); - } - }); - test.showMenu("#image", function (popup) { - test.checkMenu([item], [], []); - test.getItemElt(popup, item).click(); - }); - }); -}; - - -// Setting an item's label before the menu is ever shown should correctly change -// its label. -exports.testSetLabelBeforeShow = function (assert, done) { - let test = new TestHelper(assert, done); - let loader = test.newLoader(); - - let items = [ - new loader.cm.Item({ label: "a" }), - new loader.cm.Item({ label: "b" }) - ] - items[0].label = "z"; - assert.equal(items[0].label, "z"); - - test.showMenu(null, function (popup) { - test.checkMenu(items, [], []); - test.done(); - }); -}; - - -// Setting an item's label after the menu is shown should correctly change its -// label. -exports.testSetLabelAfterShow = function (assert, done) { - let test = new TestHelper(assert, done); - let loader = test.newLoader(); - - let items = [ - new loader.cm.Item({ label: "a" }), - new loader.cm.Item({ label: "b" }) - ]; - - test.showMenu(null, function (popup) { - test.checkMenu(items, [], []); - popup.hidePopup(); - - items[0].label = "z"; - assert.equal(items[0].label, "z"); - test.showMenu(null, function (popup) { - test.checkMenu(items, [], []); - test.done(); - }); - }); -}; - - -// Setting an item's label before the menu is ever shown should correctly change -// its label. -exports.testSetLabelBeforeShowOverflow = function (assert, done) { - let test = new TestHelper(assert, done); - let loader = test.newLoader(); - - let prefs = loader.loader.require("sdk/preferences/service"); - prefs.set(OVERFLOW_THRESH_PREF, 0); - - let items = [ - new loader.cm.Item({ label: "a" }), - new loader.cm.Item({ label: "b" }) - ] - items[0].label = "z"; - assert.equal(items[0].label, "z"); - - test.showMenu(null, function (popup) { - test.checkMenu(items, [], []); - test.done(); - }); -}; - - -// Setting an item's label after the menu is shown should correctly change its -// label. -exports.testSetLabelAfterShowOverflow = function (assert, done) { - let test = new TestHelper(assert, done); - let loader = test.newLoader(); - - let prefs = loader.loader.require("sdk/preferences/service"); - prefs.set(OVERFLOW_THRESH_PREF, 0); - - let items = [ - new loader.cm.Item({ label: "a" }), - new loader.cm.Item({ label: "b" }) - ]; - - test.showMenu(null, function (popup) { - test.checkMenu(items, [], []); - popup.hidePopup(); - - items[0].label = "z"; - assert.equal(items[0].label, "z"); - test.showMenu(null, function (popup) { - test.checkMenu(items, [], []); - test.done(); - }); - }); -}; - - -// Setting the label of an item in a Menu should work. -exports.testSetLabelMenuItem = function (assert, done) { - let test = new TestHelper(assert, done); - let loader = test.newLoader(); - - let menu = loader.cm.Menu({ - label: "menu", - items: [loader.cm.Item({ label: "a" })] - }); - menu.items[0].label = "z"; - - assert.equal(menu.items[0].label, "z"); - - test.showMenu(null, function (popup) { - test.checkMenu([menu], [], []); - test.done(); - }); -}; - - -// Menu.addItem() should work. -exports.testMenuAddItem = function (assert, done) { - let test = new TestHelper(assert, done); - let loader = test.newLoader(); - - let menu = loader.cm.Menu({ - label: "menu", - items: [ - loader.cm.Item({ label: "item 0" }) - ] - }); - menu.addItem(loader.cm.Item({ label: "item 1" })); - menu.addItem(loader.cm.Item({ label: "item 2" })); - - assert.equal(menu.items.length, 3, - "menu should have correct number of items"); - for (let i = 0; i < 3; i++) { - assert.equal(menu.items[i].label, "item " + i, - "item label should be correct"); - assert.equal(menu.items[i].parentMenu, menu, - "item's parent menu should be correct"); - } - - test.showMenu(null, function (popup) { - test.checkMenu([menu], [], []); - test.done(); - }); -}; - - -// Adding the same item twice to a menu should work as expected. -exports.testMenuAddItemTwice = function (assert, done) { - let test = new TestHelper(assert, done); - let loader = test.newLoader(); - - let menu = loader.cm.Menu({ - label: "menu", - items: [] - }); - let subitem = loader.cm.Item({ label: "item 1" }) - menu.addItem(subitem); - menu.addItem(loader.cm.Item({ label: "item 0" })); - menu.addItem(subitem); - - assert.equal(menu.items.length, 2, - "menu should have correct number of items"); - for (let i = 0; i < 2; i++) { - assert.equal(menu.items[i].label, "item " + i, - "item label should be correct"); - } - - test.showMenu(null, function (popup) { - test.checkMenu([menu], [], []); - test.done(); - }); -}; - - -// Menu.removeItem() should work. -exports.testMenuRemoveItem = function (assert, done) { - let test = new TestHelper(assert, done); - let loader = test.newLoader(); - - let subitem = loader.cm.Item({ label: "item 1" }); - let menu = loader.cm.Menu({ - label: "menu", - items: [ - loader.cm.Item({ label: "item 0" }), - subitem, - loader.cm.Item({ label: "item 2" }) - ] - }); - - // Removing twice should be harmless. - menu.removeItem(subitem); - menu.removeItem(subitem); - - assert.equal(subitem.parentMenu, null, - "item's parent menu should be correct"); - - assert.equal(menu.items.length, 2, - "menu should have correct number of items"); - assert.equal(menu.items[0].label, "item 0", - "item label should be correct"); - assert.equal(menu.items[1].label, "item 2", - "item label should be correct"); - - test.showMenu(null, function (popup) { - test.checkMenu([menu], [], []); - test.done(); - }); -}; - - -// Adding an item currently contained in one menu to another menu should work. -exports.testMenuItemSwap = function (assert, done) { - let test = new TestHelper(assert, done); - let loader = test.newLoader(); - - let subitem = loader.cm.Item({ label: "item" }); - let menu0 = loader.cm.Menu({ - label: "menu 0", - items: [subitem] - }); - let menu1 = loader.cm.Menu({ - label: "menu 1", - items: [] - }); - menu1.addItem(subitem); - - assert.equal(menu0.items.length, 0, - "menu should have correct number of items"); - - assert.equal(menu1.items.length, 1, - "menu should have correct number of items"); - assert.equal(menu1.items[0].label, "item", - "item label should be correct"); - - assert.equal(subitem.parentMenu, menu1, - "item's parent menu should be correct"); - - test.showMenu(null, function (popup) { - test.checkMenu([menu0, menu1], [menu0], []); - test.done(); - }); -}; - - -// Destroying an item should remove it from its parent menu. -exports.testMenuItemDestroy = function (assert, done) { - let test = new TestHelper(assert, done); - let loader = test.newLoader(); - - let subitem = loader.cm.Item({ label: "item" }); - let menu = loader.cm.Menu({ - label: "menu", - items: [subitem] - }); - subitem.destroy(); - - assert.equal(menu.items.length, 0, - "menu should have correct number of items"); - assert.equal(subitem.parentMenu, null, - "item's parent menu should be correct"); - - test.showMenu(null, function (popup) { - test.checkMenu([menu], [menu], []); - test.done(); - }); -}; - - -// Setting Menu.items should work. -exports.testMenuItemsSetter = function (assert, done) { - let test = new TestHelper(assert, done); - let loader = test.newLoader(); - - let menu = loader.cm.Menu({ - label: "menu", - items: [ - loader.cm.Item({ label: "old item 0" }), - loader.cm.Item({ label: "old item 1" }) - ] - }); - menu.items = [ - loader.cm.Item({ label: "new item 0" }), - loader.cm.Item({ label: "new item 1" }), - loader.cm.Item({ label: "new item 2" }) - ]; - - assert.equal(menu.items.length, 3, - "menu should have correct number of items"); - for (let i = 0; i < 3; i++) { - assert.equal(menu.items[i].label, "new item " + i, - "item label should be correct"); - assert.equal(menu.items[i].parentMenu, menu, - "item's parent menu should be correct"); - } - - test.showMenu(null, function (popup) { - test.checkMenu([menu], [], []); - test.done(); - }); -}; - - -// Setting Item.data should work. -exports.testItemDataSetter = function (assert, done) { - let test = new TestHelper(assert, done); - let loader = test.newLoader(); - - let item = loader.cm.Item({ label: "old item 0", data: "old" }); - item.data = "new"; - - assert.equal(item.data, "new", "item should have correct data"); - - test.showMenu(null, function (popup) { - test.checkMenu([item], [], []); - test.done(); - }); -}; - - -// Open the test doc, load the module, make sure items appear when context- -// clicking the iframe. -exports.testAlreadyOpenIframe = function (assert, done) { - let test = new TestHelper(assert, done); - test.withTestDoc(function (window, doc) { - let loader = test.newLoader(); - let item = new loader.cm.Item({ - label: "item" - }); - test.showMenu("#iframe", function (popup) { - test.checkMenu([item], [], []); - test.done(); - }); - }); -}; - - -// Tests that a missing label throws an exception -exports.testItemNoLabel = function (assert, done) { - let test = new TestHelper(assert, done); - let loader = test.newLoader(); - - try { - new loader.cm.Item({}); - assert.ok(false, "Should have seen exception"); - } - catch (e) { - assert.ok(true, "Should have seen exception"); - } - - try { - new loader.cm.Item({ label: null }); - assert.ok(false, "Should have seen exception"); - } - catch (e) { - assert.ok(true, "Should have seen exception"); - } - - try { - new loader.cm.Item({ label: undefined }); - assert.ok(false, "Should have seen exception"); - } - catch (e) { - assert.ok(true, "Should have seen exception"); - } - - try { - new loader.cm.Item({ label: "" }); - assert.ok(false, "Should have seen exception"); - } - catch (e) { - assert.ok(true, "Should have seen exception"); - } - - test.done(); -} - -/* bug 1302854 - disabled this subtest as it is intermittent -// Tests that items can have an empty data property -exports.testItemNoData = function (assert, done) { - let test = new TestHelper(assert, done); - let loader = test.newLoader(); - - function checkData(data) { - assert.equal(data, undefined, "Data should be undefined"); - } - - let item1 = new loader.cm.Item({ - label: "item 1", - contentScript: 'self.on("click", (node, data) => self.postMessage(data))', - onMessage: checkData - }); - let item2 = new loader.cm.Item({ - label: "item 2", - data: null, - contentScript: 'self.on("click", (node, data) => self.postMessage(data))', - onMessage: checkData - }); - let item3 = new loader.cm.Item({ - label: "item 3", - data: undefined, - contentScript: 'self.on("click", (node, data) => self.postMessage(data))', - onMessage: checkData - }); - - assert.equal(item1.data, undefined, "Should be no defined data"); - assert.equal(item2.data, null, "Should be no defined data"); - assert.equal(item3.data, undefined, "Should be no defined data"); - - test.showMenu(null, function (popup) { - test.checkMenu([item1, item2, item3], [], []); - - let itemElt = test.getItemElt(popup, item1); - itemElt.click(); - - test.hideMenu(function() { - test.showMenu(null, function (popup) { - let itemElt = test.getItemElt(popup, item2); - itemElt.click(); - - test.hideMenu(function() { - test.showMenu(null, function (popup) { - let itemElt = test.getItemElt(popup, item3); - itemElt.click(); - - test.done(); - }); - }); - }); - }); - }); -} -*/ - - -exports.testItemNoAccessKey = function (assert, done) { - let test = new TestHelper(assert, done); - let loader = test.newLoader(); - - let item1 = new loader.cm.Item({ label: "item 1" }); - let item2 = new loader.cm.Item({ label: "item 2", accesskey: null }); - let item3 = new loader.cm.Item({ label: "item 3", accesskey: undefined }); - - assert.equal(item1.accesskey, undefined, "Should be no defined image"); - assert.equal(item2.accesskey, null, "Should be no defined image"); - assert.equal(item3.accesskey, undefined, "Should be no defined image"); - - test.showMenu(). - then((popup) => test.checkMenu([item1, item2, item3], [], [])). - then(test.done). - catch(assert.fail); -} - - -// Test accesskey support. -exports.testItemAccessKey = function (assert, done) { - let test = new TestHelper(assert, done); - let loader = test.newLoader(); - - let item = new loader.cm.Item({ label: "item", accesskey: "i" }); - assert.equal(item.accesskey, "i", "Should have set the image to i"); - - let menu = new loader.cm.Menu({ label: "menu", accesskey: "m", items: [ - loader.cm.Item({ label: "subitem" }) - ]}); - assert.equal(menu.accesskey, "m", "Should have set the accesskey to m"); - - test.showMenu().then((popup) => { - test.checkMenu([item, menu], [], []); - - let accesskey = "e"; - menu.accesskey = item.accesskey = accesskey; - assert.equal(item.accesskey, accesskey, "Should have set the accesskey to " + accesskey); - assert.equal(menu.accesskey, accesskey, "Should have set the accesskey to " + accesskey); - test.checkMenu([item, menu], [], []); - - item.accesskey = null; - menu.accesskey = null; - assert.equal(item.accesskey, null, "Should have set the accesskey to " + accesskey); - assert.equal(menu.accesskey, null, "Should have set the accesskey to " + accesskey); - test.checkMenu([item, menu], [], []); - }). - then(test.done). - catch(assert.fail); -}; - - -// Tests that items without an image don't attempt to show one -exports.testItemNoImage = function (assert, done) { - let test = new TestHelper(assert, done); - let loader = test.newLoader(); - - let item1 = new loader.cm.Item({ label: "item 1" }); - let item2 = new loader.cm.Item({ label: "item 2", image: null }); - let item3 = new loader.cm.Item({ label: "item 3", image: undefined }); - - assert.equal(item1.image, undefined, "Should be no defined image"); - assert.equal(item2.image, null, "Should be no defined image"); - assert.equal(item3.image, undefined, "Should be no defined image"); - - test.showMenu(null, function (popup) { - test.checkMenu([item1, item2, item3], [], []); - - test.done(); - }); -} - - -// Test image support. -exports.testItemImage = function (assert, done) { - let test = new TestHelper(assert, done); - let loader = test.newLoader(); - - let imageURL = data.url("moz_favicon.ico"); - let item = new loader.cm.Item({ label: "item", image: imageURL }); - let menu = new loader.cm.Menu({ label: "menu", image: imageURL, items: [ - loader.cm.Item({ label: "subitem" }) - ]}); - assert.equal(item.image, imageURL, "Should have set the image correctly"); - assert.equal(menu.image, imageURL, "Should have set the image correctly"); - - test.showMenu(null, function (popup) { - test.checkMenu([item, menu], [], []); - - let imageURL2 = data.url("dummy.ico"); - item.image = imageURL2; - menu.image = imageURL2; - assert.equal(item.image, imageURL2, "Should have set the image correctly"); - assert.equal(menu.image, imageURL2, "Should have set the image correctly"); - test.checkMenu([item, menu], [], []); - - item.image = null; - menu.image = null; - assert.equal(item.image, null, "Should have set the image correctly"); - assert.equal(menu.image, null, "Should have set the image correctly"); - test.checkMenu([item, menu], [], []); - - test.done(); - }); -}; - -// Test image URL validation. -exports.testItemImageValidURL = function (assert, done) { - let test = new TestHelper(assert, done); - let loader = test.newLoader(); - - assert.throws(function(){ - new loader.cm.Item({ - label: "item 1", - image: "foo" - }) - }, /Image URL validation failed/ - ); - - assert.throws(function(){ - new loader.cm.Item({ - label: "item 2", - image: false - }) - }, /Image URL validation failed/ - ); - - assert.throws(function(){ - new loader.cm.Item({ - label: "item 3", - image: 0 - }) - }, /Image URL validation failed/ - ); - - let imageURL = data.url("moz_favicon.ico"); - let item4 = new loader.cm.Item({ label: "item 4", image: imageURL }); - let item5 = new loader.cm.Item({ label: "item 5", image: null }); - let item6 = new loader.cm.Item({ label: "item 6", image: undefined }); - - assert.equal(item4.image, imageURL, "Should be proper image URL"); - assert.equal(item5.image, null, "Should be null image"); - assert.equal(item6.image, undefined, "Should be undefined image"); - - test.done(); -}; - - -// Menu.destroy should destroy the item tree rooted at that menu. -exports.testMenuDestroy = function (assert, done) { - let test = new TestHelper(assert, done); - let loader = test.newLoader(); - - let menu = loader.cm.Menu({ - label: "menu", - items: [ - loader.cm.Item({ label: "item 0" }), - loader.cm.Menu({ - label: "item 1", - items: [ - loader.cm.Item({ label: "subitem 0" }), - loader.cm.Item({ label: "subitem 1" }), - loader.cm.Item({ label: "subitem 2" }) - ] - }), - loader.cm.Item({ label: "item 2" }) - ] - }); - menu.destroy(); - - /*let numRegistryEntries = 0; - loader.globalScope.browserManager.browserWins.forEach(function (bwin) { - for (let itemID in bwin.items) - numRegistryEntries++; - }); - assert.equal(numRegistryEntries, 0, "All items should be unregistered.");*/ - - test.showMenu(null, function (popup) { - test.checkMenu([menu], [], [menu]); - test.done(); - }); -}; - -// Checks that if a menu contains sub items that are hidden then the menu is -// hidden too. Also checks that content scripts and contexts work for sub items. -exports.testSubItemContextNoMatchHideMenu = function (assert, done) { - let test = new TestHelper(assert, done); - let loader = test.newLoader(); - - let items = [ - loader.cm.Menu({ - label: "menu 1", - items: [ - loader.cm.Item({ - label: "subitem 1", - context: loader.cm.SelectorContext(".foo") - }) - ] - }), - loader.cm.Menu({ - label: "menu 2", - items: [ - loader.cm.Item({ - label: "subitem 2", - contentScript: 'self.on("context", () => false);' - }) - ] - }), - loader.cm.Menu({ - label: "menu 3", - items: [ - loader.cm.Item({ - label: "subitem 3", - context: loader.cm.SelectorContext(".foo") - }), - loader.cm.Item({ - label: "subitem 4", - contentScript: 'self.on("context", () => false);' - }) - ] - }) - ]; - - test.showMenu(null, function (popup) { - test.checkMenu(items, items, []); - test.done(); - }); -}; - - -// Checks that if a menu contains a combination of hidden and visible sub items -// then the menu is still visible too. -exports.testSubItemContextMatch = function (assert, done) { - let test = new TestHelper(assert, done); - let loader = test.newLoader(); - - let hiddenItems = [ - loader.cm.Item({ - label: "subitem 3", - context: loader.cm.SelectorContext(".foo") - }), - loader.cm.Item({ - label: "subitem 6", - contentScript: 'self.on("context", () => false);' - }) - ]; - - let items = [ - loader.cm.Menu({ - label: "menu 1", - items: [ - loader.cm.Item({ - label: "subitem 1", - context: loader.cm.URLContext(TEST_DOC_URL) - }) - ] - }), - loader.cm.Menu({ - label: "menu 2", - items: [ - loader.cm.Item({ - label: "subitem 2", - contentScript: 'self.on("context", () => true);' - }) - ] - }), - loader.cm.Menu({ - label: "menu 3", - items: [ - hiddenItems[0], - loader.cm.Item({ - label: "subitem 4", - contentScript: 'self.on("context", () => true);' - }) - ] - }), - loader.cm.Menu({ - label: "menu 4", - items: [ - loader.cm.Item({ - label: "subitem 5", - context: loader.cm.URLContext(TEST_DOC_URL) - }), - hiddenItems[1] - ] - }), - loader.cm.Menu({ - label: "menu 5", - items: [ - loader.cm.Item({ - label: "subitem 7", - context: loader.cm.URLContext(TEST_DOC_URL) - }), - loader.cm.Item({ - label: "subitem 8", - contentScript: 'self.on("context", () => true);' - }) - ] - }) - ]; - - test.withTestDoc(function (window, doc) { - test.showMenu(null, function (popup) { - test.checkMenu(items, hiddenItems, []); - test.done(); - }); - }); -}; - - -// Child items should default to visible, not to PageContext -exports.testSubItemDefaultVisible = function (assert, done) { - let test = new TestHelper(assert, done); - let loader = test.newLoader(); - - let items = [ - loader.cm.Menu({ - label: "menu 1", - context: loader.cm.SelectorContext("img"), - items: [ - loader.cm.Item({ - label: "subitem 1" - }), - loader.cm.Item({ - label: "subitem 2", - context: loader.cm.SelectorContext("img") - }), - loader.cm.Item({ - label: "subitem 3", - context: loader.cm.SelectorContext("a") - }) - ] - }) - ]; - - // subitem 3 will be hidden - let hiddenItems = [items[0].items[2]]; - - test.withTestDoc(function (window, doc) { - test.showMenu("#image", function (popup) { - test.checkMenu(items, hiddenItems, []); - test.done(); - }); - }); -}; - -// Tests that the click event on sub menuitem -// tiggers the click event for the sub menuitem and the parent menu -exports.testSubItemClick = function (assert, done) { - let test = new TestHelper(assert, done); - let loader = test.newLoader(); - - let state = 0; - - let items = [ - loader.cm.Menu({ - label: "menu 1", - items: [ - loader.cm.Item({ - label: "subitem 1", - data: "foobar", - contentScript: 'self.on("click", function (node, data) {' + - ' self.postMessage({' + - ' tagName: node.tagName,' + - ' data: data' + - ' });' + - '});', - onMessage: function(msg) { - assert.equal(msg.tagName, "HTML", "should have seen the right node"); - assert.equal(msg.data, "foobar", "should have seen the right data"); - assert.equal(state, 0, "should have seen the event at the right time"); - state++; - } - }) - ], - contentScript: 'self.on("click", function (node, data) {' + - ' self.postMessage({' + - ' tagName: node.tagName,' + - ' data: data' + - ' });' + - '});', - onMessage: function(msg) { - assert.equal(msg.tagName, "HTML", "should have seen the right node"); - assert.equal(msg.data, "foobar", "should have seen the right data"); - assert.equal(state, 1, "should have seen the event at the right time"); - - test.done(); - } - }) - ]; - - test.withTestDoc(function (window, doc) { - test.showMenu(null, function (popup) { - test.checkMenu(items, [], []); - - let topMenuElt = test.getItemElt(popup, items[0]); - let topMenuPopup = topMenuElt.firstChild; - let itemElt = test.getItemElt(topMenuPopup, items[0].items[0]); - itemElt.click(); - }); - }); -}; - -// Tests that the command event on sub menuitem -// tiggers the click event for the sub menuitem and the parent menu -exports.testSubItemCommand = function (assert, done) { - let test = new TestHelper(assert, done); - let loader = test.newLoader(); - - let state = 0; - - let items = [ - loader.cm.Menu({ - label: "menu 1", - items: [ - loader.cm.Item({ - label: "subitem 1", - data: "foobar", - contentScript: 'self.on("click", function (node, data) {' + - ' self.postMessage({' + - ' tagName: node.tagName,' + - ' data: data' + - ' });' + - '});', - onMessage: function(msg) { - assert.equal(msg.tagName, "HTML", "should have seen the right node"); - assert.equal(msg.data, "foobar", "should have seen the right data"); - assert.equal(state, 0, "should have seen the event at the right time"); - state++; - } - }) - ], - contentScript: 'self.on("click", function (node, data) {' + - ' self.postMessage({' + - ' tagName: node.tagName,' + - ' data: data' + - ' });' + - '});', - onMessage: function(msg) { - assert.equal(msg.tagName, "HTML", "should have seen the right node"); - assert.equal(msg.data, "foobar", "should have seen the right data"); - assert.equal(state, 1, "should have seen the event at the right time"); - state++ - - test.done(); - } - }) - ]; - - test.withTestDoc(function (window, doc) { - test.showMenu(null, function (popup) { - test.checkMenu(items, [], []); - - let topMenuElt = test.getItemElt(popup, items[0]); - let topMenuPopup = topMenuElt.firstChild; - let itemElt = test.getItemElt(topMenuPopup, items[0].items[0]); - - // create a command event - let evt = itemElt.ownerDocument.createEvent('Event'); - evt.initEvent('command', true, true); - itemElt.dispatchEvent(evt); - }); - }); -}; - -// Tests that opening a context menu for an outer frame when an inner frame -// has a selection doesn't activate the SelectionContext -exports.testSelectionInInnerFrameNoMatch = function (assert, done) { - let test = new TestHelper(assert, done); - let loader = test.newLoader(); - - let state = 0; - - let items = [ - loader.cm.Item({ - label: "test item", - context: loader.cm.SelectionContext() - }) - ]; - - test.withTestDoc(function (window, doc) { - let frame = doc.getElementById("iframe"); - frame.contentWindow.getSelection().selectAllChildren(frame.contentDocument.body); - - test.showMenu(null, function (popup) { - test.checkMenu(items, items, []); - test.done(); - }); - }); -}; - -// Tests that opening a context menu for an inner frame when the inner frame -// has a selection does activate the SelectionContext -exports.testSelectionInInnerFrameMatch = function (assert, done) { - let test = new TestHelper(assert, done); - let loader = test.newLoader(); - - let state = 0; - - let items = [ - loader.cm.Item({ - label: "test item", - context: loader.cm.SelectionContext() - }) - ]; - - test.withTestDoc(function (window, doc) { - let frame = doc.getElementById("iframe"); - frame.contentWindow.getSelection().selectAllChildren(frame.contentDocument.body); - - test.showMenu(["#iframe", "#text"], function (popup) { - test.checkMenu(items, [], []); - test.done(); - }); - }); -}; - -// Tests that opening a context menu for an inner frame when the outer frame -// has a selection doesn't activate the SelectionContext -exports.testSelectionInOuterFrameNoMatch = function (assert, done) { - let test = new TestHelper(assert, done); - let loader = test.newLoader(); - - let state = 0; - - let items = [ - loader.cm.Item({ - label: "test item", - context: loader.cm.SelectionContext() - }) - ]; - - test.withTestDoc(function (window, doc) { - let frame = doc.getElementById("iframe"); - window.getSelection().selectAllChildren(doc.body); - - test.showMenu(["#iframe", "#text"], function (popup) { - test.checkMenu(items, items, []); - test.done(); - }); - }); -}; - - -// Test that the return value of the predicate function determines if -// item is shown -exports.testPredicateContextControl = function (assert, done) { - let test = new TestHelper(assert, done); - let loader = test.newLoader(); - - let itemTrue = loader.cm.Item({ - label: "visible", - context: loader.cm.PredicateContext(function () { return true; }) - }); - - let itemFalse = loader.cm.Item({ - label: "hidden", - context: loader.cm.PredicateContext(function () { return false; }) - }); - - test.showMenu(null, function (popup) { - test.checkMenu([itemTrue, itemFalse], [itemFalse], []); - test.done(); - }); -}; - -// Test that the data object has the correct document type -exports.testPredicateContextDocumentType = function (assert, done) { - let test = new TestHelper(assert, done); - let loader = test.newLoader(); - - let items = [loader.cm.Item({ - label: "item", - context: loader.cm.PredicateContext(function (data) { - assert.equal(data.documentType, 'text/html'); - return true; - }) - })]; - - test.withTestDoc(function (window, doc) { - test.showMenu(null, function (popup) { - test.checkMenu(items, [], []); - test.done(); - }); - }); -}; - -// Test that the data object has the correct document URL -exports.testPredicateContextDocumentURL = function (assert, done) { - let test = new TestHelper(assert, done); - let loader = test.newLoader(); - - let items = [loader.cm.Item({ - label: "item", - context: loader.cm.PredicateContext(function (data) { - assert.equal(data.documentURL, TEST_DOC_URL); - return true; - }) - })]; - - test.withTestDoc(function (window, doc) { - test.showMenu(null, function (popup) { - test.checkMenu(items, [], []); - test.done(); - }); - }); -}; - - -// Test that the data object has the correct element name -exports.testPredicateContextTargetName = function (assert, done) { - let test = new TestHelper(assert, done); - let loader = test.newLoader(); - - let items = [loader.cm.Item({ - label: "item", - context: loader.cm.PredicateContext(function (data) { - assert.strictEqual(data.targetName, "input"); - return true; - }) - })]; - - test.withTestDoc(function (window, doc) { - test.showMenu("#button", function (popup) { - test.checkMenu(items, [], []); - test.done(); - }); - }); -}; - - -// Test that the data object has the correct ID -exports.testPredicateContextTargetIDSet = function (assert, done) { - let test = new TestHelper(assert, done); - let loader = test.newLoader(); - - let items = [loader.cm.Item({ - label: "item", - context: loader.cm.PredicateContext(function (data) { - assert.strictEqual(data.targetID, "button"); - return true; - }) - })]; - - test.withTestDoc(function (window, doc) { - test.showMenu("#button", function (popup) { - test.checkMenu(items, [], []); - test.done(); - }); - }); -}; - -// Test that the data object has the correct ID -exports.testPredicateContextTargetIDNotSet = function (assert, done) { - let test = new TestHelper(assert, done); - let loader = test.newLoader(); - - let items = [loader.cm.Item({ - label: "item", - context: loader.cm.PredicateContext(function (data) { - assert.strictEqual(data.targetID, null); - return true; - }) - })]; - - test.withTestDoc(function (window, doc) { - test.showMenu(".predicate-test-a", function (popup) { - test.checkMenu(items, [], []); - test.done(); - }); - }); -}; - -// Test that the data object is showing editable correctly for regular text inputs -exports.testPredicateContextTextBoxIsEditable = function (assert, done) { - let test = new TestHelper(assert, done); - let loader = test.newLoader(); - - let items = [loader.cm.Item({ - label: "item", - context: loader.cm.PredicateContext(function (data) { - assert.strictEqual(data.isEditable, true); - return true; - }) - })]; - - test.withTestDoc(function (window, doc) { - test.showMenu("#textbox", function (popup) { - test.checkMenu(items, [], []); - test.done(); - }); - }); -}; - -// Test that the data object is showing editable correctly for readonly text inputs -exports.testPredicateContextReadonlyTextBoxIsNotEditable = function (assert, done) { - let test = new TestHelper(assert, done); - let loader = test.newLoader(); - - let items = [loader.cm.Item({ - label: "item", - context: loader.cm.PredicateContext(function (data) { - assert.strictEqual(data.isEditable, false); - return true; - }) - })]; - - test.withTestDoc(function (window, doc) { - test.showMenu("#readonly-textbox", function (popup) { - test.checkMenu(items, [], []); - test.done(); - }); - }); -}; - -// Test that the data object is showing editable correctly for disabled text inputs -exports.testPredicateContextDisabledTextBoxIsNotEditable = function (assert, done) { - let test = new TestHelper(assert, done); - let loader = test.newLoader(); - - let items = [loader.cm.Item({ - label: "item", - context: loader.cm.PredicateContext(function (data) { - assert.strictEqual(data.isEditable, false); - return true; - }) - })]; - - test.withTestDoc(function (window, doc) { - test.showMenu("#disabled-textbox", function (popup) { - test.checkMenu(items, [], []); - test.done(); - }); - }); -}; - -// Test that the data object is showing editable correctly for text areas -exports.testPredicateContextTextAreaIsEditable = function (assert, done) { - let test = new TestHelper(assert, done); - let loader = test.newLoader(); - - let items = [loader.cm.Item({ - label: "item", - context: loader.cm.PredicateContext(function (data) { - assert.strictEqual(data.isEditable, true); - return true; - }) - })]; - - test.withTestDoc(function (window, doc) { - test.showMenu("#textfield", function (popup) { - test.checkMenu(items, [], []); - test.done(); - }); - }); -}; - -// Test that non-text inputs are not considered editable -exports.testPredicateContextButtonIsNotEditable = function (assert, done) { - let test = new TestHelper(assert, done); - let loader = test.newLoader(); - - let items = [loader.cm.Item({ - label: "item", - context: loader.cm.PredicateContext(function (data) { - assert.strictEqual(data.isEditable, false); - return true; - }) - })]; - - test.withTestDoc(function (window, doc) { - test.showMenu("#button", function (popup) { - test.checkMenu(items, [], []); - test.done(); - }); - }); -}; - - -// Test that the data object is showing editable correctly -exports.testPredicateContextNonInputIsNotEditable = function (assert, done) { - let test = new TestHelper(assert, done); - let loader = test.newLoader(); - - let items = [loader.cm.Item({ - label: "item", - context: loader.cm.PredicateContext(function (data) { - assert.strictEqual(data.isEditable, false); - return true; - }) - })]; - - test.withTestDoc(function (window, doc) { - test.showMenu("#image", function (popup) { - test.checkMenu(items, [], []); - test.done(); - }); - }); -}; - - -// Test that the data object is showing editable correctly for HTML contenteditable elements -exports.testPredicateContextEditableElement = function (assert, done) { - let test = new TestHelper(assert, done); - let loader = test.newLoader(); - - let items = [loader.cm.Item({ - label: "item", - context: loader.cm.PredicateContext(function (data) { - assert.strictEqual(data.isEditable, true); - return true; - }) - })]; - - test.withTestDoc(function (window, doc) { - test.showMenu("#editable", function (popup) { - test.checkMenu(items, [], []); - test.done(); - }); - }); -}; - - -// Test that the data object does not have a selection when there is none -exports.testPredicateContextNoSelectionInPage = function (assert, done) { - let test = new TestHelper(assert, done); - let loader = test.newLoader(); - - let items = [loader.cm.Item({ - label: "item", - context: loader.cm.PredicateContext(function (data) { - assert.strictEqual(data.selectionText, null); - return true; - }) - })]; - - test.withTestDoc(function (window, doc) { - test.showMenu(null, function (popup) { - test.checkMenu(items, [], []); - test.done(); - }); - }); -}; - -// Test that the data object includes the selected page text -exports.testPredicateContextSelectionInPage = function (assert, done) { - let test = new TestHelper(assert, done); - let loader = test.newLoader(); - - let items = [loader.cm.Item({ - label: "item", - context: loader.cm.PredicateContext(function (data) { - // since we might get whitespace - assert.ok(data.selectionText && data.selectionText.search(/^\s*Some text.\s*$/) != -1, - 'Expected "Some text.", got "' + data.selectionText + '"'); - return true; - }) - })]; - - test.withTestDoc(function (window, doc) { - window.getSelection().selectAllChildren(doc.getElementById("text")); - test.showMenu(null, function (popup) { - test.checkMenu(items, [], []); - test.done(); - }); - }); -}; - -// Test that the data object includes the selected input text -exports.testPredicateContextSelectionInTextBox = function (assert, done) { - let test = new TestHelper(assert, done); - let loader = test.newLoader(); - - let items = [loader.cm.Item({ - label: "item", - context: loader.cm.PredicateContext(function (data) { - // since we might get whitespace - assert.strictEqual(data.selectionText, "t v"); - return true; - }) - })]; - - test.withTestDoc(function (window, doc) { - let textbox = doc.getElementById("textbox"); - test.selectRange("#textbox", 3, 6); - test.showMenu("#textbox", function (popup) { - test.checkMenu(items, [], []); - test.done(); - }); - }); -}; - -// Test that the data object has the correct src for an image -exports.testPredicateContextTargetSrcSet = function (assert, done) { - let test = new TestHelper(assert, done); - let loader = test.newLoader(); - let image; - - let items = [loader.cm.Item({ - label: "item", - context: loader.cm.PredicateContext(function (data) { - assert.strictEqual(data.srcURL, image.src); - return true; - }) - })]; - - test.withTestDoc(function (window, doc) { - image = doc.getElementById("image"); - test.showMenu("#image", function (popup) { - test.checkMenu(items, [], []); - test.done(); - }); - }); -}; - -// Test that the data object has no src for a link -exports.testPredicateContextTargetSrcNotSet = function (assert, done) { - let test = new TestHelper(assert, done); - let loader = test.newLoader(); - - let items = [loader.cm.Item({ - label: "item", - context: loader.cm.PredicateContext(function (data) { - assert.strictEqual(data.srcURL, null); - return true; - }) - })]; - - test.withTestDoc(function (window, doc) { - test.showMenu("#link", function (popup) { - test.checkMenu(items, [], []); - test.done(); - }); - }); -}; - - -// Test that the data object has the correct link set -exports.testPredicateContextTargetLinkSet = function (assert, done) { - let test = new TestHelper(assert, done); - let loader = test.newLoader(); - let image; - - let items = [loader.cm.Item({ - label: "item", - context: loader.cm.PredicateContext(function (data) { - assert.strictEqual(data.linkURL, TEST_DOC_URL + "#test"); - return true; - }) - })]; - - test.withTestDoc(function (window, doc) { - test.showMenu(".predicate-test-a", function (popup) { - test.checkMenu(items, [], []); - test.done(); - }); - }); -}; - -// Test that the data object has no link for an image -exports.testPredicateContextTargetLinkNotSet = function (assert, done) { - let test = new TestHelper(assert, done); - let loader = test.newLoader(); - - let items = [loader.cm.Item({ - label: "item", - context: loader.cm.PredicateContext(function (data) { - assert.strictEqual(data.linkURL, null); - return true; - }) - })]; - - test.withTestDoc(function (window, doc) { - test.showMenu("#image", function (popup) { - test.checkMenu(items, [], []); - test.done(); - }); - }); -}; - -// Test that the data object has the correct link for a nested image -exports.testPredicateContextTargetLinkSetNestedImage = function (assert, done) { - let test = new TestHelper(assert, done); - let loader = test.newLoader(); - - let items = [loader.cm.Item({ - label: "item", - context: loader.cm.PredicateContext(function (data) { - assert.strictEqual(data.linkURL, TEST_DOC_URL + "#nested-image"); - return true; - }) - })]; - - test.withTestDoc(function (window, doc) { - test.showMenu("#predicate-test-nested-image", function (popup) { - test.checkMenu(items, [], []); - test.done(); - }); - }); -}; - -// Test that the data object has the correct link for a complex nested structure -exports.testPredicateContextTargetLinkSetNestedStructure = function (assert, done) { - let test = new TestHelper(assert, done); - let loader = test.newLoader(); - - let items = [loader.cm.Item({ - label: "item", - context: loader.cm.PredicateContext(function (data) { - assert.strictEqual(data.linkURL, TEST_DOC_URL + "#nested-structure"); - return true; - }) - })]; - - test.withTestDoc(function (window, doc) { - test.showMenu("#predicate-test-nested-structure", function (popup) { - test.checkMenu(items, [], []); - test.done(); - }); - }); -}; - -// Test that the data object has the value for an input textbox -exports.testPredicateContextTargetValueSet = function (assert, done) { - let test = new TestHelper(assert, done); - let loader = test.newLoader(); - let image; - - let items = [loader.cm.Item({ - label: "item", - context: loader.cm.PredicateContext(function (data) { - assert.strictEqual(data.value, "test value"); - return true; - }) - })]; - - test.withTestDoc(function (window, doc) { - test.showMenu("#textbox", function (popup) { - test.checkMenu(items, [], []); - test.done(); - }); - }); -}; - -// Test that the data object has no value for an image -exports.testPredicateContextTargetValueNotSet = function (assert, done) { - let test = new TestHelper(assert, done); - let loader = test.newLoader(); - - let items = [loader.cm.Item({ - label: "item", - context: loader.cm.PredicateContext(function (data) { - assert.strictEqual(data.value, null); - return true; - }) - })]; - - test.withTestDoc(function (window, doc) { - test.showMenu("#image", function (popup) { - test.checkMenu(items, [], []); - test.done(); - }); - }); -}; - -if (isTravisCI) { - module.exports = { - "test skip on jpm": (assert) => assert.pass("skipping this file with jpm") - }; -} - -require('sdk/test').run(exports); |