From 4380b823103534b1506ac26afafe8a64ef9c2ba0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=BF=A0=20/=20green?= Date: Sat, 2 Dec 2023 23:40:45 +0900 Subject: [PATCH] test: reduce optimize-deps playground flaky fail (#15205) --- .../__tests__/optimize-deps.spec.ts | 147 +++++++++++------- playground/test-utils.ts | 20 +++ 2 files changed, 114 insertions(+), 53 deletions(-) diff --git a/playground/optimize-deps/__tests__/optimize-deps.spec.ts b/playground/optimize-deps/__tests__/optimize-deps.spec.ts index 84988f0933a546..2468a6e9ae2ea9 100644 --- a/playground/optimize-deps/__tests__/optimize-deps.spec.ts +++ b/playground/optimize-deps/__tests__/optimize-deps.spec.ts @@ -2,6 +2,7 @@ import { describe, expect, test } from 'vitest' import { browserErrors, browserLogs, + expectWithRetry, getColor, isBuild, isServe, @@ -12,93 +13,123 @@ import { } from '~utils' test('default + named imports from cjs dep (react)', async () => { - expect(await page.textContent('.cjs button')).toBe('count is 0') + await expectWithRetry(() => page.textContent('.cjs button')).toBe( + 'count is 0', + ) await page.click('.cjs button') - expect(await page.textContent('.cjs button')).toBe('count is 1') + await expectWithRetry(() => page.textContent('.cjs button')).toBe( + 'count is 1', + ) }) test('named imports from webpacked cjs (phoenix)', async () => { - expect(await page.textContent('.cjs-phoenix')).toBe('ok') + await expectWithRetry(() => page.textContent('.cjs-phoenix')).toBe('ok') }) test('default import from webpacked cjs (clipboard)', async () => { - expect(await page.textContent('.cjs-clipboard')).toBe('ok') + await expectWithRetry(() => page.textContent('.cjs-clipboard')).toBe('ok') }) test('dynamic imports from cjs dep (react)', async () => { - expect(await page.textContent('.cjs-dynamic button')).toBe('count is 0') + await expectWithRetry(() => page.textContent('.cjs-dynamic button')).toBe( + 'count is 0', + ) await page.click('.cjs-dynamic button') - expect(await page.textContent('.cjs-dynamic button')).toBe('count is 1') + await expectWithRetry(() => page.textContent('.cjs-dynamic button')).toBe( + 'count is 1', + ) }) test('dynamic named imports from webpacked cjs (phoenix)', async () => { - expect(await page.textContent('.cjs-dynamic-phoenix')).toBe('ok') + await expectWithRetry(() => page.textContent('.cjs-dynamic-phoenix')).toBe( + 'ok', + ) }) test('dynamic default import from webpacked cjs (clipboard)', async () => { - expect(await page.textContent('.cjs-dynamic-clipboard')).toBe('ok') + await expectWithRetry(() => page.textContent('.cjs-dynamic-clipboard')).toBe( + 'ok', + ) }) test('dynamic default import from cjs (cjs-dynamic-dep-cjs-compiled-from-esm)', async () => { - expect(await page.textContent('.cjs-dynamic-dep-cjs-compiled-from-esm')).toBe( - 'ok', - ) + await expectWithRetry(() => + page.textContent('.cjs-dynamic-dep-cjs-compiled-from-esm'), + ).toBe('ok') }) test('dynamic default import from cjs (cjs-dynamic-dep-cjs-compiled-from-cjs)', async () => { - expect(await page.textContent('.cjs-dynamic-dep-cjs-compiled-from-cjs')).toBe( - 'ok', - ) + await expectWithRetry(() => + page.textContent('.cjs-dynamic-dep-cjs-compiled-from-cjs'), + ).toBe('ok') }) test('dedupe', async () => { - expect(await page.textContent('.dedupe button')).toBe('count is 0') + await expectWithRetry(() => page.textContent('.dedupe button')).toBe( + 'count is 0', + ) await page.click('.dedupe button') - expect(await page.textContent('.dedupe button')).toBe('count is 1') + await expectWithRetry(() => page.textContent('.dedupe button')).toBe( + 'count is 1', + ) }) test('cjs browser field (axios)', async () => { - expect(await page.textContent('.cjs-browser-field')).toBe('pong') + await expectWithRetry(() => page.textContent('.cjs-browser-field')).toBe( + 'pong', + ) }) test('cjs browser field bare', async () => { - expect(await page.textContent('.cjs-browser-field-bare')).toBe('pong') + await expectWithRetry(() => page.textContent('.cjs-browser-field-bare')).toBe( + 'pong', + ) }) test('dep from linked dep (lodash-es)', async () => { - expect(await page.textContent('.deps-linked')).toBe('fooBarBaz') + await expectWithRetry(() => page.textContent('.deps-linked')).toBe( + 'fooBarBaz', + ) }) test('forced include', async () => { - expect(await page.textContent('.force-include')).toMatch(`[success]`) + await expectWithRetry(() => page.textContent('.force-include')).toMatch( + `[success]`, + ) }) test('import * from optimized dep', async () => { - expect(await page.textContent('.import-star')).toMatch(`[success]`) + await expectWithRetry(() => page.textContent('.import-star')).toMatch( + `[success]`, + ) }) test('import from dep with process.env.NODE_ENV', async () => { - expect(await page.textContent('.node-env')).toMatch(isBuild ? 'prod' : 'dev') + await expectWithRetry(() => page.textContent('.node-env')).toMatch( + isBuild ? 'prod' : 'dev', + ) }) test('import from dep with .notjs files', async () => { - expect(await page.textContent('.not-js')).toMatch(`[success]`) + await expectWithRetry(() => page.textContent('.not-js')).toMatch(`[success]`) }) test('Import from dependency which uses relative path which needs to be resolved by main field', async () => { - expect(await page.textContent('.relative-to-main')).toMatch(`[success]`) + await expectWithRetry(() => page.textContent('.relative-to-main')).toMatch( + `[success]`, + ) }) test('dep with dynamic import', async () => { - expect(await page.textContent('.dep-with-dynamic-import')).toMatch( - `[success]`, - ) + await expectWithRetry(() => + page.textContent('.dep-with-dynamic-import'), + ).toMatch(`[success]`) }) test('dep with optional peer dep', async () => { - expect(await page.textContent('.dep-with-optional-peer-dep')).toMatch( - `[success]`, - ) + await expectWithRetry(() => + page.textContent('.dep-with-optional-peer-dep'), + ).toMatch(`[success]`) if (isServe) { expect(browserErrors.map((error) => error.message)).toEqual( expect.arrayContaining([ @@ -109,8 +140,8 @@ test('dep with optional peer dep', async () => { }) test('dep with optional peer dep submodule', async () => { - expect( - await page.textContent('.dep-with-optional-peer-dep-submodule'), + expectWithRetry(() => + page.textContent('.dep-with-optional-peer-dep-submodule'), ).toMatch(`[success]`) if (isServe) { expect(browserErrors.map((error) => error.message)).toEqual( @@ -122,61 +153,69 @@ test('dep with optional peer dep submodule', async () => { }) test('dep with css import', async () => { - expect(await getColor('.dep-linked-include')).toBe('red') + await expectWithRetry(() => getColor('.dep-linked-include')).toBe('red') }) test('CJS dep with css import', async () => { - expect(await getColor('.cjs-with-assets')).toBe('blue') + await expectWithRetry(() => getColor('.cjs-with-assets')).toBe('blue') }) test('externalize known non-js files in optimize included dep', async () => { - expect(await page.textContent('.externalize-known-non-js')).toMatch( - `[success]`, - ) + await expectWithRetry(() => + page.textContent('.externalize-known-non-js'), + ).toMatch(`[success]`) }) test('vue + vuex', async () => { - expect(await page.textContent('.vue')).toMatch(`[success]`) + await expectWithRetry(() => page.textContent('.vue')).toMatch(`[success]`) }) // When we use the Rollup CommonJS plugin instead of esbuild prebundling, // the esbuild plugins won't apply to dependencies test('esbuild-plugin', async () => { - expect(await page.textContent('.esbuild-plugin')).toMatch( + await expectWithRetry(() => page.textContent('.esbuild-plugin')).toMatch( `Hello from an esbuild plugin`, ) }) test('import from hidden dir', async () => { - expect(await page.textContent('.hidden-dir')).toBe('hello!') + await expectWithRetry(() => page.textContent('.hidden-dir')).toBe('hello!') }) test('import optimize-excluded package that imports optimized-included package', async () => { - expect(await page.textContent('.nested-include')).toBe('nested-include') + await expectWithRetry(() => page.textContent('.nested-include')).toBe( + 'nested-include', + ) }) test('import aliased package with colon', async () => { - expect(await page.textContent('.url')).toBe('vitejs.dev') + await expectWithRetry(() => page.textContent('.url')).toBe('vitejs.dev') }) test('import aliased package using absolute path', async () => { - expect(await page.textContent('.alias-using-absolute-path')).toBe( - 'From dep-alias-using-absolute-path', - ) + await expectWithRetry(() => + page.textContent('.alias-using-absolute-path'), + ).toBe('From dep-alias-using-absolute-path') }) test('variable names are reused in different scripts', async () => { - expect(await page.textContent('.reused-variable-names')).toBe('reused') + await expectWithRetry(() => page.textContent('.reused-variable-names')).toBe( + 'reused', + ) }) test('flatten id should generate correctly', async () => { - expect(await page.textContent('.clonedeep-slash')).toBe('clonedeep-slash') - expect(await page.textContent('.clonedeep-dot')).toBe('clonedeep-dot') + await expectWithRetry(() => page.textContent('.clonedeep-slash')).toBe( + 'clonedeep-slash', + ) + await expectWithRetry(() => page.textContent('.clonedeep-dot')).toBe( + 'clonedeep-dot', + ) }) test('non optimized module is not duplicated', async () => { - expect( - await page.textContent('.non-optimized-module-is-not-duplicated'), + await expectWithRetry(() => + page.textContent('.non-optimized-module-is-not-duplicated'), ).toBe('from-absolute-path, from-relative-path') }) @@ -227,8 +266,8 @@ test('pre bundle css require', async () => { ) } - expect(await getColor('.css-require')).toBe('red') - expect(await getColor('.css-module-require')).toBe('red') + await expectWithRetry(() => getColor('.css-require')).toBe('red') + await expectWithRetry(() => getColor('.css-module-require')).toBe('red') }) test.runIf(isBuild)('no missing deps during build', async () => { @@ -276,5 +315,7 @@ describe.runIf(isServe)('optimizeDeps config', () => { }) test('long file name should work', async () => { - expect(await page.textContent('.long-file-name')).toMatch(`hello world`) + await expectWithRetry(() => page.textContent('.long-file-name')).toMatch( + `hello world`, + ) }) diff --git a/playground/test-utils.ts b/playground/test-utils.ts index 0e2f54fc7c6298..741a11386078b7 100644 --- a/playground/test-utils.ts +++ b/playground/test-utils.ts @@ -12,6 +12,7 @@ import type { import type { DepOptimizationMetadata, Manifest } from 'vite' import { normalizePath } from 'vite' import { fromComment } from 'convert-source-map' +import type { Assertion } from 'vitest' import { expect } from 'vitest' import type { ExecaChildProcess } from 'execa' import { isBuild, isWindows, page, testDir } from './vitestSetup' @@ -232,6 +233,25 @@ export async function withRetry( await func() } +export const expectWithRetry = (getActual: () => Promise) => { + type A = Assertion + return new Proxy( + {}, + { + get(_target, key) { + return async (...args) => { + await withRetry( + async () => expect(await getActual())[key](...args), + true, + ) + } + }, + }, + ) as { + [K in keyof A]: (...params: Parameters) => Promise> + } +} + type UntilBrowserLogAfterCallback = (logs: string[]) => PromiseLike | void export async function untilBrowserLogAfter(