Merge pull request #18331 from timvandermeij/integration-test-copy-pasting
Refactor the copy/paste logic in the integration tests and fix a race condition involving the `waitForEvent` integration test helper function
This commit is contained in:
commit
6d579081c4
@ -15,7 +15,7 @@
|
|||||||
|
|
||||||
import {
|
import {
|
||||||
closePages,
|
closePages,
|
||||||
kbCopy,
|
copy,
|
||||||
kbSelectAll,
|
kbSelectAll,
|
||||||
loadAndWait,
|
loadAndWait,
|
||||||
mockClipboard,
|
mockClipboard,
|
||||||
@ -23,9 +23,11 @@ import {
|
|||||||
} from "./test_utils.mjs";
|
} from "./test_utils.mjs";
|
||||||
|
|
||||||
const selectAll = async page => {
|
const selectAll = async page => {
|
||||||
const promise = waitForEvent(page, "selectionchange");
|
await waitForEvent({
|
||||||
await kbSelectAll(page);
|
page,
|
||||||
await promise;
|
eventName: "selectionchange",
|
||||||
|
action: () => kbSelectAll(page),
|
||||||
|
});
|
||||||
|
|
||||||
await page.waitForFunction(() => {
|
await page.waitForFunction(() => {
|
||||||
const selection = document.getSelection();
|
const selection = document.getSelection();
|
||||||
@ -55,10 +57,7 @@ describe("Copy and paste", () => {
|
|||||||
);
|
);
|
||||||
await selectAll(page);
|
await selectAll(page);
|
||||||
|
|
||||||
const promise = waitForEvent(page, "copy");
|
await copy(page);
|
||||||
await kbCopy(page);
|
|
||||||
await promise;
|
|
||||||
|
|
||||||
await page.waitForFunction(
|
await page.waitForFunction(
|
||||||
`document.querySelector('#viewerContainer').style.cursor !== "wait"`
|
`document.querySelector('#viewerContainer').style.cursor !== "wait"`
|
||||||
);
|
);
|
||||||
@ -159,10 +158,7 @@ describe("Copy and paste", () => {
|
|||||||
);
|
);
|
||||||
await selectAll(page);
|
await selectAll(page);
|
||||||
|
|
||||||
const promise = waitForEvent(page, "copy");
|
await copy(page);
|
||||||
await kbCopy(page);
|
|
||||||
await promise;
|
|
||||||
|
|
||||||
await page.waitForFunction(
|
await page.waitForFunction(
|
||||||
`document.querySelector('#viewerContainer').style.cursor !== "wait"`
|
`document.querySelector('#viewerContainer').style.cursor !== "wait"`
|
||||||
);
|
);
|
||||||
|
|||||||
@ -16,6 +16,8 @@
|
|||||||
import {
|
import {
|
||||||
awaitPromise,
|
awaitPromise,
|
||||||
closePages,
|
closePages,
|
||||||
|
copy,
|
||||||
|
copyToClipboard,
|
||||||
createPromise,
|
createPromise,
|
||||||
dragAndDropAnnotation,
|
dragAndDropAnnotation,
|
||||||
firstPageOnTop,
|
firstPageOnTop,
|
||||||
@ -30,21 +32,19 @@ import {
|
|||||||
kbBigMoveLeft,
|
kbBigMoveLeft,
|
||||||
kbBigMoveRight,
|
kbBigMoveRight,
|
||||||
kbBigMoveUp,
|
kbBigMoveUp,
|
||||||
kbCopy,
|
|
||||||
kbGoToBegin,
|
kbGoToBegin,
|
||||||
kbGoToEnd,
|
kbGoToEnd,
|
||||||
kbModifierDown,
|
kbModifierDown,
|
||||||
kbModifierUp,
|
kbModifierUp,
|
||||||
kbPaste,
|
|
||||||
kbRedo,
|
kbRedo,
|
||||||
kbSelectAll,
|
kbSelectAll,
|
||||||
kbUndo,
|
kbUndo,
|
||||||
loadAndWait,
|
loadAndWait,
|
||||||
|
paste,
|
||||||
pasteFromClipboard,
|
pasteFromClipboard,
|
||||||
scrollIntoView,
|
scrollIntoView,
|
||||||
switchToEditor,
|
switchToEditor,
|
||||||
waitForAnnotationEditorLayer,
|
waitForAnnotationEditorLayer,
|
||||||
waitForEvent,
|
|
||||||
waitForSelectedEditor,
|
waitForSelectedEditor,
|
||||||
waitForSerialized,
|
waitForSerialized,
|
||||||
waitForStorageEntries,
|
waitForStorageEntries,
|
||||||
@ -53,16 +53,6 @@ import {
|
|||||||
} from "./test_utils.mjs";
|
} from "./test_utils.mjs";
|
||||||
import { PNG } from "pngjs";
|
import { PNG } from "pngjs";
|
||||||
|
|
||||||
const copyPaste = async page => {
|
|
||||||
let promise = waitForEvent(page, "copy");
|
|
||||||
await kbCopy(page);
|
|
||||||
await promise;
|
|
||||||
|
|
||||||
promise = waitForEvent(page, "paste");
|
|
||||||
await kbPaste(page);
|
|
||||||
await promise;
|
|
||||||
};
|
|
||||||
|
|
||||||
const selectAll = async page => {
|
const selectAll = async page => {
|
||||||
await kbSelectAll(page);
|
await kbSelectAll(page);
|
||||||
await page.waitForFunction(
|
await page.waitForFunction(
|
||||||
@ -187,7 +177,8 @@ describe("FreeText Editor", () => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
await waitForSelectedEditor(page, getEditorSelector(0));
|
await waitForSelectedEditor(page, getEditorSelector(0));
|
||||||
await copyPaste(page);
|
await copy(page);
|
||||||
|
await paste(page);
|
||||||
await page.waitForSelector(getEditorSelector(1), {
|
await page.waitForSelector(getEditorSelector(1), {
|
||||||
visible: true,
|
visible: true,
|
||||||
});
|
});
|
||||||
@ -203,7 +194,8 @@ describe("FreeText Editor", () => {
|
|||||||
|
|
||||||
expect(pastedContent).withContext(`In ${browserName}`).toEqual(content);
|
expect(pastedContent).withContext(`In ${browserName}`).toEqual(content);
|
||||||
|
|
||||||
await copyPaste(page);
|
await copy(page);
|
||||||
|
await paste(page);
|
||||||
await page.waitForSelector(getEditorSelector(2), {
|
await page.waitForSelector(getEditorSelector(2), {
|
||||||
visible: true,
|
visible: true,
|
||||||
});
|
});
|
||||||
@ -263,7 +255,8 @@ describe("FreeText Editor", () => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
await waitForSelectedEditor(page, getEditorSelector(3));
|
await waitForSelectedEditor(page, getEditorSelector(3));
|
||||||
await copyPaste(page);
|
await copy(page);
|
||||||
|
await paste(page);
|
||||||
await page.waitForSelector(getEditorSelector(4), {
|
await page.waitForSelector(getEditorSelector(4), {
|
||||||
visible: true,
|
visible: true,
|
||||||
});
|
});
|
||||||
@ -276,9 +269,7 @@ describe("FreeText Editor", () => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
for (let i = 0; i < 2; i++) {
|
for (let i = 0; i < 2; i++) {
|
||||||
const promise = waitForEvent(page, "paste");
|
await paste(page);
|
||||||
await kbPaste(page);
|
|
||||||
await promise;
|
|
||||||
await page.waitForSelector(getEditorSelector(5 + i));
|
await page.waitForSelector(getEditorSelector(5 + i));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -597,7 +588,8 @@ describe("FreeText Editor", () => {
|
|||||||
.withContext(`In ${browserName}`)
|
.withContext(`In ${browserName}`)
|
||||||
.toEqual([0, 1, 3]);
|
.toEqual([0, 1, 3]);
|
||||||
|
|
||||||
await copyPaste(page);
|
await copy(page);
|
||||||
|
await paste(page);
|
||||||
await page.waitForSelector(getEditorSelector(6), {
|
await page.waitForSelector(getEditorSelector(6), {
|
||||||
visible: true,
|
visible: true,
|
||||||
});
|
});
|
||||||
@ -1275,7 +1267,8 @@ describe("FreeText Editor", () => {
|
|||||||
);
|
);
|
||||||
await waitForSelectedEditor(page, getEditorSelector(1));
|
await waitForSelectedEditor(page, getEditorSelector(1));
|
||||||
|
|
||||||
await copyPaste(page);
|
await copy(page);
|
||||||
|
await paste(page);
|
||||||
await page.waitForSelector(getEditorSelector(6), {
|
await page.waitForSelector(getEditorSelector(6), {
|
||||||
visible: true,
|
visible: true,
|
||||||
});
|
});
|
||||||
@ -3425,14 +3418,11 @@ describe("FreeText Editor", () => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
await select(0);
|
await select(0);
|
||||||
await pasteFromClipboard(
|
await copyToClipboard(page, {
|
||||||
page,
|
"text/html": "<b>Bold Foo</b>",
|
||||||
{
|
"text/plain": "Foo",
|
||||||
"text/html": "<b>Bold Foo</b>",
|
});
|
||||||
"text/plain": "Foo",
|
await pasteFromClipboard(page, `${editorSelector} .internal`);
|
||||||
},
|
|
||||||
`${editorSelector} .internal`
|
|
||||||
);
|
|
||||||
|
|
||||||
let lastText = data;
|
let lastText = data;
|
||||||
|
|
||||||
@ -3442,14 +3432,11 @@ describe("FreeText Editor", () => {
|
|||||||
expect(text).withContext(`In ${browserName}`).toEqual(lastText);
|
expect(text).withContext(`In ${browserName}`).toEqual(lastText);
|
||||||
|
|
||||||
await select(3);
|
await select(3);
|
||||||
await pasteFromClipboard(
|
await copyToClipboard(page, {
|
||||||
page,
|
"text/html": "<b>Bold Bar</b><br><b>Oof</b>",
|
||||||
{
|
"text/plain": "Bar\nOof",
|
||||||
"text/html": "<b>Bold Bar</b><br><b>Oof</b>",
|
});
|
||||||
"text/plain": "Bar\nOof",
|
await pasteFromClipboard(page, `${editorSelector} .internal`);
|
||||||
},
|
|
||||||
`${editorSelector} .internal`
|
|
||||||
);
|
|
||||||
|
|
||||||
await waitForTextChange(lastText, editorSelector);
|
await waitForTextChange(lastText, editorSelector);
|
||||||
text = await getText(editorSelector);
|
text = await getText(editorSelector);
|
||||||
@ -3457,13 +3444,8 @@ describe("FreeText Editor", () => {
|
|||||||
expect(text).withContext(`In ${browserName}`).toEqual(lastText);
|
expect(text).withContext(`In ${browserName}`).toEqual(lastText);
|
||||||
|
|
||||||
await select(0);
|
await select(0);
|
||||||
await pasteFromClipboard(
|
await copyToClipboard(page, { "text/html": "<b>basic html</b>" });
|
||||||
page,
|
await pasteFromClipboard(page, `${editorSelector} .internal`);
|
||||||
{
|
|
||||||
"text/html": "<b>basic html</b>",
|
|
||||||
},
|
|
||||||
`${editorSelector} .internal`
|
|
||||||
);
|
|
||||||
|
|
||||||
// Nothing should change, so it's hard to wait on something.
|
// Nothing should change, so it's hard to wait on something.
|
||||||
// eslint-disable-next-line no-restricted-syntax
|
// eslint-disable-next-line no-restricted-syntax
|
||||||
@ -3477,15 +3459,12 @@ describe("FreeText Editor", () => {
|
|||||||
const prevHTML = await getHTML();
|
const prevHTML = await getHTML();
|
||||||
|
|
||||||
// Try to paste an image.
|
// Try to paste an image.
|
||||||
await pasteFromClipboard(
|
await copyToClipboard(page, {
|
||||||
page,
|
"image/png":
|
||||||
{
|
// 1x1 transparent png.
|
||||||
"image/png":
|
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8z8BQDwAEhQGAhKmMIQAAAABJRU5ErkJggg==",
|
||||||
// 1x1 transparent png.
|
});
|
||||||
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8z8BQDwAEhQGAhKmMIQAAAABJRU5ErkJggg==",
|
await pasteFromClipboard(page, `${editorSelector} .internal`);
|
||||||
},
|
|
||||||
`${editorSelector} .internal`
|
|
||||||
);
|
|
||||||
|
|
||||||
// Nothing should change, so it's hard to wait on something.
|
// Nothing should change, so it's hard to wait on something.
|
||||||
// eslint-disable-next-line no-restricted-syntax
|
// eslint-disable-next-line no-restricted-syntax
|
||||||
@ -3505,14 +3484,11 @@ describe("FreeText Editor", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const fooBar = "Foo\nBar\nOof";
|
const fooBar = "Foo\nBar\nOof";
|
||||||
await pasteFromClipboard(
|
await copyToClipboard(page, {
|
||||||
page,
|
"text/html": "<b>html</b>",
|
||||||
{
|
"text/plain": fooBar,
|
||||||
"text/html": "<b>html</b>",
|
});
|
||||||
"text/plain": fooBar,
|
await pasteFromClipboard(page, `${editorSelector} .internal`);
|
||||||
},
|
|
||||||
`${editorSelector} .internal`
|
|
||||||
);
|
|
||||||
|
|
||||||
await waitForTextChange("", editorSelector);
|
await waitForTextChange("", editorSelector);
|
||||||
text = await getText(editorSelector);
|
text = await getText(editorSelector);
|
||||||
|
|||||||
@ -17,6 +17,8 @@ import {
|
|||||||
applyFunctionToEditor,
|
applyFunctionToEditor,
|
||||||
awaitPromise,
|
awaitPromise,
|
||||||
closePages,
|
closePages,
|
||||||
|
copy,
|
||||||
|
copyToClipboard,
|
||||||
getEditorDimensions,
|
getEditorDimensions,
|
||||||
getEditorSelector,
|
getEditorSelector,
|
||||||
getFirstSerialized,
|
getFirstSerialized,
|
||||||
@ -24,11 +26,10 @@ import {
|
|||||||
getSerialized,
|
getSerialized,
|
||||||
kbBigMoveDown,
|
kbBigMoveDown,
|
||||||
kbBigMoveRight,
|
kbBigMoveRight,
|
||||||
kbCopy,
|
|
||||||
kbPaste,
|
|
||||||
kbSelectAll,
|
kbSelectAll,
|
||||||
kbUndo,
|
kbUndo,
|
||||||
loadAndWait,
|
loadAndWait,
|
||||||
|
paste,
|
||||||
pasteFromClipboard,
|
pasteFromClipboard,
|
||||||
scrollIntoView,
|
scrollIntoView,
|
||||||
serializeBitmapDimensions,
|
serializeBitmapDimensions,
|
||||||
@ -78,12 +79,10 @@ const copyImage = async (page, imagePath, number) => {
|
|||||||
const data = fs
|
const data = fs
|
||||||
.readFileSync(path.join(__dirname, imagePath))
|
.readFileSync(path.join(__dirname, imagePath))
|
||||||
.toString("base64");
|
.toString("base64");
|
||||||
await pasteFromClipboard(
|
|
||||||
page,
|
await copyToClipboard(page, { "image/png": `data:image/png;base64,${data}` });
|
||||||
{ "image/png": `data:image/png;base64,${data}` },
|
await pasteFromClipboard(page);
|
||||||
"",
|
|
||||||
500
|
|
||||||
);
|
|
||||||
await waitForImage(page, getEditorSelector(number));
|
await waitForImage(page, getEditorSelector(number));
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -570,13 +569,13 @@ describe("Stamp Editor", () => {
|
|||||||
await page1.click("#editorStamp");
|
await page1.click("#editorStamp");
|
||||||
|
|
||||||
await copyImage(page1, "../images/firefox_logo.png", 0);
|
await copyImage(page1, "../images/firefox_logo.png", 0);
|
||||||
await kbCopy(page1);
|
await copy(page1);
|
||||||
|
|
||||||
const [, page2] = pages2[i];
|
const [, page2] = pages2[i];
|
||||||
await page2.bringToFront();
|
await page2.bringToFront();
|
||||||
await page2.click("#editorStamp");
|
await page2.click("#editorStamp");
|
||||||
|
|
||||||
await kbPaste(page2);
|
await paste(page2);
|
||||||
|
|
||||||
await waitForImage(page2, getEditorSelector(0));
|
await waitForImage(page2, getEditorSelector(0));
|
||||||
}
|
}
|
||||||
@ -831,8 +830,8 @@ describe("Stamp Editor", () => {
|
|||||||
);
|
);
|
||||||
await page.waitForSelector(`${getEditorSelector(0)} .altText.done`);
|
await page.waitForSelector(`${getEditorSelector(0)} .altText.done`);
|
||||||
|
|
||||||
await kbCopy(page);
|
await copy(page);
|
||||||
await kbPaste(page);
|
await paste(page);
|
||||||
await page.waitForSelector(`${getEditorSelector(1)} .altText.done`);
|
await page.waitForSelector(`${getEditorSelector(1)} .altText.done`);
|
||||||
await waitForSerialized(page, 2);
|
await waitForSerialized(page, 2);
|
||||||
|
|
||||||
|
|||||||
@ -186,13 +186,14 @@ async function getSpanRectFromText(page, pageNumber, text) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function waitForEvent(
|
async function waitForEvent({
|
||||||
page,
|
page,
|
||||||
eventName,
|
eventName,
|
||||||
|
action,
|
||||||
selector = null,
|
selector = null,
|
||||||
validator = null,
|
validator = null,
|
||||||
timeout = 5000
|
timeout = 5000,
|
||||||
) {
|
}) {
|
||||||
const handle = await page.evaluateHandle(
|
const handle = await page.evaluateHandle(
|
||||||
(name, sel, validate, timeOut) => {
|
(name, sel, validate, timeOut) => {
|
||||||
let callback = null,
|
let callback = null,
|
||||||
@ -227,13 +228,15 @@ async function waitForEvent(
|
|||||||
validator ? validator.toString() : null,
|
validator ? validator.toString() : null,
|
||||||
timeout
|
timeout
|
||||||
);
|
);
|
||||||
|
|
||||||
|
await action();
|
||||||
|
|
||||||
const success = await awaitPromise(handle);
|
const success = await awaitPromise(handle);
|
||||||
if (success === null) {
|
if (success === null) {
|
||||||
console.log(`waitForEvent: ${eventName} didn't trigger within the timeout`);
|
console.log(`waitForEvent: ${eventName} didn't trigger within the timeout`);
|
||||||
} else if (!success) {
|
} else if (!success) {
|
||||||
console.log(`waitForEvent: ${eventName} triggered, but validation failed`);
|
console.log(`waitForEvent: ${eventName} triggered, but validation failed`);
|
||||||
}
|
}
|
||||||
return success;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async function waitForStorageEntries(page, nEntries) {
|
async function waitForStorageEntries(page, nEntries) {
|
||||||
@ -292,7 +295,15 @@ async function mockClipboard(pages) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function pasteFromClipboard(page, data, selector, timeout = 100) {
|
async function copy(page) {
|
||||||
|
await waitForEvent({
|
||||||
|
page,
|
||||||
|
eventName: "copy",
|
||||||
|
action: () => kbCopy(page),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async function copyToClipboard(page, data) {
|
||||||
await page.evaluate(async dat => {
|
await page.evaluate(async dat => {
|
||||||
const items = Object.create(null);
|
const items = Object.create(null);
|
||||||
for (const [type, value] of Object.entries(dat)) {
|
for (const [type, value] of Object.entries(dat)) {
|
||||||
@ -305,15 +316,25 @@ async function pasteFromClipboard(page, data, selector, timeout = 100) {
|
|||||||
}
|
}
|
||||||
await navigator.clipboard.write([new ClipboardItem(items)]);
|
await navigator.clipboard.write([new ClipboardItem(items)]);
|
||||||
}, data);
|
}, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function paste(page) {
|
||||||
|
await waitForEvent({
|
||||||
|
page,
|
||||||
|
eventName: "paste",
|
||||||
|
action: () => kbPaste(page),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async function pasteFromClipboard(page, selector = null) {
|
||||||
const validator = e => e.clipboardData.items.length !== 0;
|
const validator = e => e.clipboardData.items.length !== 0;
|
||||||
let hasPasteEvent = false;
|
await waitForEvent({
|
||||||
while (!hasPasteEvent) {
|
page,
|
||||||
// We retry to paste if nothing has been pasted before the timeout.
|
eventName: "paste",
|
||||||
const promise = waitForEvent(page, "paste", selector, validator);
|
action: () => kbPaste(page),
|
||||||
await kbPaste(page);
|
selector,
|
||||||
hasPasteEvent = await promise;
|
validator,
|
||||||
}
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async function getSerialized(page, filter = undefined) {
|
async function getSerialized(page, filter = undefined) {
|
||||||
@ -634,6 +655,8 @@ export {
|
|||||||
clearInput,
|
clearInput,
|
||||||
closePages,
|
closePages,
|
||||||
closeSinglePage,
|
closeSinglePage,
|
||||||
|
copy,
|
||||||
|
copyToClipboard,
|
||||||
createPromise,
|
createPromise,
|
||||||
dragAndDropAnnotation,
|
dragAndDropAnnotation,
|
||||||
firstPageOnTop,
|
firstPageOnTop,
|
||||||
@ -654,7 +677,6 @@ export {
|
|||||||
kbBigMoveLeft,
|
kbBigMoveLeft,
|
||||||
kbBigMoveRight,
|
kbBigMoveRight,
|
||||||
kbBigMoveUp,
|
kbBigMoveUp,
|
||||||
kbCopy,
|
|
||||||
kbDeleteLastWord,
|
kbDeleteLastWord,
|
||||||
kbFocusNext,
|
kbFocusNext,
|
||||||
kbFocusPrevious,
|
kbFocusPrevious,
|
||||||
@ -662,12 +684,12 @@ export {
|
|||||||
kbGoToEnd,
|
kbGoToEnd,
|
||||||
kbModifierDown,
|
kbModifierDown,
|
||||||
kbModifierUp,
|
kbModifierUp,
|
||||||
kbPaste,
|
|
||||||
kbRedo,
|
kbRedo,
|
||||||
kbSelectAll,
|
kbSelectAll,
|
||||||
kbUndo,
|
kbUndo,
|
||||||
loadAndWait,
|
loadAndWait,
|
||||||
mockClipboard,
|
mockClipboard,
|
||||||
|
paste,
|
||||||
pasteFromClipboard,
|
pasteFromClipboard,
|
||||||
scrollIntoView,
|
scrollIntoView,
|
||||||
serializeBitmapDimensions,
|
serializeBitmapDimensions,
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user