From 26a029d407be480d791972afb5975cf62c9360a6 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Fri, 19 Apr 2024 02:47:55 +0200 Subject: Adding upstream version 124.0.1. Signed-off-by: Daniel Baumann --- toolkit/components/pdfjs/test/head.js | 428 ++++++++++++++++++++++++++++++++++ 1 file changed, 428 insertions(+) create mode 100644 toolkit/components/pdfjs/test/head.js (limited to 'toolkit/components/pdfjs/test/head.js') diff --git a/toolkit/components/pdfjs/test/head.js b/toolkit/components/pdfjs/test/head.js new file mode 100644 index 0000000000..04c9543b5d --- /dev/null +++ b/toolkit/components/pdfjs/test/head.js @@ -0,0 +1,428 @@ +async function waitForPdfJS(browser, url) { + // Runs tests after all "load" event handlers have fired off + let loadPromise = BrowserTestUtils.waitForContentEvent( + browser, + "documentloaded", + false, + null, + true + ); + BrowserTestUtils.startLoadingURIString(browser, url); + return loadPromise; +} + +async function waitForPdfJSAnnotationLayer(browser, url) { + let loadPromise = BrowserTestUtils.waitForContentEvent( + browser, + "annotationlayerrendered", + false, + null, + true + ); + BrowserTestUtils.startLoadingURIString(browser, url); + return loadPromise; +} + +async function waitForPdfJSAllLayers(browser, url, layers) { + let loadPromise = BrowserTestUtils.waitForContentEvent( + browser, + "textlayerrendered", + false, + null, + true + ); + let annotationPromise = BrowserTestUtils.waitForContentEvent( + browser, + "annotationlayerrendered", + false, + null, + true + ); + let annotationEditorPromise = BrowserTestUtils.waitForContentEvent( + browser, + "annotationeditorlayerrendered", + false, + null, + true + ); + + BrowserTestUtils.startLoadingURIString(browser, url); + await Promise.all([loadPromise, annotationPromise, annotationEditorPromise]); + + await SpecialPowers.spawn(browser, [layers], async function (layers) { + const { ContentTaskUtils } = ChromeUtils.importESModule( + "resource://testing-common/ContentTaskUtils.sys.mjs" + ); + const { document } = content; + + for (let i = 0; i < layers.length; i++) { + await ContentTaskUtils.waitForCondition( + () => + layers[i].every( + name => + !!document.querySelector( + `.page[data-page-number='${i + 1}'] .${name}` + ) + ), + `All the layers must be displayed on page ${i}` + ); + } + }); + + await TestUtils.waitForTick(); +} + +async function waitForPdfJSCanvas(browser, url) { + let loadPromise = BrowserTestUtils.waitForContentEvent( + browser, + "pagerendered", + false, + null, + true + ); + BrowserTestUtils.startLoadingURIString(browser, url); + return loadPromise; +} + +async function waitForPdfJSSandbox(browser) { + let loadPromise = BrowserTestUtils.waitForContentEvent( + browser, + "sandboxcreated", + false, + null, + true + ); + return loadPromise; +} + +async function waitForSelector(browser, selector, message) { + return SpecialPowers.spawn( + browser, + [selector, message], + async function (sel, msg) { + const { ContentTaskUtils } = ChromeUtils.importESModule( + "resource://testing-common/ContentTaskUtils.sys.mjs" + ); + const { document } = content; + + await ContentTaskUtils.waitForCondition( + () => !!document.querySelector(sel), + `${sel} must be displayed` + ); + + await ContentTaskUtils.waitForCondition( + () => ContentTaskUtils.isVisible(document.querySelector(sel)), + msg + ); + } + ); +} + +async function click(browser, selector) { + await waitForSelector(browser, selector); + await SpecialPowers.spawn(browser, [selector], async function (sel) { + const el = content.document.querySelector(sel); + await new Promise(r => { + el.addEventListener("click", r, { once: true }); + el.click(); + }); + }); +} + +async function waitForTelemetry(browser) { + await BrowserTestUtils.waitForContentEvent( + browser, + "reporttelemetry", + false, + null, + true + ); + await TestUtils.waitForTick(); +} + +/** + * Enable an editor (Ink, FreeText, ...). + * @param {Object} browser + * @param {string} name + */ +async function enableEditor(browser, name) { + const editingModePromise = BrowserTestUtils.waitForContentEvent( + browser, + "annotationeditormodechanged", + false, + null, + true + ); + const editingStatePromise = BrowserTestUtils.waitForContentEvent( + browser, + "annotationeditorstateschanged", + false, + null, + true + ); + await clickOn(browser, `#editor${name}`); + await editingModePromise; + await editingStatePromise; + await TestUtils.waitForTick(); +} + +/** + * The text layer contains some spans with the text of the pdf. + * @param {Object} browser + * @param {string} text + * @returns {Object} the bbox of the span containing the text. + */ +async function getSpanBox(browser, text, pageNumber = 1) { + return SpecialPowers.spawn( + browser, + [text, pageNumber], + async function (text, number) { + const { ContentTaskUtils } = ChromeUtils.importESModule( + "resource://testing-common/ContentTaskUtils.sys.mjs" + ); + const { document } = content; + + await ContentTaskUtils.waitForCondition( + () => + !!document.querySelector( + `.page[data-page-number='${number}'] .textLayer .endOfContent` + ), + "The text layer must be displayed" + ); + + let targetSpan = null; + for (const span of document.querySelectorAll( + `.page[data-page-number='${number}'] .textLayer span` + )) { + if (span.innerText.includes(text)) { + targetSpan = span; + break; + } + } + + Assert.ok(!!targetSpan, `document must have a span containing '${text}'`); + + const { x, y, width, height } = targetSpan.getBoundingClientRect(); + return { x, y, width, height }; + } + ); +} + +/** + * Count the number of elements corresponding to the given selector. + * @param {Object} browser + * @param {string} selector + * @returns + */ +async function countElements(browser, selector) { + return SpecialPowers.spawn(browser, [selector], async function (selector) { + return new Promise(resolve => { + content.setTimeout(() => { + resolve(content.document.querySelectorAll(selector).length); + }, 0); + }); + }); +} + +/** + * Click at the given coordinates. + * @param {Object} browser + * @param {number} x + * @param {number} y + * @param {number} n + */ +async function clickAt(browser, x, y, n = 1) { + await BrowserTestUtils.synthesizeMouseAtPoint( + x, + y, + { + type: "mousedown", + button: 0, + clickCount: n, + }, + browser + ); + await BrowserTestUtils.synthesizeMouseAtPoint( + x, + y, + { + type: "mouseup", + button: 0, + clickCount: n, + }, + browser + ); + await TestUtils.waitForTick(); +} + +/** + * Click on the element corresponding to the given selector. + * @param {Object} browser + * @param {string} selector + */ +async function clickOn(browser, selector) { + await waitForSelector(browser, selector); + const [x, y] = await SpecialPowers.spawn( + browser, + [selector], + async selector => { + const element = content.document.querySelector(selector); + Assert.ok( + !!element, + `Element "${selector}" must be available in order to be clicked` + ); + const { x, y, width, height } = element.getBoundingClientRect(); + return [x + width / 2, y + height / 2]; + } + ); + await clickAt(browser, x, y); +} + +function focusEditorLayer(browser) { + return focus(browser, ".annotationEditorLayer"); +} + +/** + * Focus an element corresponding to the given selector. + * @param {Object} browser + * @param {string} selector + * @returns + */ +async function focus(browser, selector) { + return SpecialPowers.spawn(browser, [selector], function (sel) { + const el = content.document.querySelector(sel); + if (el === content.document.activeElement) { + return Promise.resolve(); + } + const promise = new Promise(resolve => { + const listener = () => { + el.removeEventListener("focus", listener); + resolve(); + }; + el.addEventListener("focus", listener); + }); + el.focus(); + return promise; + }); +} + +/** + * Hit a key. + */ +async function hitKey(browser, char) { + await SpecialPowers.spawn(browser, [char], async function (char) { + const { ContentTaskUtils } = ChromeUtils.importESModule( + "resource://testing-common/ContentTaskUtils.sys.mjs" + ); + const EventUtils = ContentTaskUtils.getEventUtils(content); + await EventUtils.synthesizeKey(char, {}, content); + }); + await TestUtils.waitForTick(); +} + +/** + * Write some text using the keyboard. + * @param {Object} browser + * @param {string} text + */ +async function write(browser, text) { + for (const char of text.split("")) { + hitKey(browser, char); + } +} + +/** + * Hit escape key. + */ +async function escape(browser) { + await hitKey(browser, "KEY_Escape"); +} + +/** + * Add a FreeText annotation and write some text inside. + * @param {Object} browser + * @param {string} text + * @param {Object} box + */ +async function addFreeText(browser, text, box) { + const { x, y, width, height } = box; + const count = await countElements(browser, ".freeTextEditor"); + await focusEditorLayer(browser); + await clickAt(browser, x + 0.1 * width, y + 0.5 * height); + await waitForEditors(browser, ".freeTextEditor", count + 1); + + await write(browser, text); + await escape(browser); +} + +async function waitForEditors(browser, selector, count) { + await BrowserTestUtils.waitForCondition( + async () => (await countElements(browser, selector)) === count + ); +} + +function changeMimeHandler(preferredAction, alwaysAskBeforeHandling) { + let handlerService = Cc[ + "@mozilla.org/uriloader/handler-service;1" + ].getService(Ci.nsIHandlerService); + let mimeService = Cc["@mozilla.org/mime;1"].getService(Ci.nsIMIMEService); + let handlerInfo = mimeService.getFromTypeAndExtension( + "application/pdf", + "pdf" + ); + var oldAction = [ + handlerInfo.preferredAction, + handlerInfo.alwaysAskBeforeHandling, + ]; + + // Change and save mime handler settings + handlerInfo.alwaysAskBeforeHandling = alwaysAskBeforeHandling; + handlerInfo.preferredAction = preferredAction; + handlerService.store(handlerInfo); + + // Refresh data + handlerInfo = mimeService.getFromTypeAndExtension("application/pdf", "pdf"); + + // Test: Mime handler was updated + is( + handlerInfo.alwaysAskBeforeHandling, + alwaysAskBeforeHandling, + "always-ask prompt change successful" + ); + is( + handlerInfo.preferredAction, + preferredAction, + "mime handler change successful" + ); + + return oldAction; +} + +function createTemporarySaveDirectory(id = "") { + var saveDir = Services.dirsvc.get("TmpD", Ci.nsIFile); + saveDir.append(`testsavedir${id}`); + if (!saveDir.exists()) { + saveDir.create(Ci.nsIFile.DIRECTORY_TYPE, 0o755); + } + return saveDir; +} + +async function cleanupDownloads(listId = Downloads.PUBLIC) { + info("cleaning up downloads"); + let downloadList = await Downloads.getList(listId); + for (let download of await downloadList.getAll()) { + await download.finalize(true); + try { + if (Services.appinfo.OS === "WINNT") { + // We need to make the file writable to delete it on Windows. + await IOUtils.setPermissions(download.target.path, 0o600); + } + await IOUtils.remove(download.target.path); + } catch (error) { + info("The file " + download.target.path + " is not removed, " + error); + } + + await downloadList.remove(download); + await download.finalize(); + } +} -- cgit v1.2.3