summaryrefslogtreecommitdiffstats
path: root/toolkit/modules/tests/browser/head.js
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--toolkit/modules/tests/browser/head.js251
1 files changed, 251 insertions, 0 deletions
diff --git a/toolkit/modules/tests/browser/head.js b/toolkit/modules/tests/browser/head.js
new file mode 100644
index 0000000000..8e9f06477e
--- /dev/null
+++ b/toolkit/modules/tests/browser/head.js
@@ -0,0 +1,251 @@
+"use strict";
+
+ChromeUtils.defineESModuleGetters(this, {
+ setTimeout: "resource://gre/modules/Timer.sys.mjs",
+});
+
+const kFixtureBaseURL =
+ "https://example.com/browser/toolkit/modules/tests/browser/";
+
+function removeDupes(list) {
+ let j = 0;
+ for (let i = 1; i < list.length; i++) {
+ if (list[i] != list[j]) {
+ j++;
+ if (i != j) {
+ list[j] = list[i];
+ }
+ }
+ }
+ list.length = j + 1;
+}
+
+function compareLists(list1, list2, kind) {
+ list1.sort();
+ removeDupes(list1);
+ list2.sort();
+ removeDupes(list2);
+ is(String(list1), String(list2), `${kind} URLs correct`);
+}
+
+async function promiseOpenFindbar(findbar) {
+ await gBrowser.getFindBar();
+ findbar.onFindCommand();
+ return gFindBar._startFindDeferred && gFindBar._startFindDeferred.promise;
+}
+
+function promiseFindResult(findbar, str = null) {
+ let highlightFinished = false;
+ let findFinished = false;
+ return new Promise(resolve => {
+ let listener = {
+ onFindResult({ searchString }) {
+ if (str !== null && str != searchString) {
+ return;
+ }
+ findFinished = true;
+ if (highlightFinished) {
+ findbar.browser.finder.removeResultListener(listener);
+ resolve();
+ }
+ },
+ onHighlightFinished() {
+ highlightFinished = true;
+ if (findFinished) {
+ findbar.browser.finder.removeResultListener(listener);
+ resolve();
+ }
+ },
+ onMatchesCountResult: () => {},
+ };
+ findbar.browser.finder.addResultListener(listener);
+ });
+}
+
+function promiseEnterStringIntoFindField(findbar, str) {
+ let promise = promiseFindResult(findbar, str);
+ for (let i = 0; i < str.length; i++) {
+ let event = new KeyboardEvent("keypress", {
+ bubbles: true,
+ cancelable: true,
+ view: null,
+ keyCode: 0,
+ charCode: str.charCodeAt(i),
+ });
+ findbar._findField.dispatchEvent(event);
+ }
+ return promise;
+}
+
+function promiseTestHighlighterOutput(
+ browser,
+ word,
+ expectedResult,
+ extraTest = () => {}
+) {
+ return SpecialPowers.spawn(
+ browser,
+ [{ word, expectedResult, extraTest: extraTest.toSource() }],
+ async function({ word, expectedResult, extraTest }) {
+ return new Promise((resolve, reject) => {
+ let stubbed = {};
+ let callCounts = {
+ insertCalls: [],
+ removeCalls: [],
+ animationCalls: [],
+ };
+ let lastMaskNode, lastOutlineNode;
+ let rects = [];
+
+ // Amount of milliseconds to wait after the last time one of our stubs
+ // was called.
+ const kTimeoutMs = 1000;
+ // The initial timeout may wait for a while for results to come in.
+ let timeout = content.setTimeout(
+ () => finish(false, "Timeout"),
+ kTimeoutMs * 5
+ );
+
+ function finish(ok = true, message = "finished with error") {
+ // Restore the functions we stubbed out.
+ try {
+ content.document.insertAnonymousContent = stubbed.insert;
+ content.document.removeAnonymousContent = stubbed.remove;
+ } catch (ex) {}
+ stubbed = {};
+ content.clearTimeout(timeout);
+
+ if (expectedResult.rectCount !== 0) {
+ Assert.ok(ok, message);
+ }
+
+ Assert.greaterOrEqual(
+ callCounts.insertCalls.length,
+ expectedResult.insertCalls[0],
+ `Min. insert calls should match for '${word}'.`
+ );
+ Assert.lessOrEqual(
+ callCounts.insertCalls.length,
+ expectedResult.insertCalls[1],
+ `Max. insert calls should match for '${word}'.`
+ );
+ Assert.greaterOrEqual(
+ callCounts.removeCalls.length,
+ expectedResult.removeCalls[0],
+ `Min. remove calls should match for '${word}'.`
+ );
+ Assert.lessOrEqual(
+ callCounts.removeCalls.length,
+ expectedResult.removeCalls[1],
+ `Max. remove calls should match for '${word}'.`
+ );
+
+ // We reached the amount of calls we expected, so now we can check
+ // the amount of rects.
+ if (!lastMaskNode && expectedResult.rectCount !== 0) {
+ Assert.ok(
+ false,
+ `No mask node found, but expected ${expectedResult.rectCount} rects.`
+ );
+ }
+
+ Assert.equal(
+ rects.length,
+ expectedResult.rectCount,
+ `Amount of inserted rects should match for '${word}'.`
+ );
+
+ if ("animationCalls" in expectedResult) {
+ Assert.greaterOrEqual(
+ callCounts.animationCalls.length,
+ expectedResult.animationCalls[0],
+ `Min. animation calls should match for '${word}'.`
+ );
+ Assert.lessOrEqual(
+ callCounts.animationCalls.length,
+ expectedResult.animationCalls[1],
+ `Max. animation calls should match for '${word}'.`
+ );
+ }
+
+ // Allow more specific assertions to be tested in `extraTest`.
+ // eslint-disable-next-line no-eval
+ extraTest = eval(extraTest);
+ extraTest(lastMaskNode, lastOutlineNode, rects);
+
+ resolve();
+ }
+
+ function stubAnonymousContentNode(domNode, anonNode) {
+ let originals = [
+ anonNode.setTextContentForElement,
+ anonNode.setAttributeForElement,
+ anonNode.removeAttributeForElement,
+ anonNode.setCutoutRectsForElement,
+ anonNode.setAnimationForElement,
+ ];
+ anonNode.setTextContentForElement = (id, text) => {
+ try {
+ (domNode.querySelector("#" + id) || domNode).textContent = text;
+ } catch (ex) {}
+ return originals[0].call(anonNode, id, text);
+ };
+ anonNode.setAttributeForElement = (id, attrName, attrValue) => {
+ try {
+ (domNode.querySelector("#" + id) || domNode).setAttribute(
+ attrName,
+ attrValue
+ );
+ } catch (ex) {}
+ return originals[1].call(anonNode, id, attrName, attrValue);
+ };
+ anonNode.removeAttributeForElement = (id, attrName) => {
+ try {
+ let node = domNode.querySelector("#" + id) || domNode;
+ if (node.hasAttribute(attrName)) {
+ node.removeAttribute(attrName);
+ }
+ } catch (ex) {}
+ return originals[2].call(anonNode, id, attrName);
+ };
+ anonNode.setCutoutRectsForElement = (id, cutoutRects) => {
+ rects = cutoutRects;
+ return originals[3].call(anonNode, id, cutoutRects);
+ };
+ anonNode.setAnimationForElement = (id, keyframes, options) => {
+ callCounts.animationCalls.push([keyframes, options]);
+ return originals[4].call(anonNode, id, keyframes, options);
+ };
+ }
+
+ // Create a function that will stub the original version and collects
+ // the arguments so we can check the results later.
+ function stub(which) {
+ stubbed[which] = content.document[which + "AnonymousContent"];
+ let prop = which + "Calls";
+ return function(node) {
+ callCounts[prop].push(node);
+ if (which == "insert") {
+ if (node.outerHTML.indexOf("outlineMask") > -1) {
+ lastMaskNode = node;
+ } else {
+ lastOutlineNode = node;
+ }
+ }
+ content.clearTimeout(timeout);
+ timeout = content.setTimeout(() => {
+ finish();
+ }, kTimeoutMs);
+ let res = stubbed[which].call(content.document, node);
+ if (which == "insert") {
+ stubAnonymousContentNode(node, res);
+ }
+ return res;
+ };
+ }
+ content.document.insertAnonymousContent = stub("insert");
+ content.document.removeAnonymousContent = stub("remove");
+ });
+ }
+ );
+}