diff --git a/package-lock.json b/package-lock.json index 12de0c4ae..35908f182 100644 --- a/package-lock.json +++ b/package-lock.json @@ -53,7 +53,7 @@ "postcss-discard-comments": "^6.0.1", "postcss-nesting": "^12.0.2", "prettier": "^3.2.5", - "puppeteer": "^21.11.0", + "puppeteer": "^22.0.0", "rimraf": "^3.0.2", "streamqueue": "^1.1.2", "stylelint": "^16.2.1", @@ -2633,9 +2633,9 @@ } }, "node_modules/@puppeteer/browsers": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/@puppeteer/browsers/-/browsers-1.9.1.tgz", - "integrity": "sha512-PuvK6xZzGhKPvlx3fpfdM2kYY3P/hB1URtK8wA7XUJ6prn6pp22zvJHu48th0SGcHL9SutbPHrFuQgfXTFobWA==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@puppeteer/browsers/-/browsers-2.0.0.tgz", + "integrity": "sha512-3PS82/5+tnpEaUWonjAFFvlf35QHF15xqyGd34GBa5oP5EPVfFXRsbSxIGYf1M+vZlqBZ3oxT1kRg9OYhtt8ng==", "dev": true, "dependencies": { "debug": "4.3.4", @@ -2650,7 +2650,7 @@ "browsers": "lib/cjs/main-cli.js" }, "engines": { - "node": ">=16.3.0" + "node": ">=18" } }, "node_modules/@puppeteer/browsers/node_modules/debug": { @@ -13371,7 +13371,6 @@ }, "node_modules/npm/node_modules/lodash._baseindexof": { "version": "3.1.0", - "extraneous": true, "inBundle": true, "license": "MIT" }, @@ -13387,19 +13386,16 @@ }, "node_modules/npm/node_modules/lodash._bindcallback": { "version": "3.0.1", - "extraneous": true, "inBundle": true, "license": "MIT" }, "node_modules/npm/node_modules/lodash._cacheindexof": { "version": "3.0.2", - "extraneous": true, "inBundle": true, "license": "MIT" }, "node_modules/npm/node_modules/lodash._createcache": { "version": "3.1.2", - "extraneous": true, "inBundle": true, "license": "MIT", "dependencies": { @@ -13414,7 +13410,6 @@ }, "node_modules/npm/node_modules/lodash._getnative": { "version": "3.9.1", - "extraneous": true, "inBundle": true, "license": "MIT" }, @@ -13432,7 +13427,6 @@ }, "node_modules/npm/node_modules/lodash.restparam": { "version": "3.6.1", - "extraneous": true, "inBundle": true, "license": "MIT" }, @@ -17006,30 +17000,30 @@ } }, "node_modules/puppeteer": { - "version": "21.11.0", - "resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-21.11.0.tgz", - "integrity": "sha512-9jTHuYe22TD3sNxy0nEIzC7ZrlRnDgeX3xPkbS7PnbdwYjl2o/z/YuCrRBwezdKpbTDTJ4VqIggzNyeRcKq3cg==", + "version": "22.0.0", + "resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-22.0.0.tgz", + "integrity": "sha512-zYVnjwJngnSB4dbkWp7DHFSIc3nqHvZzrdHyo9+ugV1nq1Lm8obOMcmCFaGfR3PJs0EmYNz+/skBeO45yvASCQ==", "dev": true, "hasInstallScript": true, "dependencies": { - "@puppeteer/browsers": "1.9.1", + "@puppeteer/browsers": "2.0.0", "cosmiconfig": "9.0.0", - "puppeteer-core": "21.11.0" + "puppeteer-core": "22.0.0" }, "bin": { "puppeteer": "lib/esm/puppeteer/node/cli.js" }, "engines": { - "node": ">=16.13.2" + "node": ">=18" } }, "node_modules/puppeteer-core": { - "version": "21.11.0", - "resolved": "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-21.11.0.tgz", - "integrity": "sha512-ArbnyA3U5SGHokEvkfWjW+O8hOxV1RSJxOgriX/3A4xZRqixt9ZFHD0yPgZQF05Qj0oAqi8H/7stDorjoHY90Q==", + "version": "22.0.0", + "resolved": "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-22.0.0.tgz", + "integrity": "sha512-S3s91rLde0A86PWVeNY82h+P0fdS7CTiNWAicCVH/bIspRP4nS2PnO5j+VTFqCah0ZJizGzpVPAmxVYbLxTc9w==", "dev": true, "dependencies": { - "@puppeteer/browsers": "1.9.1", + "@puppeteer/browsers": "2.0.0", "chromium-bidi": "0.5.8", "cross-fetch": "4.0.0", "debug": "4.3.4", @@ -17037,7 +17031,7 @@ "ws": "8.16.0" }, "engines": { - "node": ">=16.13.2" + "node": ">=18" } }, "node_modules/puppeteer-core/node_modules/debug": { diff --git a/package.json b/package.json index 35e6afcce..ef68adcc7 100644 --- a/package.json +++ b/package.json @@ -47,7 +47,7 @@ "postcss-discard-comments": "^6.0.1", "postcss-nesting": "^12.0.2", "prettier": "^3.2.5", - "puppeteer": "^21.11.0", + "puppeteer": "^22.0.0", "rimraf": "^3.0.2", "streamqueue": "^1.1.2", "stylelint": "^16.2.1", diff --git a/test/integration/annotation_spec.mjs b/test/integration/annotation_spec.mjs index 7c35b1e6e..4b5ad229c 100644 --- a/test/integration/annotation_spec.mjs +++ b/test/integration/annotation_spec.mjs @@ -18,6 +18,7 @@ import { getQuerySelector, getSelector, loadAndWait, + waitForTimeout, } from "./test_utils.mjs"; describe("Annotation highlight", () => { @@ -140,7 +141,7 @@ describe("Checkbox annotation", () => { ); for (const selector of selectors) { await page.click(selector); - page.waitForTimeout(10); + await waitForTimeout(10); } for (const selector of selectors) { await page.waitForFunction( @@ -199,7 +200,7 @@ describe("Text widget", () => { pages.map(async ([browserName, page]) => { await page.type(getSelector("22R"), "a"); await page.keyboard.press("Tab"); - await page.waitForTimeout(10); + await waitForTimeout(10); const text = await page.$eval(getSelector("22R"), el => el.value); expect(text).withContext(`In ${browserName}`).toEqual("aHello World"); @@ -485,12 +486,12 @@ describe("ResetForm action", () => { `document.querySelector("[data-annotation-id='25R']").hidden === false` ); await page.click("#editorFreeText"); - await page.waitForTimeout(10); + await waitForTimeout(10); await page.waitForFunction( `document.querySelector("[data-annotation-id='25R']").hidden === true` ); await page.click("#editorFreeText"); - await page.waitForTimeout(10); + await waitForTimeout(10); await page.waitForFunction( `document.querySelector("[data-annotation-id='25R']").hidden === false` ); @@ -553,7 +554,7 @@ describe("ResetForm action", () => { expect(hidden).withContext(`In ${browserName}`).toEqual(true); await page.focus("[data-annotation-id='20R']"); await page.keyboard.press("Enter"); - await page.waitForTimeout(10); + await waitForTimeout(10); hidden = await page.$eval( "[data-annotation-id='21R']", el => el.hidden @@ -561,7 +562,7 @@ describe("ResetForm action", () => { expect(hidden).withContext(`In ${browserName}`).toEqual(false); await page.keyboard.press("Enter"); - await page.waitForTimeout(10); + await waitForTimeout(10); hidden = await page.$eval( "[data-annotation-id='21R']", el => el.hidden @@ -569,7 +570,7 @@ describe("ResetForm action", () => { expect(hidden).withContext(`In ${browserName}`).toEqual(true); await page.keyboard.press("Enter"); - await page.waitForTimeout(10); + await waitForTimeout(10); hidden = await page.$eval( "[data-annotation-id='21R']", el => el.hidden @@ -577,7 +578,7 @@ describe("ResetForm action", () => { expect(hidden).withContext(`In ${browserName}`).toEqual(false); await page.keyboard.press("Escape"); - await page.waitForTimeout(10); + await waitForTimeout(10); hidden = await page.$eval( "[data-annotation-id='21R']", el => el.hidden diff --git a/test/integration/freetext_editor_spec.mjs b/test/integration/freetext_editor_spec.mjs index 499d32011..f3cff4cea 100644 --- a/test/integration/freetext_editor_spec.mjs +++ b/test/integration/freetext_editor_spec.mjs @@ -43,6 +43,7 @@ import { waitForSelectedEditor, waitForSerialized, waitForStorageEntries, + waitForTimeout, waitForUnselectedEditor, } from "./test_utils.mjs"; import { PNG } from "pngjs"; @@ -52,7 +53,7 @@ const copyPaste = async page => { await kbCopy(page); await promise; - await page.waitForTimeout(10); + await waitForTimeout(10); promise = waitForEvent(page, "paste"); await kbPaste(page); @@ -1137,7 +1138,7 @@ describe("FreeText Editor", () => { await kbUndo(page); // Nothing should happen, it's why we can't wait for something // specific! - await page.waitForTimeout(200); + await waitForTimeout(200); // We check that the editor hasn't been removed. editorIds = await getEditors(page, "freeText"); @@ -1343,7 +1344,7 @@ describe("FreeText Editor", () => { // Enter in editing mode. await switchToFreeText(page); - await page.waitForTimeout(200); + await waitForTimeout(200); // Disable editing mode. await page.click("#editorFreeText"); @@ -2373,7 +2374,7 @@ describe("FreeText Editor", () => { // The editor must be moved in the DOM and potentially the focus // will be lost, hence there's a callback will get back the focus. - await page.waitForTimeout(200); + await waitForTimeout(200); const focused = await page.evaluate(sel => { const editor = document.querySelector(sel); diff --git a/test/integration/scripting_spec.mjs b/test/integration/scripting_spec.mjs index daa572920..5f29be1ef 100644 --- a/test/integration/scripting_spec.mjs +++ b/test/integration/scripting_spec.mjs @@ -27,6 +27,7 @@ import { loadAndWait, scrollIntoView, waitForEntryInStorage, + waitForTimeout, } from "./test_utils.mjs"; describe("Interaction", () => { @@ -1711,7 +1712,7 @@ describe("Interaction", () => { await clearInput(page, getSelector("27R")); await page.type(getSelector("27R"), exportValue); await page.click("[data-annotation-id='28R']"); - await page.waitForTimeout(10); + await waitForTimeout(10); value = await page.$eval(getSelector("24R"), el => el.value); expect(value).withContext(`In ${browserName}`).toEqual(exportValue); @@ -1758,7 +1759,7 @@ describe("Interaction", () => { await page.waitForFunction( `${getQuerySelector("30R")}.value !== "abc"` ); - await page.waitForTimeout(100); + await waitForTimeout(100); const focusedId = await page.evaluate(_ => window.document.activeElement.getAttribute("data-element-id") @@ -1854,7 +1855,7 @@ describe("Interaction", () => { expect(text).withContext(`In ${browserName}`).toEqual("00000000123"); await page.click(getSelector("26R")); - await page.waitForTimeout(10); + await waitForTimeout(10); text = await page.$eval(getSelector("25R"), el => el.value); expect(text).withContext(`In ${browserName}`).toEqual("00000000123"); @@ -1888,13 +1889,13 @@ describe("Interaction", () => { expect(text).withContext(`In ${browserName}`).toEqual("5,25"); await page.click(getSelector("22R")); - await page.waitForTimeout(10); + await waitForTimeout(10); text = await page.$eval(getSelector("22R"), el => el.value); expect(text).withContext(`In ${browserName}`).toEqual("5,25"); await page.click(getSelector("31R")); - await page.waitForTimeout(10); + await waitForTimeout(10); text = await page.$eval(getSelector("31R"), el => el.value); expect(text).withContext(`In ${browserName}`).toEqual("5.25"); @@ -1925,7 +1926,7 @@ describe("Interaction", () => { expect(text).withContext(`In ${browserName}`).toEqual(""); await page.select(getSelector("6R"), "Yes"); - await page.waitForTimeout(10); + await waitForTimeout(10); text = await page.$eval(getSelector("44R"), el => el.value); expect(text).withContext(`In ${browserName}`).toEqual("Yes"); @@ -1933,7 +1934,7 @@ describe("Interaction", () => { await clearInput(page, getSelector("44R")); await page.select(getSelector("6R"), "No"); - await page.waitForTimeout(10); + await waitForTimeout(10); text = await page.$eval(getSelector("44R"), el => el.value); expect(text).withContext(`In ${browserName}`).toEqual("No"); @@ -1990,14 +1991,14 @@ describe("Interaction", () => { await page.type(getSelector("26R"), "abcde", { delay: 10 }); await page.click(getSelector("23R")); - await page.waitForTimeout(10); + await waitForTimeout(10); await page.click(getSelector("26R")); await kbSelectAll(page); await page.keyboard.press("Backspace"); await page.click(getSelector("23R")); - await page.waitForTimeout(10); + await waitForTimeout(10); text = await page.$eval(getSelector("26R"), el => el.value); expect(text).withContext(`In ${browserName}`).toEqual(""); @@ -2093,7 +2094,7 @@ describe("Interaction", () => { expect(visibility).withContext(`In ${browserName}`).toEqual("hidden"); await page.click(getSelector("11R")); - await page.waitForTimeout(10); + await waitForTimeout(10); visibility = await page.$eval( getSelector("7R"), @@ -2139,28 +2140,28 @@ describe("Interaction", () => { ); expect(readonly).withContext(`In ${browserName}`).toEqual(true); await page.click(getSelector("334R")); - await page.waitForTimeout(10); + await waitForTimeout(10); readonly = await page.$eval(getSelector("353R"), el => el.disabled); expect(readonly).withContext(`In ${browserName}`).toEqual(true); await page.click(getSelector("351R")); - await page.waitForTimeout(10); + await waitForTimeout(10); readonly = await page.$eval(getSelector("353R"), el => el.disabled); expect(readonly).withContext(`In ${browserName}`).toEqual(true); await page.click(getSelector("352R")); - await page.waitForTimeout(10); + await waitForTimeout(10); readonly = await page.$eval(getSelector("353R"), el => el.disabled); expect(readonly).withContext(`In ${browserName}`).toEqual(false); await page.click(getSelector("353R")); - await page.waitForTimeout(10); + await waitForTimeout(10); let checked = await page.$eval(getSelector("353R"), el => el.checked); expect(checked).withContext(`In ${browserName}`).toEqual(true); await page.click(getSelector("334R")); - await page.waitForTimeout(10); + await waitForTimeout(10); readonly = await page.$eval(getSelector("353R"), el => el.disabled); expect(readonly).withContext(`In ${browserName}`).toEqual(true); @@ -2199,16 +2200,16 @@ describe("Interaction", () => { await page.click(getSelector("55R")); await page.type(getSelector("55R"), "Hello", { delay: 10 }); await page.click(getSelector("56R")); - await page.waitForTimeout(10); + await waitForTimeout(10); await page.click(getSelector("55R")); await page.type(getSelector("55R"), " World", { delay: 10 }); - await page.waitForTimeout(10); + await waitForTimeout(10); await otherPages[i].bringToFront(); - await otherPages[i].waitForTimeout(100); + await waitForTimeout(100); await page.bringToFront(); - await page.waitForTimeout(100); + await waitForTimeout(100); const text = await page.$eval(getSelector("55R"), el => el.value); expect(text).withContext(`In ${browserName}`).toEqual("Hello World"); @@ -2243,7 +2244,7 @@ describe("Interaction", () => { ); await page.click(getSelector("25R")); - await page.waitForTimeout(10); + await waitForTimeout(10); await page.click(getSelector("26R")); await page.waitForFunction( diff --git a/test/integration/test_utils.mjs b/test/integration/test_utils.mjs index 4705a2f49..037b547a1 100644 --- a/test/integration/test_utils.mjs +++ b/test/integration/test_utils.mjs @@ -85,11 +85,27 @@ function closePages(pages) { ); } +function waitForTimeout(milliseconds) { + /** + * Wait for the given number of milliseconds. + * + * Note that waiting for an arbitrary time in tests is discouraged because it + * can easily cause intermittent failures, which is why this functionality is + * no longer provided by Puppeteer 22+ and we have to implement it ourselves + * for the remaining callers in the integration tests. We should avoid + * creating new usages of this function; instead please refer to the better + * alternatives at https://github.com/puppeteer/puppeteer/pull/11780. + */ + return new Promise(resolve => { + setTimeout(resolve, milliseconds); + }); +} + async function clearInput(page, selector) { await page.click(selector); await kbSelectAll(page); await page.keyboard.press("Backspace"); - await page.waitForTimeout(10); + await waitForTimeout(10); } function getSelector(id) { @@ -276,7 +292,7 @@ async function serializeBitmapDimensions(page) { async function dragAndDropAnnotation(page, startX, startY, tX, tY) { await page.mouse.move(startX, startY); await page.mouse.down(); - await page.waitForTimeout(10); + await waitForTimeout(10); await page.mouse.move(startX + tX, startY + tY); await page.mouse.up(); await page.waitForSelector("#viewer:not(.noUserSelect)"); @@ -487,5 +503,6 @@ export { waitForSerialized, waitForStorageEntries, waitForTextLayer, + waitForTimeout, waitForUnselectedEditor, }; diff --git a/test/test.mjs b/test/test.mjs index 26405e6fc..8928546d4 100644 --- a/test/test.mjs +++ b/test/test.mjs @@ -892,9 +892,7 @@ async function startBrowser({ browserName, headless, startUrl }) { const options = { product: browserName, protocol: "cdp", - // Note that using `headless: true` gives a deprecation warning; see - // https://github.com/puppeteer/puppeteer#default-runtime-settings. - headless: headless === true ? "new" : false, + headless, defaultViewport: null, ignoreDefaultArgs: ["--disable-extensions"], // The timeout for individual protocol (CDP) calls should always be lower