mirror of
https://github.com/classilla/tenfourfox.git
synced 2024-11-20 10:33:36 +00:00
1351 lines
41 KiB
JavaScript
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);
|