diff options
Diffstat (limited to 'toolkit/modules/tests/browser/head.js')
-rw-r--r-- | toolkit/modules/tests/browser/head.js | 251 |
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"); + }); + } + ); +} |