Source code

Revision control

Copy as Markdown

Other Tools

Test Info: Warnings

  • This test gets skipped with pattern: os == 'linux' && os_version == '18.04' && asan OR os == 'linux' && os_version == '18.04' && tsan OR os == 'linux' && os_version == '18.04' && verify OR apple_catalina && verify OR apple_silicon && verify
  • Manifest: browser/components/extensions/test/browser/browser.toml
/* global browser */
"use strict";
function frameScript() {
let docShell = content.docShell;
let controller = docShell
.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsISelectionDisplay)
.QueryInterface(Ci.nsISelectionController);
let selection = controller.getSelection(controller.SELECTION_FIND);
if (!selection.rangeCount) {
return {
text: "",
};
}
let range = selection.getRangeAt(0);
const { FindContent } = ChromeUtils.importESModule(
);
let highlighter = new FindContent(docShell).highlighter;
let r1 = content.parent.frameElement.getBoundingClientRect();
let f1 = highlighter._getFrameElementOffsets(content.parent);
let r2 = content.frameElement.getBoundingClientRect();
let f2 = highlighter._getFrameElementOffsets(content);
let r3 = range.getBoundingClientRect();
let rect = {
top: r1.top + r2.top + r3.top + f1.y + f2.y,
left: r1.left + r2.left + r3.left + f1.x + f2.x,
};
return {
text: selection.toString(),
rect,
};
}
add_task(async function testFind() {
async function background() {
function awaitLoad(tabId, url) {
return new Promise(resolve => {
browser.tabs.onUpdated.addListener(function listener(
tabId_,
changed,
tab
) {
if (
tabId == tabId_ &&
changed.status == "complete" &&
tab.url == url
) {
browser.tabs.onUpdated.removeListener(listener);
resolve();
}
});
});
}
let url =
let tab = await browser.tabs.update({ url });
await awaitLoad(tab.id, url);
let data = await browser.find.find("banana", { includeRangeData: true });
let rangeData = data.rangeData;
browser.test.log("Test that `data.count` is the expected value.");
browser.test.assertEq(
6,
data.count,
"The value returned from `data.count`"
);
browser.test.log("Test that `rangeData` has the proper number of values.");
browser.test.assertEq(
6,
rangeData.length,
"The number of values held in `rangeData`"
);
browser.test.log(
"Test that the text found in the top window and nested frames corresponds to the proper position."
);
let terms = ["Bánana", "bAnana", "baNana", "banAna", "banaNa", "bananA"];
for (let i = 0; i < terms.length; i++) {
browser.test.assertEq(
terms[i],
rangeData[i].text,
`The text at range position ${i}:`
);
}
browser.test.log("Test that case sensitive match works properly.");
data = await browser.find.find("baNana", {
caseSensitive: true,
includeRangeData: true,
});
browser.test.assertEq(1, data.count, "The number of matches found:");
browser.test.assertEq("baNana", data.rangeData[0].text, "The text found:");
browser.test.log("Test that diacritic sensitive match works properly.");
data = await browser.find.find("bánana", {
matchDiacritics: true,
includeRangeData: true,
});
browser.test.assertEq(1, data.count, "The number of matches found:");
browser.test.assertEq("Bánana", data.rangeData[0].text, "The text found:");
browser.test.log("Test that case insensitive match works properly.");
data = await browser.find.find("banana", { caseSensitive: false });
browser.test.assertEq(6, data.count, "The number of matches found:");
browser.test.log("Test that entire word match works properly.");
data = await browser.find.find("banana", { entireWord: true });
browser.test.assertEq(
4,
data.count,
'The number of matches found, should skip 2 matches, "banaNaland" and "bananAland":'
);
let expectedRangeData = [
{
framePos: 0,
text: "example",
startTextNodePos: 16,
startOffset: 11,
endTextNodePos: 16,
endOffset: 18,
},
{
framePos: 0,
text: "example",
startTextNodePos: 16,
startOffset: 25,
endTextNodePos: 16,
endOffset: 32,
},
{
framePos: 0,
text: "example",
startTextNodePos: 19,
startOffset: 6,
endTextNodePos: 19,
endOffset: 13,
},
{
framePos: 0,
text: "example",
startTextNodePos: 21,
startOffset: 3,
endTextNodePos: 21,
endOffset: 10,
},
{
framePos: 1,
text: "example",
startTextNodePos: 0,
startOffset: 0,
endTextNodePos: 0,
endOffset: 7,
},
{
framePos: 2,
text: "example",
startTextNodePos: 0,
startOffset: 0,
endTextNodePos: 0,
endOffset: 7,
},
];
browser.test.log(
"Test that word found in the same node, different nodes and different frames returns the correct rangeData results."
);
data = await browser.find.find("example", { includeRangeData: true });
for (let i = 0; i < data.rangeData.length; i++) {
for (let name in data.rangeData[i]) {
browser.test.assertEq(
expectedRangeData[i][name],
data.rangeData[i][name],
`rangeData[${i}].${name}:`
);
}
}
browser.test.log(
"Test that `rangeData` is not returned if `includeRangeData` is false."
);
data = await browser.find.find("banana", {
caseSensitive: false,
includeRangeData: false,
});
browser.test.assertEq(
false,
!!data.rangeData,
"The boolean cast value of `rangeData`:"
);
browser.test.log(
"Test that `rectData` is not returned if `includeRectData` is false."
);
data = await browser.find.find("banana", {
caseSensitive: false,
includeRectData: false,
});
browser.test.assertEq(
false,
!!data.rectData,
"The boolean cast value of `rectData`:"
);
browser.test.log(
"Test that text spanning multiple inline elements is found."
);
data = await browser.find.find("fruitcake");
browser.test.assertEq(1, data.count, "The number of matches found:");
browser.test.log(
"Test that text spanning multiple block elements is not found."
);
data = await browser.find.find("angelfood");
browser.test.assertEq(0, data.count, "The number of matches found:");
browser.test.log(
"Test that `highlightResults` returns proper status code."
);
await browser.find.find("banana");
await browser.test.assertRejects(
browser.find.highlightResults({ rangeIndex: 6 }),
/index supplied was out of range/,
"rejected Promise should pass the expected error"
);
data = await browser.find.find("xyz");
await browser.test.assertRejects(
browser.find.highlightResults({ rangeIndex: 0 }),
/no search results to highlight/,
"rejected Promise should pass the expected error"
);
// Test highlightResults without any arguments, especially `rangeIndex`.
data = await browser.find.find("example");
browser.test.assertEq(6, data.count, "The number of matches found:");
await browser.find.highlightResults();
await browser.find.removeHighlighting();
data = await browser.find.find("banana", { includeRectData: true });
await browser.find.highlightResults({ rangeIndex: 5 });
browser.test.sendMessage("test:find:WebExtensionFinished", data.rectData);
}
let extension = ExtensionTestUtils.loadExtension({
manifest: {
permissions: ["find", "tabs"],
},
background,
});
await extension.startup();
let rectData = await extension.awaitMessage("test:find:WebExtensionFinished");
let { top, left } = rectData[5].rectsAndTexts.rectList[0];
await extension.unload();
let subFrameBrowsingContext =
gBrowser.selectedBrowser.browsingContext.children[0].children[1];
let result = await SpecialPowers.spawn(
subFrameBrowsingContext,
[],
frameScript
);
info("Test that text was highlighted properly.");
is(
result.text,
"bananA",
`The text that was highlighted: - Expected: bananA, Actual: ${result.text}`
);
info(
"Test that rectangle data returned from the search matches the highlighted result."
);
is(
result.rect.top,
top,
`rect.top: - Expected: ${result.rect.top}, Actual: ${top}`
);
is(
result.rect.left,
left,
`rect.left: - Expected: ${result.rect.left}, Actual: ${left}`
);
});
add_task(async function testRemoveHighlighting() {
async function background() {
function awaitLoad(tabId, url) {
return new Promise(resolve => {
browser.tabs.onUpdated.addListener(function listener(
tabId_,
changed,
tab
) {
if (
tabId == tabId_ &&
changed.status == "complete" &&
tab.url == url
) {
browser.tabs.onUpdated.removeListener(listener);
resolve();
}
});
});
}
let url =
let tab = await browser.tabs.update({ url });
await awaitLoad(tab.id, url);
let data = await browser.find.find("banana", { includeRangeData: true });
browser.test.log("Test that `data.count` is the expected value.");
browser.test.assertEq(
6,
data.count,
"The value returned from `data.count`"
);
await browser.find.highlightResults({ rangeIndex: 5 });
browser.find.removeHighlighting();
browser.test.sendMessage("test:find:WebExtensionFinished");
}
let extension = ExtensionTestUtils.loadExtension({
manifest: {
permissions: ["find", "tabs"],
},
background,
});
await extension.startup();
await extension.awaitMessage("test:find:WebExtensionFinished");
await extension.unload();
let subFrameBrowsingContext =
gBrowser.selectedBrowser.browsingContext.children[0].children[1];
let result = await SpecialPowers.spawn(
subFrameBrowsingContext,
[],
frameScript
);
info("Test that highlight was cleared properly.");
is(
result.text,
"",
`The text that was highlighted: - Expected: '', Actual: ${result.text}`
);
});
add_task(async function testAboutFind() {
async function background() {
await browser.test.assertRejects(
browser.find.find("banana"),
/Unable to search:/,
"Should not be able to search about tabs"
);
browser.test.sendMessage("done");
}
let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, "about:home");
let extension = ExtensionTestUtils.loadExtension({
manifest: {
permissions: ["find", "tabs"],
},
background,
});
await extension.startup();
await extension.awaitMessage("done");
await extension.unload();
BrowserTestUtils.removeTab(tab);
});
add_task(async function testIncognitoFind() {
async function background() {
await browser.test.assertRejects(
browser.find.find("banana"),
/Unable to search:/,
"Should not be able to search private window"
);
await browser.test.assertRejects(
browser.find.highlightResults(),
/Unable to search:/,
"Should not be able to highlight in private window"
);
await browser.test.assertRejects(
browser.find.removeHighlighting(),
/Invalid tab ID:/,
"Should not be able to remove highlight in private window"
);
browser.test.sendMessage("done");
}
let privateWin = await BrowserTestUtils.openNewBrowserWindow({
private: true,
});
BrowserTestUtils.startLoadingURIString(
privateWin.gBrowser.selectedBrowser,
);
await BrowserTestUtils.browserLoaded(privateWin.gBrowser.selectedBrowser);
let extension = ExtensionTestUtils.loadExtension({
manifest: {
permissions: ["find", "tabs"],
},
background,
});
await extension.startup();
await extension.awaitMessage("done");
await extension.unload();
await BrowserTestUtils.closeWindow(privateWin);
});
add_task(async function testIncognitoFindAllowed() {
// We're only testing we can make the calls in a private window,
// testFind above tests full functionality.
async function background() {
await browser.find.find("banana");
await browser.find.highlightResults({ rangeIndex: 0 });
await browser.find.removeHighlighting();
browser.test.sendMessage("done");
}
let url =
let privateWin = await BrowserTestUtils.openNewBrowserWindow({
private: true,
});
BrowserTestUtils.startLoadingURIString(
privateWin.gBrowser.selectedBrowser,
url
);
await BrowserTestUtils.browserLoaded(privateWin.gBrowser.selectedBrowser);
let extension = ExtensionTestUtils.loadExtension({
manifest: {
permissions: ["find", "tabs"],
},
background,
incognitoOverride: "spanning",
});
await extension.startup();
await extension.awaitMessage("done");
await extension.unload();
await BrowserTestUtils.closeWindow(privateWin);
});