diff --git a/tests/e2e/client-reconnect.test.js b/tests/e2e/client-reconnect.test.js index 9d58558..f073045 100644 --- a/tests/e2e/client-reconnect.test.js +++ b/tests/e2e/client-reconnect.test.js @@ -4,6 +4,72 @@ const config = require('../fixtures/simple-config/rspack.config'); const runBrowser = require('../helpers/run-browser'); const port = require('../helpers/ports-map')['client-reconnect-option']; +const DISCONNECTED_MESSAGE = 'Disconnected!'; +const RECONNECT_MESSAGE = 'Trying to reconnect...'; +const FAST_RECONNECT_DELAY = 100; + +const delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms)); + +const waitForMessages = async ( + consoleMessages, + predicate, + errorMessage, + timeout = 10000, +) => { + const startedAt = Date.now(); + + while (Date.now() - startedAt < timeout) { + const texts = consoleMessages.map((message) => message.text()); + + if (predicate(texts)) { + return; + } + + await delay(50); + } + + throw new Error(errorMessage); +}; + +const waitForReconnectMessages = (consoleMessages, expectedCount) => + waitForMessages( + consoleMessages, + (texts) => + texts.filter((text) => text.includes(RECONNECT_MESSAGE)).length >= + expectedCount, + `Expected ${expectedCount} reconnect messages.`, + 15000, + ); + +const waitForDisconnectMessage = (consoleMessages) => + waitForMessages( + consoleMessages, + (texts) => texts.some((text) => text.includes(DISCONNECTED_MESSAGE)), + `Expected "${DISCONNECTED_MESSAGE}" message.`, + ); + +const waitForConsoleMessages = (consoleMessages, expectedCount) => + waitForMessages( + consoleMessages, + (texts) => texts.length >= expectedCount, + `Expected ${expectedCount} console messages.`, + ); + +const useFastPageReconnectTimers = async (page) => { + await page.evaluateOnNewDocument((fastReconnectDelay) => { + const originalSetTimeout = window.setTimeout.bind(window); + + window.setTimeout = (handler, timeout, ...args) => + originalSetTimeout( + handler, + typeof timeout === 'number' && timeout >= 1000 + ? fastReconnectDelay + : timeout, + ...args, + ); + }, FAST_RECONNECT_DELAY); +}; + describe('client.reconnect option', () => { describe('specified as true', () => { let compiler; @@ -21,6 +87,7 @@ describe('client.reconnect option', () => { await server.start(); ({ page, browser } = await runBrowser()); + await useFastPageReconnectTimers(page); pageErrors = []; consoleMessages = []; @@ -49,21 +116,7 @@ describe('client.reconnect option', () => { await server.stop(); } - let interval; - - await new Promise((resolve) => { - interval = setInterval(() => { - const retryingMessages = consoleMessages.filter((message) => - message.text().includes('Trying to reconnect...'), - ); - - if (retryingMessages.length >= 5) { - clearInterval(interval); - - resolve(); - } - }, 1000); - }); + await waitForReconnectMessages(consoleMessages, 5); expect(pageErrors).toMatchSnapshot('page errors'); }); @@ -85,6 +138,7 @@ describe('client.reconnect option', () => { await server.start(); ({ page, browser } = await runBrowser()); + await useFastPageReconnectTimers(page); pageErrors = []; consoleMessages = []; @@ -113,16 +167,7 @@ describe('client.reconnect option', () => { await server.stop(); } - // Can't wait to check for unlimited times so wait only for couple retries - await new Promise((resolve) => - setTimeout( - () => { - resolve(); - }, - // eslint-disable-next-line no-restricted-properties - 1000 * 2 ** 3, - ), - ); + await waitForDisconnectMessage(consoleMessages); expect(consoleMessages.map((message) => message.text())).toMatchSnapshot( 'console messages', @@ -148,6 +193,7 @@ describe('client.reconnect option', () => { await server.start(); ({ page, browser } = await runBrowser()); + await useFastPageReconnectTimers(page); pageErrors = []; consoleMessages = []; @@ -176,16 +222,8 @@ describe('client.reconnect option', () => { await server.stop(); } - // Can't wait to check for unlimited times so wait only for couple retries - await new Promise((resolve) => - setTimeout( - () => { - resolve(); - }, - // eslint-disable-next-line no-restricted-properties - 1000 * 2 ** 3, - ), - ); + await waitForReconnectMessages(consoleMessages, 2); + await waitForConsoleMessages(consoleMessages, 10); expect(consoleMessages.map((message) => message.text())).toMatchSnapshot( 'console messages', diff --git a/tests/e2e/overlay.test.js b/tests/e2e/overlay.test.js index 9703586..b817010 100644 --- a/tests/e2e/overlay.test.js +++ b/tests/e2e/overlay.test.js @@ -1,10 +1,12 @@ const path = require('node:path'); const fs = require('node:fs'); +const puppeteer = require('puppeteer'); const { rspack } = require('@rspack/core'); const config = require('../fixtures/overlay-config/rspack.config'); const trustedTypesConfig = require('../fixtures/overlay-config/trusted-types.rspack.config'); const getPort = require('../helpers/get-port'); -const runBrowser = require('../helpers/run-browser'); +const { puppeteerArgs } = require('../helpers/puppeteer-constants'); +const { runPage } = require('../helpers/run-browser'); const basePort = require('../helpers/ports-map').overlay; require('../helpers/normalize'); @@ -63,12 +65,15 @@ class WarningPlugin { } } -const delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms)); +const OVERLAY_SELECTOR = '#rspack-dev-server-client-overlay'; +const OVERLAY_TIMEOUT = 5000; +const OVERLAY_ABSENCE_TIMEOUT = 500; let prettier; let prettierHTML; let prettierCSS; let port; +let sharedBrowser; const overlayFixturePath = path.resolve( __dirname, '../fixtures/overlay-config/foo.js', @@ -111,6 +116,30 @@ const formatOverlayHtml = (html) => (value) => value.replace(/<\/?span[^>]*>/g, ''), ); +const waitForOverlay = (page) => + page.waitForSelector(OVERLAY_SELECTOR, { timeout: OVERLAY_TIMEOUT }); + +const expectNoOverlay = async (page) => { + const overlayHandle = await page + .waitForSelector(OVERLAY_SELECTOR, { timeout: OVERLAY_ABSENCE_TIMEOUT }) + .catch((error) => { + if (error.name === 'TimeoutError') { + return null; + } + + throw error; + }); + + expect(overlayHandle).toBe(null); +}; + +const runBrowser = async () => { + const context = await sharedBrowser.createBrowserContext(); + const page = await runPage(context); + + return { page, browser: context }; +}; + describe('overlay', () => { beforeEach(async () => { port = await getPort(basePort); @@ -121,6 +150,12 @@ describe('overlay', () => { }); beforeAll(async () => { + sharedBrowser = await puppeteer.launch({ + headless: 'new', + acceptInsecureCerts: true, + args: puppeteerArgs, + }); + // Due problems with ESM modules for Node.js@18 // TODO replace it on import/require when Node.js@18 will be dropped prettier = require('../../node_modules/prettier/standalone'); @@ -128,6 +163,10 @@ describe('overlay', () => { prettierCSS = require('../../node_modules/prettier/plugins/postcss'); }); + afterAll(async () => { + await sharedBrowser.close(); + }); + it('should show a warning for initial compilation', async () => { const compiler = rspack(config); @@ -147,8 +186,7 @@ describe('overlay', () => { waitUntil: 'networkidle0', }); - // Delay for the overlay to appear - await delay(1000); + await waitForOverlay(page); const pageHtml = await page.evaluate(() => document.body.outerHTML); const overlayHandle = await page.$('#rspack-dev-server-client-overlay'); @@ -186,8 +224,7 @@ describe('overlay', () => { waitUntil: 'networkidle0', }); - // Delay for the overlay to appear - await delay(1000); + await waitForOverlay(page); const pageHtml = await page.evaluate(() => document.body.outerHTML); const overlayHandle = await page.$('#rspack-dev-server-client-overlay'); @@ -229,8 +266,7 @@ describe('overlay', () => { waitUntil: 'networkidle0', }); - // Delay for the overlay to appear - await delay(1000); + await waitForOverlay(page); const pageHtml = await page.evaluate(() => document.body.outerHTML); const overlayHandle = await page.$('#rspack-dev-server-client-overlay'); @@ -270,8 +306,7 @@ describe('overlay', () => { waitUntil: 'networkidle0', }); - // Delay for the overlay to appear - await delay(1000); + await waitForOverlay(page); const pageHtml = await page.evaluate(() => document.body.outerHTML); const overlayHandle = await page.$('#rspack-dev-server-client-overlay'); @@ -311,8 +346,7 @@ describe('overlay', () => { waitUntil: 'networkidle0', }); - // Delay for the overlay to appear - await delay(1000); + await waitForOverlay(page); const overlayHandle = await page.$('#rspack-dev-server-client-overlay'); const overlayFrame = await overlayHandle.contentFrame(); @@ -347,8 +381,7 @@ describe('overlay', () => { waitUntil: 'networkidle0', }); - // Delay for the overlay to appear - await delay(1000); + await waitForOverlay(page); const pageHtml = await page.evaluate(() => document.body.outerHTML); const overlayHandle = await page.$('#rspack-dev-server-client-overlay'); @@ -673,8 +706,7 @@ describe('overlay', () => { waitUntil: 'networkidle0', }); - // Delay for the overlay to appear - await delay(1000); + await expectNoOverlay(page); const pageHtml = await page.evaluate(() => document.body.outerHTML); const overlayHandle = await page.$('#rspack-dev-server-client-overlay'); @@ -711,8 +743,7 @@ describe('overlay', () => { waitUntil: 'networkidle0', }); - // Delay for the overlay to appear - await delay(1000); + await expectNoOverlay(page); const pageHtml = await page.evaluate(() => document.body.outerHTML); const overlayHandle = await page.$('#rspack-dev-server-client-overlay'); @@ -753,8 +784,7 @@ describe('overlay', () => { waitUntil: 'networkidle0', }); - // Delay for the overlay to appear - await delay(1000); + await expectNoOverlay(page); const overlayHandle = await page.$('#rspack-dev-server-client-overlay'); @@ -791,8 +821,7 @@ describe('overlay', () => { waitUntil: 'networkidle0', }); - // Delay for the overlay to appear - await delay(1000); + await waitForOverlay(page); const pageHtml = await page.evaluate(() => document.body.outerHTML); const overlayHandle = await page.$('#rspack-dev-server-client-overlay'); @@ -833,8 +862,7 @@ describe('overlay', () => { waitUntil: 'networkidle0', }); - // Delay for the overlay to appear - await delay(1000); + await waitForOverlay(page); const pageHtml = await page.evaluate(() => document.body.outerHTML); const overlayHandle = await page.$('#rspack-dev-server-client-overlay'); @@ -877,8 +905,7 @@ describe('overlay', () => { waitUntil: 'networkidle0', }); - // Delay for the overlay to appear - await delay(1000); + await waitForOverlay(page); const pageHtml = await page.evaluate(() => document.body.outerHTML); const overlayHandle = await page.$('#rspack-dev-server-client-overlay'); @@ -921,8 +948,7 @@ describe('overlay', () => { waitUntil: 'networkidle0', }); - // Delay for the overlay to appear - await delay(1000); + await waitForOverlay(page); const pageHtml = await page.evaluate(() => document.body.outerHTML); const overlayHandle = await page.$('#rspack-dev-server-client-overlay'); @@ -963,8 +989,7 @@ describe('overlay', () => { waitUntil: 'networkidle0', }); - // Delay for the overlay to appear - await delay(1000); + await expectNoOverlay(page); const pageHtml = await page.evaluate(() => document.body.outerHTML); const overlayHandle = await page.$('#rspack-dev-server-client-overlay'); @@ -1001,8 +1026,7 @@ describe('overlay', () => { waitUntil: 'networkidle0', }); - // Delay for the overlay to appear - await delay(1000); + await expectNoOverlay(page); const pageHtml = await page.evaluate(() => document.body.outerHTML); const overlayHandle = await page.$('#rspack-dev-server-client-overlay'); @@ -1043,8 +1067,7 @@ describe('overlay', () => { waitUntil: 'networkidle0', }); - // Delay for the overlay to appear - await delay(1000); + await expectNoOverlay(page); const overlayHandle = await page.$('#rspack-dev-server-client-overlay'); @@ -1081,8 +1104,7 @@ describe('overlay', () => { waitUntil: 'networkidle0', }); - // Delay for the overlay to appear - await delay(1000); + await waitForOverlay(page); const pageHtml = await page.evaluate(() => document.body.outerHTML); const overlayHandle = await page.$('#rspack-dev-server-client-overlay'); @@ -1123,8 +1145,7 @@ describe('overlay', () => { waitUntil: 'networkidle0', }); - // Delay for the overlay to appear - await delay(1000); + await waitForOverlay(page); const pageHtml = await page.evaluate(() => document.body.outerHTML); const overlayHandle = await page.$('#rspack-dev-server-client-overlay'); @@ -1173,8 +1194,7 @@ describe('overlay', () => { waitUntil: 'networkidle0', }); - // Delay for the overlay to appear - await delay(1000); + await waitForOverlay(page); const pageHtml = await page.evaluate(() => document.body.outerHTML); const overlayHandle = await page.$('#rspack-dev-server-client-overlay'); @@ -1234,8 +1254,7 @@ describe('overlay', () => { waitUntil: 'networkidle0', }); - // Delay for the overlay to appear - await delay(1000); + await waitForOverlay(page); const pageHtml = await page.evaluate(() => document.body.outerHTML); const overlayHandle = await page.$('#rspack-dev-server-client-overlay'); @@ -1287,8 +1306,7 @@ describe('overlay', () => { waitUntil: 'networkidle0', }); - // Delay for the overlay to appear - await delay(1000); + await expectNoOverlay(page); const pageHtml = await page.evaluate(() => document.body.outerHTML); const overlayHandle = await page.$('#rspack-dev-server-client-overlay'); @@ -1324,8 +1342,7 @@ describe('overlay', () => { waitUntil: 'networkidle0', }); - // Delay for the overlay to appear - await delay(1000); + await waitForOverlay(page); const pageHtml = await page.evaluate(() => document.body.outerHTML); const overlayHandle = await page.$('#rspack-dev-server-client-overlay'); @@ -1368,8 +1385,7 @@ describe('overlay', () => { waitUntil: 'networkidle0', }); - // Delay for the overlay to appear - await delay(1000); + await waitForOverlay(page); const pageHtml = await page.evaluate(() => document.body.outerHTML); const overlayHandle = await page.$('#rspack-dev-server-client-overlay'); @@ -1411,8 +1427,7 @@ describe('overlay', () => { waitUntil: 'networkidle0', }); - // Delay for the overlay to appear - await delay(1000); + await waitForOverlay(page); const pageHtml = await page.evaluate(() => document.body.outerHTML); const overlayHandle = await page.$('#rspack-dev-server-client-overlay'); @@ -1481,10 +1496,7 @@ describe('overlay', () => { }); }); - // Delay for the overlay to appear - await delay(1000); - - await page.waitForSelector('#rspack-dev-server-client-overlay'); + await waitForOverlay(page); const pageHtml = await page.evaluate(() => document.body.outerHTML); const overlayHandle = await page.$('#rspack-dev-server-client-overlay'); @@ -1534,10 +1546,7 @@ describe('overlay', () => { }); }); - // Delay for the overlay to appear - await delay(1000); - - await page.waitForSelector('#rspack-dev-server-client-overlay'); + await waitForOverlay(page); const pageHtml = await page.evaluate(() => document.body.outerHTML); const overlayHandle = await page.$('#rspack-dev-server-client-overlay'); @@ -1581,8 +1590,7 @@ describe('overlay', () => { })();`, }); - // Delay for the overlay to appear - await delay(1000); + await waitForOverlay(page); const overlayHandle = await page.$('#rspack-dev-server-client-overlay'); const overlayFrame = await overlayHandle.contentFrame(); @@ -1629,8 +1637,7 @@ describe('overlay', () => { })();`, }); - // Delay for the overlay to appear - await delay(1000); + await expectNoOverlay(page); const overlayHandle = await page.$('#rspack-dev-server-client-overlay'); @@ -1668,8 +1675,7 @@ describe('overlay', () => { })();`, }); - // Delay for the overlay to appear - await delay(1000); + await waitForOverlay(page); const overlayHandle = await page.$('#rspack-dev-server-client-overlay'); const overlayFrame = await overlayHandle.contentFrame(); @@ -1718,8 +1724,7 @@ describe('overlay', () => { })();`, }); - // Delay for the overlay to appear - await delay(1000); + await expectNoOverlay(page); const overlayHandle = await page.$('#rspack-dev-server-client-overlay'); @@ -1761,8 +1766,7 @@ describe('overlay', () => { waitUntil: 'networkidle0', }); - // Delay for the overlay to appear - await delay(1000); + await waitForOverlay(page); const pageHtml = await page.evaluate(() => document.body.outerHTML); const overlayHandle = await page.$('#rspack-dev-server-client-overlay');