diff --git a/test/integration/freetext_editor_spec.js b/test/integration/freetext_editor_spec.js index db3688b73..0fea39fbd 100644 --- a/test/integration/freetext_editor_spec.js +++ b/test/integration/freetext_editor_spec.js @@ -18,8 +18,25 @@ const { getEditorSelector, getSelectedEditors, loadAndWait, + waitForEvent, } = require("./test_utils.js"); +const copyPaste = async page => { + let promise = waitForEvent(page, "copy"); + await page.keyboard.down("Control"); + await page.keyboard.press("c"); + await page.keyboard.up("Control"); + await promise; + + await page.waitForTimeout(10); + + promise = waitForEvent(page, "paste"); + await page.keyboard.down("Control"); + await page.keyboard.press("v"); + await page.keyboard.up("Control"); + await promise; +}; + describe("Editor", () => { describe("FreeText", () => { let pages; @@ -32,10 +49,22 @@ describe("Editor", () => { await closePages(pages); }); - const countStorageEntries = async page => - page.evaluate( - () => window.PDFViewerApplication.pdfDocument.annotationStorage.size + const waitForStorageEntries = async (page, nEntries) => { + await page.waitForFunction( + n => + window.PDFViewerApplication.pdfDocument.annotationStorage.size === n, + {}, + nEntries ); + }; + + const waitForSelected = async (page, selector) => { + await page.waitForFunction( + sel => document.querySelector(sel).classList.contains("selectedEditor"), + {}, + selector + ); + }; it("must write a string in a FreeText editor", async () => { await Promise.all( @@ -69,9 +98,8 @@ describe("Editor", () => { editorRect.y + 2 * editorRect.height ); - expect(await countStorageEntries(page)) - .withContext(`In ${browserName}`) - .toEqual(1); + await waitForSelected(page, getEditorSelector(0)); + await waitForStorageEntries(page, 1); const content = await page.$eval(getEditorSelector(0), el => el.innerText.trimEnd() @@ -82,63 +110,41 @@ describe("Editor", () => { }); it("must copy/paste", async () => { - await Promise.all( - pages.map(async ([browserName, page]) => { - const editorRect = await page.$eval(getEditorSelector(0), el => { - const { x, y, width, height } = el.getBoundingClientRect(); - return { x, y, width, height }; - }); + // Run sequentially to avoid clipboard issues. + for (const [browserName, page] of pages) { + const editorRect = await page.$eval(getEditorSelector(0), el => { + const { x, y, width, height } = el.getBoundingClientRect(); + return { x, y, width, height }; + }); - // Select the editor created previously. - await page.mouse.click( - editorRect.x + editorRect.width / 2, - editorRect.y + editorRect.height / 2 - ); + // Select the editor created previously. + await page.mouse.click( + editorRect.x + editorRect.width / 2, + editorRect.y + editorRect.height / 2 + ); - await page.keyboard.down("Control"); - await page.keyboard.press("c"); - await page.keyboard.up("Control"); + await waitForSelected(page, getEditorSelector(0)); + await copyPaste(page); + await waitForStorageEntries(page, 2); - await page.keyboard.down("Control"); - await page.keyboard.press("v"); - await page.keyboard.up("Control"); + const content = await page.$eval(getEditorSelector(0), el => + el.innerText.trimEnd() + ); - expect(await countStorageEntries(page)) - .withContext(`In ${browserName}`) - .toEqual(2); + let pastedContent = await page.$eval(getEditorSelector(1), el => + el.innerText.trimEnd() + ); - const content = await page.$eval(getEditorSelector(0), el => - el.innerText.trimEnd() - ); + expect(pastedContent).withContext(`In ${browserName}`).toEqual(content); - let pastedContent = await page.$eval(getEditorSelector(1), el => - el.innerText.trimEnd() - ); + await copyPaste(page); + await waitForStorageEntries(page, 3); - expect(pastedContent) - .withContext(`In ${browserName}`) - .toEqual(content); - - await page.keyboard.down("Control"); - await page.keyboard.press("c"); - await page.keyboard.up("Control"); - - await page.keyboard.down("Control"); - await page.keyboard.press("v"); - await page.keyboard.up("Control"); - - expect(await countStorageEntries(page)) - .withContext(`In ${browserName}`) - .toEqual(3); - - pastedContent = await page.$eval(getEditorSelector(2), el => - el.innerText.trimEnd() - ); - expect(pastedContent) - .withContext(`In ${browserName}`) - .toEqual(content); - }) - ); + pastedContent = await page.$eval(getEditorSelector(2), el => + el.innerText.trimEnd() + ); + expect(pastedContent).withContext(`In ${browserName}`).toEqual(content); + } }); it("must clear all", async () => { @@ -160,88 +166,85 @@ describe("Editor", () => { expect(hasEditor).withContext(`In ${browserName}`).toEqual(false); } - expect(await countStorageEntries(page)) - .withContext(`In ${browserName}`) - .toEqual(0); + await waitForStorageEntries(page, 0); }) ); }); it("must check that a paste has been undone", async () => { - await Promise.all( - pages.map(async ([browserName, page]) => { - const rect = await page.$eval(".annotationEditorLayer", el => { - const { x, y } = el.getBoundingClientRect(); - return { x, y }; - }); + // Run sequentially to avoid clipboard issues. + for (const [browserName, page] of pages) { + const rect = await page.$eval(".annotationEditorLayer", el => { + const { x, y } = el.getBoundingClientRect(); + return { x, y }; + }); - const data = "Hello PDF.js World !!"; - await page.mouse.click(rect.x + 100, rect.y + 100); - await page.type(`${getEditorSelector(3)} .internal`, data); + const data = "Hello PDF.js World !!"; + await page.mouse.click(rect.x + 100, rect.y + 100); + await page.type(`${getEditorSelector(3)} .internal`, data); - const editorRect = await page.$eval(getEditorSelector(3), el => { - const { x, y, width, height } = el.getBoundingClientRect(); - return { x, y, width, height }; - }); + const editorRect = await page.$eval(getEditorSelector(3), el => { + const { x, y, width, height } = el.getBoundingClientRect(); + return { x, y, width, height }; + }); - // Commit. - await page.mouse.click( - editorRect.x, - editorRect.y + 2 * editorRect.height - ); - // And select it again. - await page.mouse.click( - editorRect.x + editorRect.width / 2, - editorRect.y + editorRect.height / 2 - ); + // Commit. + await page.mouse.click( + editorRect.x, + editorRect.y + 2 * editorRect.height + ); + // And select it again. + await page.mouse.click( + editorRect.x + editorRect.width / 2, + editorRect.y + editorRect.height / 2 + ); - await page.keyboard.down("Control"); - await page.keyboard.press("c"); - await page.keyboard.up("Control"); + await waitForSelected(page, getEditorSelector(3)); + await copyPaste(page); + let hasEditor = await page.evaluate(sel => { + return !!document.querySelector(sel); + }, getEditorSelector(4)); + + expect(hasEditor).withContext(`In ${browserName}`).toEqual(true); + + await page.keyboard.down("Control"); + await page.keyboard.press("z"); + await page.keyboard.up("Control"); + await page.waitForTimeout(10); + + hasEditor = await page.evaluate(sel => { + return !!document.querySelector(sel); + }, getEditorSelector(4)); + + expect(hasEditor).withContext(`In ${browserName}`).toEqual(false); + + for (let i = 0; i < 2; i++) { + const promise = waitForEvent(page, "paste"); await page.keyboard.down("Control"); await page.keyboard.press("v"); await page.keyboard.up("Control"); + await promise; + await page.waitForTimeout(10); + } - let hasEditor = await page.evaluate(sel => { - return !!document.querySelector(sel); - }, getEditorSelector(4)); - - expect(hasEditor).withContext(`In ${browserName}`).toEqual(true); + let length = await page.evaluate(sel => { + return document.querySelectorAll(sel).length; + }, `${getEditorSelector(5)}, ${getEditorSelector(6)}`); + expect(length).withContext(`In ${browserName}`).toEqual(2); + for (let i = 0; i < 2; i++) { await page.keyboard.down("Control"); await page.keyboard.press("z"); await page.keyboard.up("Control"); + await page.waitForTimeout(10); + } - hasEditor = await page.evaluate(sel => { - return !!document.querySelector(sel); - }, getEditorSelector(4)); - - expect(hasEditor).withContext(`In ${browserName}`).toEqual(false); - - for (let i = 0; i < 2; i++) { - await page.keyboard.down("Control"); - await page.keyboard.press("v"); - await page.keyboard.up("Control"); - } - - let length = await page.evaluate(sel => { - return document.querySelectorAll(sel).length; - }, `${getEditorSelector(5)}, ${getEditorSelector(6)}`); - expect(length).withContext(`In ${browserName}`).toEqual(2); - - for (let i = 0; i < 2; i++) { - await page.keyboard.down("Control"); - await page.keyboard.press("z"); - await page.keyboard.up("Control"); - } - - length = await page.evaluate(sel => { - return document.querySelectorAll(sel).length; - }, `${getEditorSelector(5)}, ${getEditorSelector(6)}`); - expect(length).withContext(`In ${browserName}`).toEqual(0); - }) - ); + length = await page.evaluate(sel => { + return document.querySelectorAll(sel).length; + }, `${getEditorSelector(5)}, ${getEditorSelector(6)}`); + expect(length).withContext(`In ${browserName}`).toEqual(0); + } }); it("must check that aria-owns is correct", async () => { @@ -332,6 +335,8 @@ describe("Editor", () => { editorRect.y + editorRect.height / 2 ); + await waitForSelected(page, getEditorSelector(8)); + expect(await getSelectedEditors(page)) .withContext(`In ${browserName}`) .toEqual([8]); @@ -367,151 +372,144 @@ describe("Editor", () => { }); it("must select/unselect several editors and check copy, paste and delete operations", async () => { - await Promise.all( - pages.map(async ([browserName, page]) => { - await page.click("#editorFreeText"); + // Run sequentially to avoid clipboard issues. + for (const [browserName, page] of pages) { + await page.click("#editorFreeText"); - const rect = await page.$eval(".annotationEditorLayer", el => { - // With Chrome something is wrong when serializing a DomRect, - // hence we extract the values and just return them. - const { x, y } = el.getBoundingClientRect(); - return { x, y }; + const rect = await page.$eval(".annotationEditorLayer", el => { + // With Chrome something is wrong when serializing a DomRect, + // hence we extract the values and just return them. + const { x, y } = el.getBoundingClientRect(); + return { x, y }; + }); + + const editorCenters = []; + for (let i = 0; i < 4; i++) { + const data = `FreeText ${i}`; + await page.mouse.click( + rect.x + (i + 1) * 100, + rect.y + (i + 1) * 100 + ); + await page.type(`${getEditorSelector(i)} .internal`, data); + + const editorRect = await page.$eval(getEditorSelector(i), el => { + const { x, y, width, height } = el.getBoundingClientRect(); + return { + x, + y, + width, + height, + }; + }); + editorCenters.push({ + x: editorRect.x + editorRect.width / 2, + y: editorRect.y + editorRect.height / 2, }); - const editorCenters = []; - for (let i = 0; i < 4; i++) { - const data = `FreeText ${i}`; - await page.mouse.click( - rect.x + (i + 1) * 100, - rect.y + (i + 1) * 100 - ); - await page.type(`${getEditorSelector(i)} .internal`, data); + // Commit. + await page.mouse.click( + editorRect.x, + editorRect.y + 2 * editorRect.height + ); + } - const editorRect = await page.$eval(getEditorSelector(i), el => { - const { x, y, width, height } = el.getBoundingClientRect(); - return { - x, - y, - width, - height, - }; - }); - editorCenters.push({ - x: editorRect.x + editorRect.width / 2, - y: editorRect.y + editorRect.height / 2, - }); + await page.keyboard.down("Control"); + await page.keyboard.press("a"); + await page.keyboard.up("Control"); - // Commit. - await page.mouse.click( - editorRect.x, - editorRect.y + 2 * editorRect.height - ); - } + expect(await getSelectedEditors(page)) + .withContext(`In ${browserName}`) + .toEqual([0, 1, 2, 3]); - await page.keyboard.down("Control"); - await page.keyboard.press("a"); - await page.keyboard.up("Control"); + await page.keyboard.down("Control"); + await page.mouse.click(editorCenters[1].x, editorCenters[1].y); - expect(await getSelectedEditors(page)) - .withContext(`In ${browserName}`) - .toEqual([0, 1, 2, 3]); + expect(await getSelectedEditors(page)) + .withContext(`In ${browserName}`) + .toEqual([0, 2, 3]); - await page.keyboard.down("Control"); - await page.mouse.click(editorCenters[1].x, editorCenters[1].y); + await page.mouse.click(editorCenters[2].x, editorCenters[2].y); - expect(await getSelectedEditors(page)) - .withContext(`In ${browserName}`) - .toEqual([0, 2, 3]); + expect(await getSelectedEditors(page)) + .withContext(`In ${browserName}`) + .toEqual([0, 3]); - await page.mouse.click(editorCenters[2].x, editorCenters[2].y); + await page.mouse.click(editorCenters[1].x, editorCenters[1].y); + await page.keyboard.up("Control"); - expect(await getSelectedEditors(page)) - .withContext(`In ${browserName}`) - .toEqual([0, 3]); + expect(await getSelectedEditors(page)) + .withContext(`In ${browserName}`) + .toEqual([0, 1, 3]); - await page.mouse.click(editorCenters[1].x, editorCenters[1].y); - await page.keyboard.up("Control"); + await copyPaste(page); - expect(await getSelectedEditors(page)) - .withContext(`In ${browserName}`) - .toEqual([0, 1, 3]); + // 0,1,3 are unselected and new pasted editors are selected. + expect(await getSelectedEditors(page)) + .withContext(`In ${browserName}`) + .toEqual([4, 5, 6]); - await page.keyboard.down("Control"); - await page.keyboard.press("c"); - await page.keyboard.up("Control"); + // No ctrl here, hence all are unselected and 2 is selected. + await page.mouse.click(editorCenters[2].x, editorCenters[2].y); + expect(await getSelectedEditors(page)) + .withContext(`In ${browserName}`) + .toEqual([2]); - await page.keyboard.down("Control"); - await page.keyboard.press("v"); - await page.keyboard.up("Control"); + await page.mouse.click(editorCenters[1].x, editorCenters[1].y); + expect(await getSelectedEditors(page)) + .withContext(`In ${browserName}`) + .toEqual([1]); - // 0,1,3 are unselected and new pasted editors are selected. - expect(await getSelectedEditors(page)) - .withContext(`In ${browserName}`) - .toEqual([4, 5, 6]); + await page.keyboard.down("Control"); - // No ctrl here, hence all are unselected and 2 is selected. - await page.mouse.click(editorCenters[2].x, editorCenters[2].y); - expect(await getSelectedEditors(page)) - .withContext(`In ${browserName}`) - .toEqual([2]); + await page.mouse.click(editorCenters[3].x, editorCenters[3].y); + expect(await getSelectedEditors(page)) + .withContext(`In ${browserName}`) + .toEqual([1, 3]); - await page.mouse.click(editorCenters[1].x, editorCenters[1].y); - expect(await getSelectedEditors(page)) - .withContext(`In ${browserName}`) - .toEqual([1]); + await page.keyboard.up("Control"); - await page.keyboard.down("Control"); + // Delete 1 and 3. + await page.keyboard.press("Backspace"); - await page.mouse.click(editorCenters[3].x, editorCenters[3].y); - expect(await getSelectedEditors(page)) - .withContext(`In ${browserName}`) - .toEqual([1, 3]); + await page.keyboard.down("Control"); + await page.keyboard.press("a"); + await page.keyboard.up("Control"); - await page.keyboard.up("Control"); + expect(await getSelectedEditors(page)) + .withContext(`In ${browserName}`) + .toEqual([0, 2, 4, 5, 6]); - // Delete 1 and 3. - await page.keyboard.press("Backspace"); + // Create an empty editor. + await page.mouse.click(rect.x + 700, rect.y + 100); + expect(await getSelectedEditors(page)) + .withContext(`In ${browserName}`) + .toEqual([7]); - await page.keyboard.down("Control"); - await page.keyboard.press("a"); - await page.keyboard.up("Control"); + // Set the focus to 2 and check that only 2 is selected. + await page.mouse.click(editorCenters[2].x, editorCenters[2].y); + expect(await getSelectedEditors(page)) + .withContext(`In ${browserName}`) + .toEqual([2]); - expect(await getSelectedEditors(page)) - .withContext(`In ${browserName}`) - .toEqual([0, 2, 4, 5, 6]); + // Create an empty editor. + await page.mouse.click(rect.x + 700, rect.y + 100); + expect(await getSelectedEditors(page)) + .withContext(`In ${browserName}`) + .toEqual([8]); + // Dismiss it. + await page.keyboard.press("Escape"); - // Create an empty editor. - await page.mouse.click(rect.x + 700, rect.y + 100); - expect(await getSelectedEditors(page)) - .withContext(`In ${browserName}`) - .toEqual([7]); + // Select all. + await page.keyboard.down("Control"); + await page.keyboard.press("a"); + await page.keyboard.up("Control"); - // Set the focus to 2 and check that only 2 is selected. - await page.mouse.click(editorCenters[2].x, editorCenters[2].y); - expect(await getSelectedEditors(page)) - .withContext(`In ${browserName}`) - .toEqual([2]); - - // Create an empty editor. - await page.mouse.click(rect.x + 700, rect.y + 100); - expect(await getSelectedEditors(page)) - .withContext(`In ${browserName}`) - .toEqual([8]); - // Dismiss it. - await page.keyboard.press("Escape"); - - // Select all. - await page.keyboard.down("Control"); - await page.keyboard.press("a"); - await page.keyboard.up("Control"); - - // Check that all the editors are correctly selected (and the focus - // didn't move to the body when the empty editor was removed). - expect(await getSelectedEditors(page)) - .withContext(`In ${browserName}`) - .toEqual([0, 2, 4, 5, 6]); - }) - ); + // Check that all the editors are correctly selected (and the focus + // didn't move to the body when the empty editor was removed). + expect(await getSelectedEditors(page)) + .withContext(`In ${browserName}`) + .toEqual([0, 2, 4, 5, 6]); + } }); }); }); diff --git a/test/integration/scripting_spec.js b/test/integration/scripting_spec.js index fa086bfd0..64467f644 100644 --- a/test/integration/scripting_spec.js +++ b/test/integration/scripting_spec.js @@ -24,6 +24,9 @@ const { describe("Interaction", () => { async function actAndWaitForInput(page, selector, action, clear = true) { + await page.waitForSelector(selector, { + timeout: 0, + }); if (clear) { await clearInput(page, selector); } @@ -1430,13 +1433,18 @@ describe("Interaction", () => { [45, 180], [46, 270], ]) { - const rotation = await page.$eval( + await page.waitForFunction( + (sel, b, a) => { + const el = document.querySelector(sel); + const rotation = + parseInt(el.getAttribute("data-main-rotation")) || 0; + return rotation === (360 + ((360 - (b + a)) % 360)) % 360; + }, + {}, `[data-annotation-id='${ref}R']`, - el => parseInt(el.getAttribute("data-main-rotation") || 0) + base, + angle ); - expect(rotation) - .withContext(`In ${browserName}`) - .toEqual((360 + ((360 - (base + angle)) % 360)) % 360); } base += 90; await page.click(getSelector("48R")); diff --git a/test/integration/test_utils.js b/test/integration/test_utils.js index fa6443d8a..c50938d87 100644 --- a/test/integration/test_utils.js +++ b/test/integration/test_utils.js @@ -87,3 +87,16 @@ function getSelectedEditors(page) { }); } exports.getSelectedEditors = getSelectedEditors; + +async function waitForEvent(page, eventName, timeout = 30000) { + await Promise.race([ + // add event listener and wait for event to fire before returning + page.evaluate(name => { + return new Promise(resolve => { + document.addEventListener(name, resolve, { once: true }); + }); + }, eventName), + page.waitForTimeout(timeout), + ]); +} +exports.waitForEvent = waitForEvent;