tenfourfox/addon-sdk/source/test/test-context-menu@2.js
Cameron Kaiser c9b2922b70 hello FPR
2017-04-19 00:56:45 -07:00

1351 lines
41 KiB
JavaScript

/* 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";
const { Cc, Ci } = require("chrome");
const {openWindow, closeWindow, openTab, closeTab,
openContextMenu, closeContextMenu, select,
readNode, captureContextMenu, withTab, withItems } = require("./context-menu/util");
const {when} = require("sdk/dom/events");
const {Item, Menu, Separator, Contexts, Readers } = require("sdk/context-menu@2");
const prefs = require("sdk/preferences/service");
const { before, after } = require('sdk/test/utils');
const testPageURI = require.resolve("./test-context-menu").replace(".js", ".html");
const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
const data = input =>
`data:text/html;charset=utf-8,${encodeURIComponent(input)}`
const menugroup = (...children) => Object.assign({
tagName: "menugroup",
namespaceURI: XUL_NS,
style: "-moz-box-orient: vertical;",
className: "sdk-context-menu-extension"
}, children.length ? {children} : {});
const menuseparator = () => ({
tagName: "menuseparator",
namespaceURI: XUL_NS,
className: "sdk-context-menu-separator"
})
const menuitem = properties => Object.assign({
tagName: "menuitem",
namespaceURI: XUL_NS,
className: "sdk-context-menu-item menuitem-iconic"
}, properties);
const menu = (properties, ...children) => Object.assign({
tagName: "menu",
namespaceURI: XUL_NS,
className: "sdk-context-menu menu-iconic"
}, properties, {
children: [Object.assign({tagName: "menupopup", namespaceURI: XUL_NS},
children.length ? {children} : {})]
});
// Destroying items that were previously created should cause them to be absent
// from the menu.
exports["test create / destroy menu item"] = withTab(function*(assert) {
const item = new Item({
label: "test-1"
});
const before = yield captureContextMenu("h1");
assert.deepEqual(before,
menugroup(menuseparator(),
menuitem({label: "test-1"})),
"context menu contains separator & added item");
item.destroy();
const after = yield captureContextMenu("h1");
assert.deepEqual(after, menugroup(),
"all items were removed children are present");
}, data`<h1>hello</h1>`);
/* Bug 1115419 - Disable occasionally failing test until we
figure out why it fails.
// Items created should be present on all browser windows.
exports["test menu item in new window"] = function*(assert) {
const isMenuPopulated = function*(tab) {
const state = yield captureContextMenu("h1", tab);
assert.deepEqual(state,
menugroup(menuseparator(),
menuitem({label: "multi-window"})),
"created menu item is present")
};
const isMenuEmpty = function*(tab) {
const state = yield captureContextMenu("h1", tab);
assert.deepEqual(state, menugroup(), "no sdk items present");
};
const item = new Item({ label: "multi-window" });
const tab1 = yield openTab(`data:text/html,<h1>hello</h1>`);
yield* isMenuPopulated(tab1);
const window2 = yield openWindow();
assert.pass("window is ready");
const tab2 = yield openTab(`data:text/html,<h1>hello window-2</h1>`, window2);
assert.pass("tab is ready");
yield* isMenuPopulated(tab2);
item.destroy();
yield* isMenuEmpty(tab2);
yield closeWindow(window2);
yield* isMenuEmpty(tab1);
yield closeTab(tab1);
};
*/
// Multilpe items can be created and destroyed at different points
// in time & they should not affect each other.
exports["test multiple items"] = withTab(function*(assert) {
const item1 = new Item({ label: "one" });
const step1 = yield captureContextMenu("h1");
assert.deepEqual(step1,
menugroup(menuseparator(),
menuitem({label: "one"})),
"item1 is present");
const item2 = new Item({ label: "two" });
const step2 = yield captureContextMenu("h1");
assert.deepEqual(step2,
menugroup(menuseparator(),
menuitem({label: "one"}),
menuitem({label: "two"})),
"both items where present");
item1.destroy();
const step3 = yield captureContextMenu("h1");
assert.deepEqual(step3,
menugroup(menuseparator(),
menuitem({label: "two"})),
"one items left");
item2.destroy();
const step4 = yield captureContextMenu("h1");
assert.deepEqual(step4, menugroup(), "no items left");
}, data`<h1>Multiple Items</h1>`);
// Destroying an item twice should not cause an error.
exports["test destroy twice"] = withTab(function*(assert) {
const item = new Item({ label: "destroy" });
const withItem = yield captureContextMenu("h2");
assert.deepEqual(withItem,
menugroup(menuseparator(),
menuitem({label:"destroy"})),
"Item is added");
item.destroy();
const withoutItem = yield captureContextMenu("h2");
assert.deepEqual(withoutItem, menugroup(), "Item was removed");
item.destroy();
assert.pass("Destroying an item twice should not cause an error.");
}, "data:text/html,<h2>item destroy</h2>");
// CSS selector contexts should cause their items to be absent from the menu
// when the menu is not invoked on nodes that match selectors.
exports["test selector context"] = withTab(function*(assert) {
const item = new Item({
context: [new Contexts.Selector("body b")],
label: "bold"
});
const match = yield captureContextMenu("b");
assert.deepEqual(match,
menugroup(menuseparator(),
menuitem({label: "bold"})),
"item mathched context");
const noMatch = yield captureContextMenu("i");
assert.deepEqual(noMatch, menugroup(), "item did not match context");
item.destroy();
const cleared = yield captureContextMenu("b");
assert.deepEqual(cleared, menugroup(), "item was removed");
}, data`<body><i>one</i><b>two</b></body>`);
// CSS selector contexts should cause their items to be absent in the menu
// when the menu is invoked even on nodes that have ancestors that match the
// selectors.
exports["test parent selector don't match children"] = withTab(function*(assert) {
const item = new Item({
label: "parent match",
context: [new Contexts.Selector("a[href]")]
});
const match = yield captureContextMenu("a");
assert.deepEqual(match,
menugroup(menuseparator(),
menuitem({label: "parent match"})),
"item mathched context");
const noMatch = yield captureContextMenu("strong");
assert.deepEqual(noMatch, menugroup(), "item did not mathch context");
item.destroy();
const destroyed = yield captureContextMenu("a");
assert.deepEqual(destroyed, menugroup(), "no items left");
}, data`<a href='/foo'>This text must be long & <strong>bold!</strong></a>`);
// Page contexts should cause their items to be present in the menu when the
// menu is not invoked on an active element.
exports["test page context match"] = withTab(function*(assert) {
const isPageMatch = (tree, description="page context matched") =>
assert.deepEqual(tree,
menugroup(menuseparator(),
menuitem({label: "page match"}),
menuitem({label: "any match"})),
description);
const isntPageMatch = (tree, description="page context did not match") =>
assert.deepEqual(tree,
menugroup(menuseparator(),
menuitem({label: "any match"})),
description);
yield* withItems({
pageMatch: new Item({
label: "page match",
context: [new Contexts.Page()],
}),
anyMatch: new Item({
label: "any match"
})
}, function*({pageMatch, anyMatch}) {
for (let tagName of [null, "p", "h3"]) {
isPageMatch((yield captureContextMenu(tagName)),
`Page context matches ${tagName} passive element`);
}
for (let tagName of ["button", "canvas", "img", "input", "textarea",
"select", "menu", "embed" ,"object", "video", "audio",
"applet"])
{
isntPageMatch((yield captureContextMenu(tagName)),
`Page context does not match <${tagName}/> active element`);
}
for (let selector of ["span"])
{
isntPageMatch((yield captureContextMenu(selector)),
`Page context does not match decedents of active element`);
}
});
},
data`<head>
<style>
p, object, embed { display: inline-block; }
</style>
</head>
<body>
<div><p>paragraph</p></div>
<div><a href=./link><span>link</span></a></div>
<h3>hi</h3>
<div><button>button</button></div>
<div><canvas height=10 /></div>
<div><img height=10 width=10 /></div>
<div><input value=input /></div>
<div><textarea>text</textarea></div>
<div><select><option>one</option><option>two</option></select></div>
<div><menu><button>item</button></menu></div>
<div><object width=10 height=10><param name=foo value=bar /></object></div>
<div><embed width=10 height=10/></div>
<div><video width=10 height=10 controls /></div>
<div><audio width=10 height=10 controls /></div>
<div><applet width=10 height=10 /></div>
</body>`);
// Page context does not match if if there is a selection.
exports["test page context doesn't match on selection"] = withTab(function*(assert) {
const isPageMatch = (tree, description="page context matched") =>
assert.deepEqual(tree,
menugroup(menuseparator(),
menuitem({label: "page match"}),
menuitem({label: "any match"})),
description);
const isntPageMatch = (tree, description="page context did not match") =>
assert.deepEqual(tree,
menugroup(menuseparator(),
menuitem({label: "any match"})),
description);
yield* withItems({
pageMatch: new Item({
label: "page match",
context: [new Contexts.Page()],
}),
anyMatch: new Item({
label: "any match"
})
}, function*({pageMatch, anyMatch}) {
yield select("b");
isntPageMatch((yield captureContextMenu("i")),
"page context does not match if there is a selection");
yield select(null);
isPageMatch((yield captureContextMenu("i")),
"page context match if there is no selection");
});
}, data`<body><i>one</i><b>two</b></body>`);
exports["test selection context"] = withTab(function*(assert) {
yield* withItems({
item: new Item({
label: "selection",
context: [new Contexts.Selection()]
})
}, function*({item}) {
assert.deepEqual((yield captureContextMenu()),
menugroup(),
"item does not match if there is no selection");
yield select("b");
assert.deepEqual((yield captureContextMenu()),
menugroup(menuseparator(),
menuitem({label: "selection"})),
"item matches if there is a selection");
});
}, data`<i>one</i><b>two</b>`);
exports["test selection context in textarea"] = withTab(function*(assert) {
yield* withItems({
item: new Item({
label: "selection",
context: [new Contexts.Selection()]
})
}, function*({item}) {
assert.deepEqual((yield captureContextMenu()),
menugroup(),
"does not match if there's no selection");
yield select({target:"textarea", start:0, end:5});
assert.deepEqual((yield captureContextMenu("b")),
menugroup(),
"does not match if target isn't input with selection");
assert.deepEqual((yield captureContextMenu("textarea")),
menugroup(menuseparator(),
menuitem({label: "selection"})),
"matches if target is input with selected text");
yield select({target: "textarea", start: 0, end: 0});
assert.deepEqual((yield captureContextMenu("textarea")),
menugroup(),
"does not match when selection is cleared");
});
}, data`<textarea>Hello World</textarea><b>!!</b>`);
exports["test url contexts"] = withTab(function*(assert) {
yield* withItems({
a: new Item({
label: "a",
context: [new Contexts.URL(testPageURI)]
}),
b: new Item({
label: "b",
context: [new Contexts.URL("*.bogus.com")]
}),
c: new Item({
label: "c",
context: [new Contexts.URL("*.bogus.com"),
new Contexts.URL(testPageURI)]
}),
d: new Item({
label: "d",
context: [new Contexts.URL(/.*\.html/)]
}),
e: new Item({
label: "e",
context: [new Contexts.URL("http://*"),
new Contexts.URL(testPageURI)]
}),
f: new Item({
label: "f",
context: [new Contexts.URL("http://*").required,
new Contexts.URL(testPageURI)]
}),
}, function*(_) {
assert.deepEqual((yield captureContextMenu()),
menugroup(menuseparator(),
menuitem({label: "a"}),
menuitem({label: "c"}),
menuitem({label: "d"}),
menuitem({label: "e"})),
"shows only matching items");
});
}, testPageURI);
exports["test iframe context"] = withTab(function*(assert) {
yield* withItems({
page: new Item({
label: "page",
context: [new Contexts.Page()]
}),
iframe: new Item({
label: "iframe",
context: [new Contexts.Frame()]
}),
h2: new Item({
label: "element",
context: [new Contexts.Selector("*")]
})
}, function(_) {
assert.deepEqual((yield captureContextMenu("iframe")),
menugroup(menuseparator(),
menuitem({label: "page"}),
menuitem({label: "iframe"}),
menuitem({label: "element"})),
"matching items are present");
assert.deepEqual((yield captureContextMenu("h1")),
menugroup(menuseparator(),
menuitem({label: "page"}),
menuitem({label: "element"})),
"only matching items are present");
});
},
data`<h1>hello</h1>
<iframe src='data:text/html,<body>Bye</body>' />`);
exports["test link context"] = withTab(function*(assert) {
yield* withItems({
item: new Item({
label: "link",
context: [new Contexts.Link()]
})
}, function*(_) {
assert.deepEqual((yield captureContextMenu("h1")),
menugroup(menuseparator(),
menuitem({label: "link"})),
"matches anchor child");
assert.deepEqual((yield captureContextMenu("i")),
menugroup(menuseparator(),
menuitem({label: "link"})),
"matches anchor decedent");
assert.deepEqual((yield captureContextMenu("h2")),
menugroup(),
"does not match if not under anchor");
});
}, data`<a href="/link"><h1>Hello <i>World</i></h1></a><h2>miss</h2>`);
exports["test editable context"] = withTab(function*(assert) {
const isntEditable = function*(selector) {
assert.deepEqual((yield captureContextMenu(selector)),
menugroup(),
`${selector} isn't editable`);
};
const isEditable = function*(selector) {
assert.deepEqual((yield captureContextMenu(selector)),
menugroup(menuseparator(),
menuitem({label: "editable"})),
`${selector} is editable`);
};
yield* withItems({
item: new Item({
label: "editable",
context: [new Contexts.Editable()]
})
}, function*(_) {
yield* isntEditable("h1");
yield* isEditable("input[id=text]");
yield* isntEditable("input[disabled=true]");
yield* isntEditable("input[readonly=true]");
yield* isntEditable("input[type=submit]");
yield* isntEditable("input[type=radio]");
yield* isntEditable("input[type=checkbox]");
yield* isEditable("input[type=foo]");
yield* isEditable("textarea");
yield* isEditable("[contenteditable=true]");
});
}, data`<body>
<h1>examles</h1>
<pre contenteditable="true">This content is editable.</pre>
<input type="text" readonly="true" value="readonly value">
<input type="text" disabled="true" value="disabled value">
<input type="text" id=text value="test value">
<input type="submit" />
<input type="radio" />
<input type="foo" />
<input type="checkbox" />
<textarea>A text field,
with some text.</textarea>
</body>`);
exports["test image context"] = withTab(function*(assert) {
yield withItems({
item: new Item({
label: "image",
context: [new Contexts.Image()]
})
}, function*(_) {
assert.deepEqual((yield captureContextMenu("img")),
menugroup(menuseparator(), menuitem({label: "image"})),
`<img/> matches image context`);
assert.deepEqual((yield captureContextMenu("p image")),
menugroup(),
`<image/> does not image context`);
assert.deepEqual((yield captureContextMenu("svg image")),
menugroup(menuseparator(), menuitem({label: "image"})),
`<svg:image/> matches image context`);
});
}, data`<body>
<p><image style="width: 50px; height: 50px" /></p>
<img src='' />
<div>
<svg xmlns="http://www.w3.org/2000/svg"
xmlns:xlink= "http://www.w3.org/1999/xlink">
<image x="0" y="0" height="50px" width="50px" xlink:href=""/>
</svg>
<div>
</body>`);
exports["test audiot & video contexts"] = withTab(function*(assert) {
yield withItems({
audio: new Item({
label: "audio",
context: [new Contexts.Audio()]
}),
video: new Item({
label: "video",
context: [new Contexts.Video()]
}),
media: new Item({
label: "media",
context: [new Contexts.Audio(),
new Contexts.Video()]
})
}, function*(_) {
assert.deepEqual((yield captureContextMenu("img")),
menugroup(),
`<img/> does not match video or audio context`);
assert.deepEqual((yield captureContextMenu("audio")),
menugroup(menuseparator(),
menuitem({label: "audio"}),
menuitem({label: "media"})),
`<audio/> matches audio context`);
assert.deepEqual((yield captureContextMenu("video")),
menugroup(menuseparator(),
menuitem({label: "video"}),
menuitem({label: "media"})),
`<video/> matches video context`);
})
}, data`<body>
<div><video width=10 height=10 controls /></div>
<div><audio width=10 height=10 controls /></div>
<div><image style="width: 50px; height: 50px" /></div>
</body>`);
const predicateTestURL = data`<html>
<head>
<style>
p, object, embed { display: inline-block; }
</style>
</head>
<body>
<strong><p>paragraph</p></strong>
<p><a href=./link><span>link</span></a></p>
<p><h3>hi</h3></p>
<p><button>button</button></p>
<p><canvas height=50 width=50 /></p>
<p><img height=50 width=50 src="./no.png" /></p>
<p><code contenteditable="true">This content is editable.</code></p>
<p><input type="text" readonly="true" value="readonly value"></p>
<p><input type="text" disabled="true" value="disabled value"></p>
<p><input type="text" id=text value="test value" /></p>
<p><input type="submit" /></p>
<p><input type="radio" /></p>
<p><input type="foo" /></p>
<p><input type="checkbox" /></p>
<p><textarea>A text field,
with some text.</textarea></p>
<p><iframe src='data:text/html,<body style="height:100%">Bye</body>'></iframe></p>
<p><select><option>one</option><option>two</option></select></p>
<p><menu><button>item</button></menu></p>
<p><object width=10 height=10><param name=foo value=bar /></object></p>
<p><embed width=10 height=10/></p>
<p><video width=50 height=50 controls /></p>
<p><audio width=10 height=10 controls /></p>
<p><applet width=30 height=30 /></p>
</body>
</html>`;
exports["test predicate context"] = withTab(function*(assert) {
const test = function*(selector, expect) {
var isMatch = false;
test.return = (target) => {
return isMatch = expect(target);
}
assert.deepEqual((yield captureContextMenu(selector)),
isMatch ? menugroup(menuseparator(),
menuitem({label:"predicate"})) :
menugroup(),
isMatch ? `predicate item matches ${selector}` :
`predicate item doesn't match ${selector}`);
};
test.predicate = target => test.return(target);
yield* withItems({
item: new Item({
label: "predicate",
read: {
mediaType: new Readers.MediaType(),
link: new Readers.LinkURL(),
isPage: new Readers.isPage(),
isFrame: new Readers.isFrame(),
isEditable: new Readers.isEditable(),
tagName: new Readers.Query("tagName"),
appCodeName: new Readers.Query("ownerDocument.defaultView.navigator.appCodeName"),
width: new Readers.Attribute("width"),
src: new Readers.SrcURL(),
url: new Readers.PageURL(),
selection: new Readers.Selection()
},
context: [Contexts.Predicate(test.predicate)]
})
}, function*(items) {
yield* test("strong p", target => {
assert.deepEqual(target, {
mediaType: null,
link: null,
isPage: true,
isFrame: false,
isEditable: false,
tagName: "P",
appCodeName: "Mozilla",
width: null,
src: null,
url: predicateTestURL,
selection: null,
}, "pagraph read test");
return true;
});
yield* test("a span", target => {
assert.deepEqual(target, {
mediaType: null,
link: "./link",
isPage: false,
isFrame: false,
isEditable: false,
tagName: "SPAN",
appCodeName: "Mozilla",
width: null,
src: null,
url: predicateTestURL,
selection: null,
}, "video tag test");
return false;
});
yield* test("h3", target => {
assert.deepEqual(target, {
mediaType: null,
link: null,
isPage: true,
isFrame: false,
isEditable: false,
tagName: "H3",
appCodeName: "Mozilla",
width: null,
src: null,
url: predicateTestURL,
selection: null,
}, "video tag test");
return false;
});
yield select("h3");
yield* test("a span", target => {
assert.deepEqual(target, {
mediaType: null,
link: "./link",
isPage: false,
isFrame: false,
isEditable: false,
tagName: "SPAN",
appCodeName: "Mozilla",
width: null,
src: null,
url: predicateTestURL,
selection: "hi",
}, "test selection with link");
return true;
});
yield select(null);
yield* test("button", target => {
assert.deepEqual(target, {
mediaType: null,
link: null,
isPage: false,
isFrame: false,
isEditable: false,
tagName: "BUTTON",
appCodeName: "Mozilla",
width: null,
src: null,
url: predicateTestURL,
selection: null,
}, "test button");
return true;
});
yield* test("canvas", target => {
assert.deepEqual(target, {
mediaType: null,
link: null,
isPage: false,
isFrame: false,
isEditable: false,
tagName: "CANVAS",
appCodeName: "Mozilla",
width: "50",
src: null,
url: predicateTestURL,
selection: null,
}, "test button");
return true;
});
yield* test("img", target => {
assert.deepEqual(target, {
mediaType: "image",
link: null,
isPage: false,
isFrame: false,
isEditable: false,
tagName: "IMG",
appCodeName: "Mozilla",
width: "50",
src: "./no.png",
url: predicateTestURL,
selection: null,
}, "test image");
return true;
});
yield* test("code", target => {
assert.deepEqual(target, {
mediaType: null,
link: null,
isPage: false,
isFrame: false,
isEditable: true,
tagName: "CODE",
appCodeName: "Mozilla",
width: null,
src: null,
url: predicateTestURL,
selection: null,
}, "test content editable");
return false;
});
yield* test("input[readonly=true]", target => {
assert.deepEqual(target, {
mediaType: null,
link: null,
isPage: false,
isFrame: false,
isEditable: false,
tagName: "INPUT",
appCodeName: "Mozilla",
width: null,
src: null,
url: predicateTestURL,
selection: null,
}, "test readonly input");
return false;
});
yield* test("input[disabled=true]", target => {
assert.deepEqual(target, {
mediaType: null,
link: null,
isPage: false,
isFrame: false,
isEditable: false,
tagName: "INPUT",
appCodeName: "Mozilla",
width: null,
src: null,
url: predicateTestURL,
selection: null,
}, "test disabled input");
return false;
});
yield select({target: "input#text", start: 0, end: 5 });
yield* test("input#text", target => {
assert.deepEqual(target, {
mediaType: null,
link: null,
isPage: false,
isFrame: false,
isEditable: true,
tagName: "INPUT",
appCodeName: "Mozilla",
width: null,
src: null,
url: predicateTestURL,
selection: "test ",
}, "test editable input");
return false;
});
yield select({target: "input#text", start:0, end: 0});
yield* test("input[type=submit]", target => {
assert.deepEqual(target, {
mediaType: null,
link: null,
isPage: false,
isFrame: false,
isEditable: false,
tagName: "INPUT",
appCodeName: "Mozilla",
width: null,
src: null,
url: predicateTestURL,
selection: null,
}, "test submit input");
return false;
});
yield* test("input[type=radio]", target => {
assert.deepEqual(target, {
mediaType: null,
link: null,
isPage: false,
isFrame: false,
isEditable: false,
tagName: "INPUT",
appCodeName: "Mozilla",
width: null,
src: null,
url: predicateTestURL,
selection: null,
}, "test radio input");
return false;
});
yield* test("input[type=checkbox]", target => {
assert.deepEqual(target, {
mediaType: null,
link: null,
isPage: false,
isFrame: false,
isEditable: false,
tagName: "INPUT",
appCodeName: "Mozilla",
width: null,
src: null,
url: predicateTestURL,
selection: null,
}, "test checkbox input");
return false;
});
yield* test("input[type=foo]", target => {
assert.deepEqual(target, {
mediaType: null,
link: null,
isPage: false,
isFrame: false,
isEditable: true,
tagName: "INPUT",
appCodeName: "Mozilla",
width: null,
src: null,
url: predicateTestURL,
selection: null,
}, "test unrecognized input");
return false;
});
yield* test("textarea", target => {
assert.deepEqual(target, {
mediaType: null,
link: null,
isPage: false,
isFrame: false,
isEditable: true,
tagName: "TEXTAREA",
appCodeName: "Mozilla",
width: null,
src: null,
url: predicateTestURL,
selection: null,
}, "test textarea");
return false;
});
yield* test("iframe", target => {
assert.deepEqual(target, {
mediaType: null,
link: null,
isPage: true,
isFrame: true,
isEditable: false,
tagName: "BODY",
appCodeName: "Mozilla",
width: null,
src: null,
url: `data:text/html,<body%20style="height:100%">Bye</body>`,
selection: null,
}, "test iframe");
return true;
});
yield* test("select", target => {
assert.deepEqual(target, {
mediaType: null,
link: null,
isPage: false,
isFrame: false,
isEditable: false,
tagName: "SELECT",
appCodeName: "Mozilla",
width: null,
src: null,
url: predicateTestURL,
selection: null,
}, "test select");
return true;
});
yield* test("menu", target => {
assert.deepEqual(target, {
mediaType: null,
link: null,
isPage: false,
isFrame: false,
isEditable: false,
tagName: "MENU",
appCodeName: "Mozilla",
width: null,
src: null,
url: predicateTestURL,
selection: null,
}, "test menu");
return false;
});
yield* test("video", target => {
assert.deepEqual(target, {
mediaType: "video",
link: null,
isPage: false,
isFrame: false,
isEditable: false,
tagName: "VIDEO",
appCodeName: "Mozilla",
width: "50",
src: null,
url: predicateTestURL,
selection: null,
}, "test video");
return true;
});
yield* test("audio", target => {
assert.deepEqual(target, {
mediaType: "audio",
link: null,
isPage: false,
isFrame: false,
isEditable: false,
tagName: "AUDIO",
appCodeName: "Mozilla",
width: "10",
src: null,
url: predicateTestURL,
selection: null,
}, "test audio");
return true;
});
yield* test("object", target => {
assert.deepEqual(target, {
mediaType: null,
link: null,
isPage: false,
isFrame: false,
isEditable: false,
tagName: "OBJECT",
appCodeName: "Mozilla",
width: "10",
src: null,
url: predicateTestURL,
selection: null,
}, "test object");
return true;
});
yield* test("embed", target => {
assert.deepEqual(target, {
mediaType: null,
link: null,
isPage: false,
isFrame: false,
isEditable: false,
tagName: "EMBED",
appCodeName: "Mozilla",
width: "10",
src: null,
url: predicateTestURL,
selection: null,
}, "test embed");
return true;
});
yield* test("applet", target => {
assert.deepEqual(target, {
mediaType: null,
link: null,
isPage: false,
isFrame: false,
isEditable: false,
tagName: "APPLET",
appCodeName: "Mozilla",
width: "30",
src: null,
url: predicateTestURL,
selection: null,
}, "test applet");
return false;
});
});
}, predicateTestURL);
exports["test extractor reader"] = withTab(function*(assert) {
const test = function*(selector, expect) {
var isMatch = false;
test.return = (target) => {
return isMatch = expect(target);
}
assert.deepEqual((yield captureContextMenu(selector)),
isMatch ? menugroup(menuseparator(),
menuitem({label:"extractor"})) :
menugroup(),
isMatch ? `predicate item matches ${selector}` :
`predicate item doesn't match ${selector}`);
};
test.predicate = target => test.return(target);
yield* withItems({
item: new Item({
label: "extractor",
context: [Contexts.Predicate(test.predicate)],
read: {
tagName: Readers.Query("tagName"),
selector: Readers.Extractor(target => {
let node = target;
let path = [];
while (node) {
if (node.id) {
path.unshift(`#${node.id}`);
node = null;
}
else {
path.unshift(node.localName);
node = node.parentElement;
}
}
return path.join(" > ");
})
}
})
}, function*(_) {
yield* test("footer", target => {
assert.deepEqual(target, {
tagName: "FOOTER",
selector: "html > body > nav > footer"
}, "test footer");
return false;
});
});
}, data`<html>
<body>
<nav>
<header>begin</header>
<footer>end</footer>
</nav>
<article data-index=1>
<header>First title</header>
<div>
<p>First paragraph</p>
<p>Second paragraph</p>
</div>
</article>
<article data-index=2>
<header>Second title</header>
<div>
<p>First <strong id=foo>paragraph</strong></p>
<p>Second paragraph</p>
</div>
</article>
</body>
</html>`);
exports["test items overflow"] = withTab(function*(assert) {
yield* withItems({
i1: new Item({label: "item-1"}),
i2: new Item({label: "item-2"}),
i3: new Item({label: "item-3"}),
i4: new Item({label: "item-4"}),
i5: new Item({label: "item-5"}),
i6: new Item({label: "item-6"}),
i7: new Item({label: "item-7"}),
i8: new Item({label: "item-8"}),
i9: new Item({label: "item-9"}),
i10: new Item({label: "item-10"}),
}, function*(_) {
assert.deepEqual((yield captureContextMenu("p")),
menugroup(menu({
className: "sdk-context-menu-overflow-menu",
label: "Add-ons",
accesskey: "A",
}, menuitem({label: "item-1"}),
menuitem({label: "item-2"}),
menuitem({label: "item-3"}),
menuitem({label: "item-4"}),
menuitem({label: "item-5"}),
menuitem({label: "item-6"}),
menuitem({label: "item-7"}),
menuitem({label: "item-8"}),
menuitem({label: "item-9"}),
menuitem({label: "item-10"}))),
"context menu has an overflow");
});
prefs.set("extensions.addon-sdk.context-menu.overflowThreshold", 3);
yield* withItems({
i1: new Item({label: "item-1"}),
i2: new Item({label: "item-2"}),
}, function*(_) {
assert.deepEqual((yield captureContextMenu("p")),
menugroup(menuseparator(),
menuitem({label: "item-1"}),
menuitem({label: "item-2"})),
"two items do not overflow");
});
yield* withItems({
one: new Item({label: "one"}),
two: new Item({label: "two"}),
three: new Item({label: "three"})
}, function*(_) {
assert.deepEqual((yield captureContextMenu("p")),
menugroup(menu({className: "sdk-context-menu-overflow-menu",
label: "Add-ons",
accesskey: "A"},
menuitem({label: "one"}),
menuitem({label: "two"}),
menuitem({label: "three"}))),
"three items overflow");
});
prefs.reset("extensions.addon-sdk.context-menu.overflowThreshold");
yield* withItems({
one: new Item({label: "one"}),
two: new Item({label: "two"}),
three: new Item({label: "three"})
}, function*(_) {
assert.deepEqual((yield captureContextMenu("p")),
menugroup(menuseparator(),
menuitem({label: "one"}),
menuitem({label: "two"}),
menuitem({label: "three"})),
"three items no longer overflow");
});
}, data`<p>Hello</p>`);
exports["test context menus"] = withTab(function*(assert) {
const one = new Item({
label: "one",
context: [Contexts.Selector("p")],
read: {tagName: Readers.Query("tagName")}
});
assert.deepEqual((yield captureContextMenu("p")),
menugroup(menuseparator(),
menuitem({label: "one"})),
"item is present");
const two = new Item({
label: "two",
read: {tagName: Readers.Query("tagName")}
});
assert.deepEqual((yield captureContextMenu("p")),
menugroup(menuseparator(),
menuitem({label: "one"}),
menuitem({label: "two"})),
"both items are present");
const groupLevel1 = new Menu({label: "Level 1"},
[one]);
assert.deepEqual((yield captureContextMenu("p")),
menugroup(menuseparator(),
menuitem({label: "two"}),
menu({label: "Level 1"},
menuitem({label: "one"}))),
"first item moved to group");
assert.deepEqual((yield captureContextMenu("h1")),
menugroup(menuseparator(),
menuitem({label: "two"})),
"menu is hidden since only item does not match");
const groupLevel2 = new Menu({label: "Level 2" }, [groupLevel1]);
assert.deepEqual((yield captureContextMenu("p")),
menugroup(menuseparator(),
menuitem({label: "two"}),
menu({label: "Level 2"},
menu({label: "Level 1"},
menuitem({label: "one"})))),
"top level menu moved to submenu");
assert.deepEqual((yield captureContextMenu("h1")),
menugroup(menuseparator(),
menuitem({label: "two"})),
"menu is hidden since only item does not match");
const contextGroup = new Menu({
label: "H1 Group",
context: [Contexts.Selector("h1")]
}, [
two,
new Separator(),
new Item({ label: "three" })
]);
assert.deepEqual((yield captureContextMenu("p")),
menugroup(menuseparator(),
menu({label: "Level 2"},
menu({label: "Level 1"},
menuitem({label: "one"})))),
"nested menu is rendered");
assert.deepEqual((yield captureContextMenu("h1")),
menugroup(menuseparator(),
menu({label: "H1 Group"},
menuitem({label: "two"}),
menuseparator(),
menuitem({label: "three"}))),
"new contextual menu rendered");
yield* withItems({one, two,
groupLevel1, groupLevel2, contextGroup}, function*() {
});
assert.deepEqual((yield captureContextMenu("p")),
menugroup(),
"everyhing matching p was desposed");
assert.deepEqual((yield captureContextMenu("h1")),
menugroup(),
"everyhing matching h1 was desposed");
}, data`<body><h1>Title</h1><p>Content</p></body>`);
exports["test unloading"] = withTab(function*(assert) {
const { Loader } = require("sdk/test/loader");
const loader = Loader(module);
const {Item, Menu, Separator, Contexts, Readers } = loader.require("sdk/context-menu@2");
const item = new Item({label: "item"});
const group = new Menu({label: "menu"},
[new Separator(),
new Item({label: "sub-item"})]);
assert.deepEqual((yield captureContextMenu()),
menugroup(menuseparator(),
menuitem({label: "item"}),
menu({label: "menu"},
menuseparator(),
menuitem({label: "sub-item"}))),
"all items rendered");
loader.unload();
assert.deepEqual((yield captureContextMenu()),
menugroup(),
"all items disposed");
}, data`<body></body>`);
if (require("@loader/options").isNative) {
module.exports = {
"test skip on jpm": (assert) => assert.pass("skipping this file with jpm")
};
}
before(exports, (name, assert) => {
// Make sure Java doesn't activate
prefs.set("plugin.state.java", 0);
});
after(exports, (name, assert) => {
prefs.reset("plugin.state.java");
});
require("sdk/test").run(module.exports);