Fix editor tests on Windows

- In #15373, we implemented copy/paste actions in using the system
clipboard.
For any reasons, on Windows, the clipboard doesn't contain the expected
data when the tests are ran in parallel, hence the tests which are
using the clipboard need to be ran sequentially.
- Make sure that we can paste after having copied.
This commit is contained in:
Calixte Denizet 2022-10-25 15:28:22 +02:00
parent 22225a1eaa
commit 2384fbcb89
3 changed files with 262 additions and 243 deletions

View File

@ -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]);
}
});
});
});

View File

@ -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"));

View File

@ -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;