Introduce a helper function to create a freetext editor in the integration tests

Doing so has a number of advantages:

- it removes code duplication, thereby improving readability;
- it removes hardcoded editor IDs, by using the `getNextEditorId` helper
  function that was previously introduced for the highlight editor
  integration tests, thereby improving readability and reusability;
- it removes potential for intermittent failures by not proceeding until
  the freetext editor is fully created and all assertions pass, which
  didn't happen consistently before because the code wasn't centralized.
This commit is contained in:
Tim van der Meij 2025-10-18 17:19:21 +02:00
parent 57334bd205
commit b5b821365e
No known key found for this signature in database
GPG Key ID: 8C3FD2925A5F2762
2 changed files with 319 additions and 314 deletions

View File

@ -19,6 +19,8 @@ import {
closePages, closePages,
copy, copy,
copyToClipboard, copyToClipboard,
countSerialized,
countStorageEntries,
createPromise, createPromise,
dragAndDrop, dragAndDrop,
firstPageOnTop, firstPageOnTop,
@ -26,6 +28,7 @@ import {
getEditors, getEditors,
getEditorSelector, getEditorSelector,
getFirstSerialized, getFirstSerialized,
getNextEditorId,
getRect, getRect,
getSerialized, getSerialized,
isCanvasMonochrome, isCanvasMonochrome,
@ -85,6 +88,34 @@ const cancelFocusIn = async (page, selector) => {
}, selector); }, selector);
}; };
const createFreeTextEditor = async ({
page,
x,
y,
data = null,
noFocusIn = false,
}) => {
const editorSelector = getEditorSelector(await getNextEditorId(page));
const serializedCount = await countSerialized(page);
const storageEntriesCount = await countStorageEntries(page);
await page.mouse.click(x, y);
await page.waitForSelector(editorSelector, { visible: true });
if (data) {
await page.type(`${editorSelector} .internal`, data);
}
if (noFocusIn) {
await cancelFocusIn(page, editorSelector);
}
await commit(page);
await waitForSelectedEditor(page, editorSelector);
await waitForStorageEntries(page, storageEntriesCount + 1);
await waitForSerialized(page, serializedCount + 1);
return editorSelector;
};
describe("FreeText Editor", () => { describe("FreeText Editor", () => {
describe("FreeText", () => { describe("FreeText", () => {
let pages; let pages;
@ -103,15 +134,13 @@ describe("FreeText Editor", () => {
await switchToFreeText(page); await switchToFreeText(page);
const rect = await getRect(page, ".annotationEditorLayer"); const rect = await getRect(page, ".annotationEditorLayer");
const editorSelector = getEditorSelector(0);
const data = "Hello PDF.js World !!"; const data = "Hello PDF.js World !!";
await page.mouse.click(rect.x + 100, rect.y + 100); const editorSelector = await createFreeTextEditor({
await page.waitForSelector(editorSelector, { visible: true }); page,
await page.type(`${editorSelector} .internal`, data); x: rect.x + 100,
await commit(page); y: rect.y + 100,
data,
await waitForSelectedEditor(page, editorSelector); });
await waitForStorageEntries(page, 1);
await page.waitForFunction( await page.waitForFunction(
`document.getElementById("viewer-alert").textContent === "Text added"` `document.getElementById("viewer-alert").textContent === "Text added"`
@ -143,13 +172,12 @@ describe("FreeText Editor", () => {
await switchToFreeText(page); await switchToFreeText(page);
const rect = await getRect(page, ".annotationEditorLayer"); const rect = await getRect(page, ".annotationEditorLayer");
const firstEditorSelector = getEditorSelector(0); const firstEditorSelector = await createFreeTextEditor({
const data = "Hello PDF.js World !!"; page,
await page.mouse.click(rect.x + 100, rect.y + 100); x: rect.x + 100,
await page.waitForSelector(firstEditorSelector, { visible: true }); y: rect.y + 100,
await page.type(`${firstEditorSelector} .internal`, data); data: "Hello PDF.js World !!",
await commit(page); });
await waitForStorageEntries(page, 1);
await selectEditor(page, firstEditorSelector); await selectEditor(page, firstEditorSelector);
await copy(page); await copy(page);
@ -187,13 +215,12 @@ describe("FreeText Editor", () => {
await switchToFreeText(page); await switchToFreeText(page);
const rect = await getRect(page, ".annotationEditorLayer"); const rect = await getRect(page, ".annotationEditorLayer");
const firstEditorSelector = getEditorSelector(0); const firstEditorSelector = await createFreeTextEditor({
const data = "Hello PDF.js World !!"; page,
await page.mouse.click(rect.x + 100, rect.y + 100); x: rect.x + 100,
await page.waitForSelector(firstEditorSelector, { visible: true }); y: rect.y + 100,
await page.type(`${firstEditorSelector} .internal`, data); data: "Hello PDF.js World !!",
await commit(page); });
await waitForStorageEntries(page, 1);
await page.evaluate(() => { await page.evaluate(() => {
window.PDFViewerApplication.eventBus.dispatch( window.PDFViewerApplication.eventBus.dispatch(
@ -240,12 +267,12 @@ describe("FreeText Editor", () => {
const rect = await getRect(page, ".annotationEditorLayer"); const rect = await getRect(page, ".annotationEditorLayer");
for (const n of [0, 1, 2]) { for (const n of [0, 1, 2]) {
const editorSelector = getEditorSelector(n); const editorSelector = await createFreeTextEditor({
const data = "Hello PDF.js World !!"; page,
await page.mouse.click(rect.x + 100 * n, rect.y + 100 * n); x: rect.x + 100 * n,
await page.waitForSelector(editorSelector, { visible: true }); y: rect.y + 100 * n,
await page.type(`${editorSelector} .internal`, data); data: "Hello PDF.js World !!",
await commit(page); });
const hasEditor = await page.evaluate( const hasEditor = await page.evaluate(
sel => !!document.querySelector(sel), sel => !!document.querySelector(sel),
@ -275,12 +302,12 @@ describe("FreeText Editor", () => {
await switchToFreeText(page); await switchToFreeText(page);
const rect = await getRect(page, ".annotationEditorLayer"); const rect = await getRect(page, ".annotationEditorLayer");
let editorSelector = getEditorSelector(0); let editorSelector = await createFreeTextEditor({
const data = "Hello PDF.js World !!"; page,
await page.mouse.click(rect.x + 100, rect.y + 100); x: rect.x + 100,
await page.waitForSelector(editorSelector, { visible: true }); y: rect.y + 100,
await page.type(`${editorSelector} .internal`, data); data: "Hello PDF.js World !!",
await commit(page); });
await selectEditor(page, editorSelector); await selectEditor(page, editorSelector);
await copy(page); await copy(page);
@ -317,12 +344,12 @@ describe("FreeText Editor", () => {
await switchToFreeText(page); await switchToFreeText(page);
const rect = await getRect(page, ".annotationEditorLayer"); const rect = await getRect(page, ".annotationEditorLayer");
const editorSelector = getEditorSelector(0); const editorSelector = await createFreeTextEditor({
const data = "Hello PDF.js World !!"; page,
await page.mouse.click(rect.x + 100, rect.y + 100); x: rect.x + 100,
await page.waitForSelector(editorSelector, { visible: true }); y: rect.y + 100,
await page.type(`${editorSelector} .internal`, data); data: "Hello PDF.js World !!",
await commit(page); });
expect(await getEditors(page, "selected")) expect(await getEditors(page, "selected"))
.withContext(`In ${browserName}`) .withContext(`In ${browserName}`)
@ -460,12 +487,12 @@ describe("FreeText Editor", () => {
const editorCenters = []; const editorCenters = [];
let lastX = rect.x + rect.width / 10; let lastX = rect.x + rect.width / 10;
for (let i = 0; i < 4; i++) { for (let i = 0; i < 4; i++) {
const editorSelector = getEditorSelector(i); const editorSelector = await createFreeTextEditor({
const data = `FreeText ${i}`; page,
await page.mouse.click(lastX, rect.y + rect.height / 10); x: lastX,
await page.waitForSelector(editorSelector, { visible: true }); y: rect.y + rect.height / 10,
await page.type(`${editorSelector} .internal`, data); data: `FreeText ${i}`,
await commit(page); });
const editorRect = await getRect(page, editorSelector); const editorRect = await getRect(page, editorSelector);
lastX = editorRect.x + editorRect.width + 10; lastX = editorRect.x + editorRect.width + 10;
@ -627,16 +654,13 @@ describe("FreeText Editor", () => {
); );
expect(oldAriaOwns).withContext(`In ${browserName}`).toEqual(null); expect(oldAriaOwns).withContext(`In ${browserName}`).toEqual(null);
const editorSelector = getEditorSelector(0);
const rect = await getRect(page, `span[pdfjs="true"]`); const rect = await getRect(page, `span[pdfjs="true"]`);
const data = "Hello PDF.js World !!"; await createFreeTextEditor({
await page.mouse.click( page,
rect.x + rect.width / 2, x: rect.x + rect.width / 2,
rect.y + rect.height / 2 y: rect.y + rect.height / 2,
); data: "Hello PDF.js World !!",
await page.waitForSelector(editorSelector, { visible: true }); });
await page.type(`${editorSelector} .internal`, data);
await commit(page);
const newAriaOwns = await page.$eval(`span[pdfjs="true"]`, el => const newAriaOwns = await page.$eval(`span[pdfjs="true"]`, el =>
el.getAttribute("aria-owns") el.getAttribute("aria-owns")
@ -664,7 +688,6 @@ describe("FreeText Editor", () => {
await Promise.all( await Promise.all(
pages.map(async ([browserName, page]) => { pages.map(async ([browserName, page]) => {
await switchToFreeText(page); await switchToFreeText(page);
let currentId = 0;
const expected = []; const expected = [];
const oneToFourteen = Array.from(new Array(14).keys(), x => x + 1); const oneToFourteen = Array.from(new Array(14).keys(), x => x + 1);
@ -682,23 +705,19 @@ describe("FreeText Editor", () => {
} }
const rect = await getRect(page, annotationLayerSelector); const rect = await getRect(page, annotationLayerSelector);
const editorSelector = getEditorSelector(currentId);
const data = `Hello PDF.js World !! on page ${pageNumber}`; const data = `Hello PDF.js World !! on page ${pageNumber}`;
expected.push(data); expected.push(data);
await page.mouse.click(rect.x + 100, rect.y + 100); const editorSelector = await createFreeTextEditor({
await page.waitForSelector(editorSelector, { visible: true }); page,
await page.type(`${editorSelector} .internal`, data); x: rect.x + 100,
await commit(page); y: rect.y + 100,
data,
await waitForSelectedEditor(page, editorSelector); });
await waitForStorageEntries(page, currentId + 1);
const content = await page.$eval(editorSelector, el => const content = await page.$eval(editorSelector, el =>
el.innerText.trimEnd() el.innerText.trimEnd()
); );
expect(content).withContext(`In ${browserName}`).toEqual(data); expect(content).withContext(`In ${browserName}`).toEqual(data);
currentId += 1;
} }
const serialize = proprName => const serialize = proprName =>
@ -808,19 +827,16 @@ describe("FreeText Editor", () => {
await Promise.all( await Promise.all(
pages.map(async ([browserName, page]) => { pages.map(async ([browserName, page]) => {
await switchToFreeText(page); await switchToFreeText(page);
let currentId = 0;
for (let step = 0; step < 3; step++) { for (let step = 0; step < 3; step++) {
await firstPageOnTop(page); await firstPageOnTop(page);
const rect = await getRect(page, ".annotationEditorLayer"); const rect = await getRect(page, ".annotationEditorLayer");
const editorSelector = getEditorSelector(currentId); await createFreeTextEditor({
const data = `Hello ${step}`; page,
const x = Math.max(rect.x + 0.1 * rect.width, 10); x: Math.max(rect.x + 0.1 * rect.width, 10),
const y = Math.max(rect.y + 0.1 * rect.height, 10); y: Math.max(rect.y + 0.1 * rect.height, 10),
await page.mouse.click(x, y); data: `Hello ${step}`,
await page.waitForSelector(editorSelector, { visible: true }); });
await page.type(`${editorSelector} .internal`, data);
await commit(page);
const promise = await waitForAnnotationEditorLayer(page); const promise = await waitForAnnotationEditorLayer(page);
await page.evaluate(() => { await page.evaluate(() => {
@ -828,7 +844,6 @@ describe("FreeText Editor", () => {
}); });
await awaitPromise(promise); await awaitPromise(promise);
currentId += 1;
await page.waitForSelector( await page.waitForSelector(
".page[data-page-number='1'] .canvasWrapper", ".page[data-page-number='1'] .canvasWrapper",
{ {
@ -1353,12 +1368,12 @@ describe("FreeText Editor", () => {
await switchToFreeText(page); await switchToFreeText(page);
const rect = await getRect(page, ".annotationEditorLayer"); const rect = await getRect(page, ".annotationEditorLayer");
const editorSelector = getEditorSelector(0); await createFreeTextEditor({
const data = "Hello PDF.js World !!"; page,
await page.mouse.click(rect.x + 100, rect.y + 100); x: rect.x + 100,
await page.waitForSelector(editorSelector, { visible: true }); y: rect.y + 100,
await page.type(`${editorSelector} .internal`, data); data: "Hello PDF.js World !!",
await commit(page); });
// Make Chrome happy. // Make Chrome happy.
await page.waitForFunction(() => { await page.waitForFunction(() => {
@ -1445,9 +1460,8 @@ describe("FreeText Editor", () => {
await Promise.all( await Promise.all(
pages.map(async ([browserName, page]) => { pages.map(async ([browserName, page]) => {
await switchToFreeText(page); await switchToFreeText(page);
let currentId = 0;
const oneToFourteen = Array.from(new Array(14).keys(), x => x + 1);
const oneToFourteen = Array.from(new Array(14).keys(), x => x + 1);
for (const pageNumber of oneToFourteen) { for (const pageNumber of oneToFourteen) {
const pageSelector = `.page[data-page-number = "${pageNumber}"]`; const pageSelector = `.page[data-page-number = "${pageNumber}"]`;
@ -1462,14 +1476,12 @@ describe("FreeText Editor", () => {
} }
const rect = await getRect(page, annotationLayerSelector); const rect = await getRect(page, annotationLayerSelector);
const editorSelector = getEditorSelector(currentId); await createFreeTextEditor({
const data = `Hello PDF.js World !! on page ${pageNumber}`; page,
await page.mouse.click(rect.x + 100, rect.y + 100); x: rect.x + 100,
await page.waitForSelector(editorSelector, { visible: true }); y: rect.y + 100,
await page.type(`${editorSelector} .internal`, data); data: `Hello PDF.js World !! on page ${pageNumber}`,
await commit(page); });
currentId += 1;
} }
await selectAll(page); await selectAll(page);
@ -1804,12 +1816,12 @@ describe("FreeText Editor", () => {
await switchToFreeText(page); await switchToFreeText(page);
const rect = await getRect(page, ".annotationEditorLayer"); const rect = await getRect(page, ".annotationEditorLayer");
const editorSelector = getEditorSelector(0); const editorSelector = await createFreeTextEditor({
const data = "Hello PDF.js World !!"; page,
await page.mouse.click(rect.x + 100, rect.y + 100); x: rect.x + 100,
await page.waitForSelector(editorSelector, { visible: true }); y: rect.y + 100,
await page.type(`${editorSelector} .internal`, data); data: "Hello PDF.js World !!",
await commit(page); });
await page.focus("#editorFreeTextColor"); await page.focus("#editorFreeTextColor");
await kbUndo(page); await kbUndo(page);
@ -1848,13 +1860,12 @@ describe("FreeText Editor", () => {
await switchToFreeText(page); await switchToFreeText(page);
const rect = await getRect(page, ".annotationEditorLayer"); const rect = await getRect(page, ".annotationEditorLayer");
const editorSelector = await createFreeTextEditor({
const data = "Hello PDF.js World !!"; page,
const editorSelector = getEditorSelector(0); x: rect.x + 200,
await page.mouse.click(rect.x + 200, rect.y + 200); y: rect.y + 200,
await page.waitForSelector(editorSelector, { visible: true }); data: "Hello PDF.js World !!",
await page.type(`${editorSelector} .internal`, data); });
await commit(page);
const [pageX, pageY] = await getFirstSerialized(page, x => x.rect); const [pageX, pageY] = await getFirstSerialized(page, x => x.rect);
@ -1911,12 +1922,12 @@ describe("FreeText Editor", () => {
await switchToFreeText(page); await switchToFreeText(page);
const rect = await getRect(page, ".annotationEditorLayer"); const rect = await getRect(page, ".annotationEditorLayer");
const data = "Hello PDF.js World !!"; const editorSelector = await createFreeTextEditor({
const editorSelector = getEditorSelector(0); page,
await page.mouse.click(rect.x + 200, rect.y + 200); x: rect.x + 200,
await page.waitForSelector(editorSelector, { visible: true }); y: rect.y + 200,
await page.type(`${editorSelector} .internal`, data); data: "Hello PDF.js World !!",
await commit(page); });
await selectAll(page); await selectAll(page);
await page.focus("#editorFreeTextFontSize"); await page.focus("#editorFreeTextFontSize");
@ -1950,16 +1961,17 @@ describe("FreeText Editor", () => {
const rect = await getRect(page, ".annotationEditorLayer"); const rect = await getRect(page, ".annotationEditorLayer");
const data = "Hello PDF.js World !!"; const data = "Hello PDF.js World !!";
let editorSelector = getEditorSelector(0); await createFreeTextEditor({
await page.mouse.click(rect.x + 100, rect.y + 100); page,
await page.waitForSelector(editorSelector, { visible: true }); x: rect.x + 100,
await page.type(`${editorSelector} .internal`, data); y: rect.y + 100,
await commit(page); data,
});
const [pageX, pageY] = await getFirstSerialized(page, x => x.rect); const [pageX, pageY] = await getFirstSerialized(page, x => x.rect);
await clearAll(page); await clearAll(page);
editorSelector = getEditorSelector(1); const editorSelector = getEditorSelector(1);
await page.mouse.click(rect.x + 100, rect.y + 100); await page.mouse.click(rect.x + 100, rect.y + 100);
await page.waitForSelector(editorSelector, { visible: true }); await page.waitForSelector(editorSelector, { visible: true });
@ -2023,13 +2035,13 @@ describe("FreeText Editor", () => {
await switchToFreeText(page); await switchToFreeText(page);
const rect = await getRect(page, ".annotationEditorLayer"); const rect = await getRect(page, ".annotationEditorLayer");
const editorSelector = getEditorSelector(0); await createFreeTextEditor({
const data = "Hello PDF.js World !!"; page,
await page.mouse.click(rect.x + 100, rect.y + 100); x: rect.x + 100,
await page.waitForSelector(editorSelector, { visible: true }); y: rect.y + 100,
await page.type(`${editorSelector} .internal`, data); data: "Hello PDF.js World !!",
await cancelFocusIn(page, editorSelector); noFocusIn: true,
await commit(page); });
const oneToFourteen = Array.from(new Array(14).keys(), x => x + 1); const oneToFourteen = Array.from(new Array(14).keys(), x => x + 1);
@ -2076,23 +2088,21 @@ describe("FreeText Editor", () => {
await switchToFreeText(page); await switchToFreeText(page);
let rect = await getRect(page, ".annotationEditorLayer"); let rect = await getRect(page, ".annotationEditorLayer");
const firstEditorSelector = await createFreeTextEditor({
const firstEditorSelector = getEditorSelector(0); page,
await page.mouse.click(rect.x + 100, rect.y + 100); x: rect.x + 100,
await page.waitForSelector(firstEditorSelector, { visible: true }); y: rect.y + 100,
await page.type(`${firstEditorSelector} .internal`, "A"); data: "A",
await commit(page); });
// Create a new editor. // Create a new editor.
rect = await getRect(page, firstEditorSelector); rect = await getRect(page, firstEditorSelector);
const secondEditorSelector = getEditorSelector(1); const secondEditorSelector = await createFreeTextEditor({
await page.mouse.click( page,
rect.x + 5 * rect.width, x: rect.x + 5 * rect.width,
rect.y + 5 * rect.height y: rect.y + 5 * rect.height,
); data: "B",
await page.waitForSelector(secondEditorSelector, { visible: true }); });
await page.type(`${secondEditorSelector} .internal`, "B");
await commit(page);
// Select the second editor. // Select the second editor.
await selectEditor(page, secondEditorSelector); await selectEditor(page, secondEditorSelector);
@ -2155,15 +2165,12 @@ describe("FreeText Editor", () => {
const allPositions = []; const allPositions = [];
for (let i = 0; i < 10; i++) { for (let i = 0; i < 10; i++) {
const editorSelector = getEditorSelector(i); const editorSelector = await createFreeTextEditor({
await page.mouse.click(rect.x + 10 + 30 * i, rect.y + 100 + 5 * i); page,
await page.waitForSelector(editorSelector, { visible: true }); x: rect.x + 10 + 30 * i,
await page.type( y: rect.y + 100 + 5 * i,
`${editorSelector} .internal`, data: String.fromCharCode(65 + i),
String.fromCharCode(65 + i) });
);
await commit(page);
allPositions.push(await getRect(page, editorSelector)); allPositions.push(await getRect(page, editorSelector));
} }
@ -2214,13 +2221,13 @@ describe("FreeText Editor", () => {
await switchToFreeText(page); await switchToFreeText(page);
const rect = await getRect(page, ".annotationEditorLayer"); const rect = await getRect(page, ".annotationEditorLayer");
const editorSelector = getEditorSelector(0); await createFreeTextEditor({
const data = "Hello PDF.js World !!"; page,
await page.mouse.click(rect.x + 100, rect.y + 100); x: rect.x + 100,
await page.waitForSelector(editorSelector, { visible: true }); y: rect.y + 100,
await page.type(`${editorSelector} .internal`, data); data: "Hello PDF.js World !!",
await cancelFocusIn(page, editorSelector); noFocusIn: true,
await commit(page); });
await page.evaluate(() => { await page.evaluate(() => {
window.editingEvents = []; window.editingEvents = [];
@ -2267,12 +2274,13 @@ describe("FreeText Editor", () => {
const page1Selector = `.page[data-page-number = "1"] > .annotationEditorLayer.freetextEditing`; const page1Selector = `.page[data-page-number = "1"] > .annotationEditorLayer.freetextEditing`;
let rect = await getRect(page, page1Selector); let rect = await getRect(page, page1Selector);
const firstEditorSelector = getEditorSelector(0); const firstEditorSelector = await createFreeTextEditor({
await page.mouse.click(rect.x + 10, rect.y + 10); page,
await page.waitForSelector(firstEditorSelector, { visible: true }); x: rect.x + 10,
await page.type(`${firstEditorSelector} .internal`, "Hello"); y: rect.y + 10,
await cancelFocusIn(page, firstEditorSelector); data: "Hello",
await commit(page); noFocusIn: true,
});
// Unselect. // Unselect.
await unselectEditor(page, firstEditorSelector); await unselectEditor(page, firstEditorSelector);
@ -2290,11 +2298,12 @@ describe("FreeText Editor", () => {
}); });
rect = await getRect(page, page14Selector); rect = await getRect(page, page14Selector);
const secondEditorSelector = getEditorSelector(1); await createFreeTextEditor({
await page.mouse.click(rect.x + 10, rect.y + 10); page,
await page.waitForSelector(secondEditorSelector, { visible: true }); x: rect.x + 10,
await page.type(`${secondEditorSelector} .internal`, "World"); y: rect.y + 10,
await commit(page); data: "World",
});
for (let i = 0; i < 13; i++) { for (let i = 0; i < 13; i++) {
await page.keyboard.press("P"); await page.keyboard.press("P");
@ -2336,12 +2345,13 @@ describe("FreeText Editor", () => {
const page1Selector = `.page[data-page-number = "1"] > .annotationEditorLayer.freetextEditing`; const page1Selector = `.page[data-page-number = "1"] > .annotationEditorLayer.freetextEditing`;
const rect = await getRect(page, page1Selector); const rect = await getRect(page, page1Selector);
const editorSelector = getEditorSelector(0); const editorSelector = await createFreeTextEditor({
await page.mouse.click(rect.x + 10, rect.y + 10); page,
await page.waitForSelector(editorSelector, { visible: true }); x: rect.x + 10,
await page.type(`${editorSelector} .internal`, "Hello"); y: rect.y + 10,
await cancelFocusIn(page, editorSelector); data: "Hello",
await commit(page); noFocusIn: true,
});
// Unselect. // Unselect.
await unselectEditor(page, editorSelector); await unselectEditor(page, editorSelector);
@ -2394,7 +2404,6 @@ describe("FreeText Editor", () => {
await switchToFreeText(page); await switchToFreeText(page);
const parentId = "p3R_mc8"; const parentId = "p3R_mc8";
const editorSelector = getEditorSelector(0);
const rect = await page.evaluate(id => { const rect = await page.evaluate(id => {
const parent = document.getElementById(id); const parent = document.getElementById(id);
let span = null; let span = null;
@ -2407,15 +2416,13 @@ describe("FreeText Editor", () => {
const { x, y, width, height } = span.getBoundingClientRect(); const { x, y, width, height } = span.getBoundingClientRect();
return { x, y, width, height }; return { x, y, width, height };
}, parentId); }, parentId);
await page.mouse.click(
rect.x + rect.width + 5,
rect.y + rect.height / 2
);
await page.waitForSelector(editorSelector, { visible: true });
await page.type(`${editorSelector} .internal`, "Hello Wolrd");
await commit(page);
await waitForStorageEntries(page, 1); await createFreeTextEditor({
page,
x: rect.x + rect.width + 5,
y: rect.y + rect.height / 2,
data: "Hello World",
});
const id = await getFirstSerialized(page, x => x.structTreeParentId); const id = await getFirstSerialized(page, x => x.structTreeParentId);
expect(id).withContext(`In ${browserName}`).toEqual(parentId); expect(id).withContext(`In ${browserName}`).toEqual(parentId);
@ -2441,21 +2448,19 @@ describe("FreeText Editor", () => {
await switchToFreeText(page); await switchToFreeText(page);
const rect = await getRect(page, ".annotationEditorLayer"); const rect = await getRect(page, ".annotationEditorLayer");
const editorSelector = getEditorSelector(0);
const data = "Hello PDF.js World !!"; const data = "Hello PDF.js World !!";
await page.mouse.click(rect.x + 100, rect.y + 100); const editorSelector = await createFreeTextEditor({
await page.waitForSelector(editorSelector, { visible: true }); page,
const internalEditorSelector = `${editorSelector} .internal`; x: rect.x + 100,
await page.type(internalEditorSelector, data); y: rect.y + 100,
await commit(page); data,
});
await page.click(editorSelector, { count: 2 }); await page.click(editorSelector, { count: 2 });
await page.waitForSelector( await page.waitForSelector(
`${editorSelector} .overlay:not(.enabled)` `${editorSelector} .overlay:not(.enabled)`
); );
await page.click(internalEditorSelector, { await page.click(`${editorSelector} .internal`, { count: 3 });
count: 3,
});
const selection = await page.evaluate(() => const selection = await page.evaluate(() =>
document.getSelection().toString() document.getSelection().toString()
); );
@ -2588,12 +2593,13 @@ describe("FreeText Editor", () => {
await switchToFreeText(page); await switchToFreeText(page);
const rect = await getRect(page, ".annotationEditorLayer"); const rect = await getRect(page, ".annotationEditorLayer");
const editorSelector = getEditorSelector(0);
const data = "Hello PDF.js World !!"; const data = "Hello PDF.js World !!";
await page.mouse.click(rect.x + 100, rect.y + 100); const editorSelector = await createFreeTextEditor({
await page.waitForSelector(editorSelector, { visible: true }); page,
await page.type(`${editorSelector} .internal`, data); x: rect.x + 100,
await commit(page); y: rect.y + 100,
data,
});
let handle = await createPromise(page, resolve => { let handle = await createPromise(page, resolve => {
document.addEventListener("selectionchange", resolve, { document.addEventListener("selectionchange", resolve, {
@ -2642,12 +2648,12 @@ describe("FreeText Editor", () => {
await switchToFreeText(page); await switchToFreeText(page);
const rect = await getRect(page, ".annotationEditorLayer"); const rect = await getRect(page, ".annotationEditorLayer");
const editorSelector = getEditorSelector(0); const editorSelector = await createFreeTextEditor({
const data = "Hello PDF.js World !!"; page,
await page.mouse.click(rect.x + 100, rect.y + 100); x: rect.x + 100,
await page.waitForSelector(editorSelector, { visible: true }); y: rect.y + 100,
await page.type(`${editorSelector} .internal`, data); data: "Hello PDF.js World !!",
await commit(page); });
// Delete it in using the button. // Delete it in using the button.
await page.click(`${editorSelector} button.deleteButton`); await page.click(`${editorSelector} button.deleteButton`);
@ -2685,38 +2691,39 @@ describe("FreeText Editor", () => {
await switchToFreeText(page); await switchToFreeText(page);
const rect = await getRect(page, ".annotationEditorLayer"); const rect = await getRect(page, ".annotationEditorLayer");
const firstEditorSelector = await createFreeTextEditor({
page,
x: rect.x + 100,
y: rect.y + 100,
data: "Hello PDF.js World !!",
});
const secondEditorSelector = await createFreeTextEditor({
page,
x: rect.x + 200,
y: rect.y + 200,
data: "Hello PDF.js World !!",
});
const data = "Hello PDF.js World !!"; // Select the first editor.
await selectEditor(page, firstEditorSelector);
for (let i = 1; i <= 2; i++) {
const editorSelector = getEditorSelector(i - 1);
await page.mouse.click(rect.x + i * 100, rect.y + i * 100);
await page.waitForSelector(editorSelector, { visible: true });
await page.type(`${editorSelector} .internal`, data);
await commit(page);
}
// Select the editor created previously.
const editorSelector = getEditorSelector(0);
await selectEditor(page, editorSelector);
await selectAll(page); await selectAll(page);
// Delete it in using the button. // Delete it in using the button.
await page.focus(`${editorSelector} button.deleteButton`); await page.focus(`${firstEditorSelector} button.deleteButton`);
await page.keyboard.press("Enter"); await page.keyboard.press("Enter");
await page.waitForFunction( await page.waitForFunction(
sel => !document.querySelector(sel), sel => !document.querySelector(sel),
{}, {},
editorSelector firstEditorSelector
); );
await waitForStorageEntries(page, 0); await waitForStorageEntries(page, 0);
// Undo. // Undo.
await kbUndo(page); await kbUndo(page);
await waitForSerialized(page, 2); await waitForSerialized(page, 2);
await page.waitForSelector(editorSelector, { visible: true }); await page.waitForSelector(firstEditorSelector, { visible: true });
await page.waitForSelector(getEditorSelector(1), { visible: true }); await page.waitForSelector(secondEditorSelector, { visible: true });
}) })
); );
}); });
@ -2801,14 +2808,14 @@ describe("FreeText Editor", () => {
await switchToFreeText(page); await switchToFreeText(page);
const rect = await getRect(page, ".annotationEditorLayer"); const rect = await getRect(page, ".annotationEditorLayer");
const editorSelector = getEditorSelector(0);
const data = "Hello\nPDF.js\nWorld\n!!"; const data = "Hello\nPDF.js\nWorld\n!!";
await page.mouse.click(rect.x + 100, rect.y + 100); await createFreeTextEditor({
await page.waitForSelector(editorSelector, { visible: true }); page,
await page.type(`${editorSelector} .internal`, data); x: rect.x + 100,
await commit(page); y: rect.y + 100,
data,
});
await waitForSerialized(page, 1);
const serialized = (await getSerialized(page))[0]; const serialized = (await getSerialized(page))[0];
expect(serialized.value) expect(serialized.value)
.withContext(`In ${browserName}`) .withContext(`In ${browserName}`)
@ -2835,12 +2842,12 @@ describe("FreeText Editor", () => {
await switchToFreeText(page); await switchToFreeText(page);
const rect = await getRect(page, ".annotationEditorLayer"); const rect = await getRect(page, ".annotationEditorLayer");
const editorSelector = getEditorSelector(0); await createFreeTextEditor({
const data = "Hello PDF.js World !!"; page,
await page.mouse.click(rect.x + 100, rect.y + 100); x: rect.x + 100,
await page.waitForSelector(editorSelector, { visible: true }); y: rect.y + 100,
await page.type(`${editorSelector} .internal`, data); data: "Hello PDF.js World !!",
await commit(page); });
await page.evaluate(() => { await page.evaluate(() => {
window.PDFViewerApplication.eventBus.dispatch( window.PDFViewerApplication.eventBus.dispatch(
@ -2936,13 +2943,12 @@ describe("FreeText Editor", () => {
await switchToFreeText(page); await switchToFreeText(page);
const rect = await getRect(page, ".annotationEditorLayer"); const rect = await getRect(page, ".annotationEditorLayer");
const editorSelector = getEditorSelector(0); const editorSelector = await createFreeTextEditor({
const data = "Hello PDF.js World !!"; page,
await page.mouse.click(rect.x + 100, rect.y + 100); x: rect.x + 100,
await page.waitForSelector(editorSelector, { visible: true }); y: rect.y + 100,
await page.type(`${editorSelector} .internal`, data); data: "Hello PDF.js World !!",
await commit(page); });
await waitForSerialized(page, 1);
await page.waitForSelector(`${editorSelector} button.deleteButton`); await page.waitForSelector(`${editorSelector} button.deleteButton`);
await page.click(`${editorSelector} button.deleteButton`); await page.click(`${editorSelector} button.deleteButton`);
@ -2986,13 +2992,12 @@ describe("FreeText Editor", () => {
await switchToFreeText(page); await switchToFreeText(page);
const rect = await getRect(page, ".annotationEditorLayer"); const rect = await getRect(page, ".annotationEditorLayer");
const editorSelector = getEditorSelector(0); const editorSelector = await createFreeTextEditor({
const data = "Hello PDF.js World !!"; page,
await page.mouse.click(rect.x + 100, rect.y + 100); x: rect.x + 100,
await page.waitForSelector(editorSelector, { visible: true }); y: rect.y + 100,
await page.type(`${editorSelector} .internal`, data); data: "Hello PDF.js World !!",
await commit(page); });
await waitForSerialized(page, 1);
await page.waitForSelector(`${editorSelector} button.deleteButton`); await page.waitForSelector(`${editorSelector} button.deleteButton`);
await page.click(`${editorSelector} button.deleteButton`); await page.click(`${editorSelector} button.deleteButton`);
@ -3031,13 +3036,13 @@ describe("FreeText Editor", () => {
await switchToFreeText(page); await switchToFreeText(page);
const rect = await getRect(page, ".annotationEditorLayer"); const rect = await getRect(page, ".annotationEditorLayer");
let editorSelector = getEditorSelector(0);
const data = "Hello PDF.js World !!"; const data = "Hello PDF.js World !!";
await page.mouse.click(rect.x + 100, rect.y + 100); let editorSelector = await createFreeTextEditor({
await page.waitForSelector(editorSelector, { visible: true }); page,
await page.type(`${editorSelector} .internal`, data); x: rect.x + 100,
await commit(page); y: rect.y + 100,
data,
});
const waitForTextChange = (previous, edSelector) => const waitForTextChange = (previous, edSelector) =>
page.waitForFunction( page.waitForFunction(
@ -3300,7 +3305,6 @@ describe("FreeText Editor", () => {
describe("Undo deletion popup has the expected behaviour", () => { describe("Undo deletion popup has the expected behaviour", () => {
let pages; let pages;
const editorSelector = getEditorSelector(0);
beforeEach(async () => { beforeEach(async () => {
pages = await loadAndWait("tracemonkey.pdf", ".annotationEditorLayer"); pages = await loadAndWait("tracemonkey.pdf", ".annotationEditorLayer");
@ -3316,12 +3320,12 @@ describe("FreeText Editor", () => {
await switchToFreeText(page); await switchToFreeText(page);
const rect = await getRect(page, ".annotationEditorLayer"); const rect = await getRect(page, ".annotationEditorLayer");
const data = "Hello PDF.js World !!"; const editorSelector = await createFreeTextEditor({
await page.mouse.click(rect.x + 100, rect.y + 100); page,
await page.waitForSelector(editorSelector, { visible: true }); x: rect.x + 100,
await page.type(`${editorSelector} .internal`, data); y: rect.y + 100,
await commit(page); data: "Hello PDF.js World !!",
await waitForSerialized(page, 1); });
await page.waitForSelector(`${editorSelector} button.deleteButton`); await page.waitForSelector(`${editorSelector} button.deleteButton`);
await page.click(`${editorSelector} button.deleteButton`); await page.click(`${editorSelector} button.deleteButton`);
@ -3344,12 +3348,12 @@ describe("FreeText Editor", () => {
await switchToFreeText(page); await switchToFreeText(page);
const rect = await getRect(page, ".annotationEditorLayer"); const rect = await getRect(page, ".annotationEditorLayer");
const data = "Hello PDF.js World !!"; const editorSelector = await createFreeTextEditor({
await page.mouse.click(rect.x + 100, rect.y + 100); page,
await page.waitForSelector(editorSelector, { visible: true }); x: rect.x + 100,
await page.type(`${editorSelector} .internal`, data); y: rect.y + 100,
await commit(page); data: "Hello PDF.js World !!",
await waitForSerialized(page, 1); });
await page.waitForSelector(`${editorSelector} button.deleteButton`); await page.waitForSelector(`${editorSelector} button.deleteButton`);
await page.click(`${editorSelector} button.deleteButton`); await page.click(`${editorSelector} button.deleteButton`);
@ -3377,12 +3381,12 @@ describe("FreeText Editor", () => {
await switchToFreeText(page); await switchToFreeText(page);
let rect = await getRect(page, ".annotationEditorLayer"); let rect = await getRect(page, ".annotationEditorLayer");
const data = "Hello PDF.js World !!"; const editorSelector = await createFreeTextEditor({
await page.mouse.click(rect.x + 100, rect.y + 100); page,
await page.waitForSelector(editorSelector, { visible: true }); x: rect.x + 100,
await page.type(`${editorSelector} .internal`, data); y: rect.y + 100,
await commit(page); data: "Hello PDF.js World !!",
await waitForSerialized(page, 1); });
await page.waitForSelector(`${editorSelector} button.deleteButton`); await page.waitForSelector(`${editorSelector} button.deleteButton`);
await page.click(`${editorSelector} button.deleteButton`); await page.click(`${editorSelector} button.deleteButton`);
@ -3390,13 +3394,12 @@ describe("FreeText Editor", () => {
await page.waitForSelector("#editorUndoBar", { visible: true }); await page.waitForSelector("#editorUndoBar", { visible: true });
rect = await getRect(page, ".annotationEditorLayer"); rect = await getRect(page, ".annotationEditorLayer");
const secondEditorSelector = getEditorSelector(1); await createFreeTextEditor({
const newData = "This is a new text box!"; page,
await page.mouse.click(rect.x + 150, rect.y + 150); x: rect.x + 150,
await page.waitForSelector(secondEditorSelector, { visible: true }); y: rect.y + 150,
await page.type(`${secondEditorSelector} .internal`, newData); data: "This is a new text box!",
await commit(page); });
await waitForSerialized(page, 1);
await page.waitForSelector("#editorUndoBar", { hidden: true }); await page.waitForSelector("#editorUndoBar", { hidden: true });
}) })
); );
@ -3420,14 +3423,12 @@ describe("FreeText Editor", () => {
await switchToFreeText(page); await switchToFreeText(page);
const rect = await getRect(page, ".annotationEditorLayer"); const rect = await getRect(page, ".annotationEditorLayer");
const editorSelector = getEditorSelector(0); const editorSelector = await createFreeTextEditor({
page,
const data = "Hello PDF.js World !!"; x: rect.x + 100,
await page.mouse.click(rect.x + 100, rect.y + 100); y: rect.y + 100,
await page.waitForSelector(editorSelector, { visible: true }); data: "Hello PDF.js World !!",
await page.type(`${editorSelector} .internal`, data); });
await commit(page);
await waitForSerialized(page, 1);
let alignment = await page.$eval( let alignment = await page.$eval(
`${editorSelector} .internal`, `${editorSelector} .internal`,
@ -3468,17 +3469,12 @@ describe("FreeText Editor", () => {
await switchToFreeText(page); await switchToFreeText(page);
const rect = await getRect(page, ".annotationEditorLayer"); const rect = await getRect(page, ".annotationEditorLayer");
const editorSelector = getEditorSelector(0); const editorSelector = await createFreeTextEditor({
page,
const data = "Hello PDF.js World !!"; x: rect.x + rect.width / 2,
await page.mouse.click( y: rect.y + rect.height / 2,
rect.x + rect.width / 2, data: "Hello PDF.js World !!",
rect.y + rect.height / 2 });
);
await page.waitForSelector(editorSelector, { visible: true });
await page.type(`${editorSelector} .internal`, data);
await commit(page);
await waitForSerialized(page, 1);
await switchToFreeText(page, /* disable */ true); await switchToFreeText(page, /* disable */ true);
@ -3508,17 +3504,12 @@ describe("FreeText Editor", () => {
await switchToFreeText(page); await switchToFreeText(page);
const rect = await getRect(page, ".annotationEditorLayer"); const rect = await getRect(page, ".annotationEditorLayer");
const editorSelector = getEditorSelector(0); const editorSelector = await createFreeTextEditor({
page,
const data = "Hello PDF.js World !!"; x: rect.x + rect.width / 2,
await page.mouse.click( y: rect.y + rect.height / 2,
rect.x + rect.width / 2, data: "Hello PDF.js World !!",
rect.y + rect.height / 2 });
);
await page.waitForSelector(editorSelector, { visible: true });
await page.type(`${editorSelector} .internal`, data);
await commit(page);
await waitForSerialized(page, 1);
await switchToFreeText(page, /* disable */ true); await switchToFreeText(page, /* disable */ true);
await switchToEditor("Ink", page); await switchToEditor("Ink", page);
@ -3573,15 +3564,12 @@ describe("FreeText Editor", () => {
await switchToFreeText(page); await switchToFreeText(page);
const rect = await getRect(page, ".annotationEditorLayer"); const rect = await getRect(page, ".annotationEditorLayer");
const editorSelector = getEditorSelector(0); const editorSelector = await createFreeTextEditor({
const data = "Hello PDF.js World !!"; page,
await page.mouse.click( x: rect.x + rect.width / 2,
rect.x + rect.width / 2, y: rect.y + rect.height / 2,
rect.y + rect.height / 2 data: "Hello PDF.js World !!",
); });
await page.waitForSelector(editorSelector, { visible: true });
await page.type(`${editorSelector} .internal`, data);
await commit(page);
const colorPickerSelector = `${editorSelector} input.basicColorPicker`; const colorPickerSelector = `${editorSelector} input.basicColorPicker`;
await page.waitForSelector(colorPickerSelector, { visible: true }); await page.waitForSelector(colorPickerSelector, { visible: true });

View File

@ -310,6 +310,12 @@ async function waitForEvent({
} }
} }
async function countStorageEntries(page) {
return page.evaluate(
() => window.PDFViewerApplication.pdfDocument.annotationStorage.size
);
}
async function waitForStorageEntries(page, nEntries) { async function waitForStorageEntries(page, nEntries) {
return page.waitForFunction( return page.waitForFunction(
n => window.PDFViewerApplication.pdfDocument.annotationStorage.size === n, n => window.PDFViewerApplication.pdfDocument.annotationStorage.size === n,
@ -318,6 +324,14 @@ async function waitForStorageEntries(page, nEntries) {
); );
} }
async function countSerialized(page) {
return page.evaluate(
() =>
window.PDFViewerApplication.pdfDocument.annotationStorage.serializable.map
?.size ?? 0
);
}
async function waitForSerialized(page, nEntries) { async function waitForSerialized(page, nEntries) {
return page.waitForFunction( return page.waitForFunction(
n => { n => {
@ -924,6 +938,8 @@ export {
closeSinglePage, closeSinglePage,
copy, copy,
copyToClipboard, copyToClipboard,
countSerialized,
countStorageEntries,
createPromise, createPromise,
dragAndDrop, dragAndDrop,
firstPageOnTop, firstPageOnTop,
@ -935,6 +951,7 @@ export {
getEditors, getEditors,
getEditorSelector, getEditorSelector,
getFirstSerialized, getFirstSerialized,
getNextEditorId,
getQuerySelector, getQuerySelector,
getRect, getRect,
getSelector, getSelector,