diff --git a/e2e/cases/alias/legacy-alias/index.test.ts b/e2e/cases/alias/legacy-alias/index.test.ts index ebe703478d..06b8aefc47 100644 --- a/e2e/cases/alias/legacy-alias/index.test.ts +++ b/e2e/cases/alias/legacy-alias/index.test.ts @@ -1,8 +1,7 @@ -import { build, proxyConsole } from '@e2e/helper'; +import { build } from '@e2e/helper'; import { expect, test } from '@playwright/test'; test('should allow to use the legacy `source.alias` config', async () => { - const { logs, restore } = proxyConsole(); const rsbuild = await build({ cwd: __dirname, }); @@ -20,7 +19,9 @@ test('should allow to use the legacy `source.alias` config', async () => { expect(files[nodeIndex!]).toContain('for node target'); expect( - logs.some((log) => log.includes('"source.alias" config is deprecated')), + rsbuild.logs.some((log) => + log.includes('"source.alias" config is deprecated'), + ), ).toBeTruthy(); - restore(); + await rsbuild.close(); }); diff --git a/e2e/cases/config/inspect-config/debug.test.ts b/e2e/cases/config/inspect-config/debug.test.ts index 78ce5fa640..fe277744e2 100644 --- a/e2e/cases/config/inspect-config/debug.test.ts +++ b/e2e/cases/config/inspect-config/debug.test.ts @@ -1,6 +1,6 @@ import fs from 'node:fs'; import path from 'node:path'; -import { build, dev, gotoPage, proxyConsole } from '@e2e/helper'; +import { build, dev, gotoPage } from '@e2e/helper'; import { expect, test } from '@playwright/test'; import { logger } from '@rsbuild/core'; @@ -14,13 +14,12 @@ const getBundlerConfig = (dist: string) => ); test('should generate config files when build (with DEBUG)', async () => { - process.env.DEBUG = 'rsbuild'; + const { level } = logger; logger.level = 'verbose'; + process.env.DEBUG = 'rsbuild'; const distRoot = 'dist-1'; - const { logs, restore } = proxyConsole(); - - await build({ + const { logs, close } = await build({ cwd: __dirname, rsbuildConfig: { output: { @@ -42,18 +41,16 @@ test('should generate config files when build (with DEBUG)', async () => { expect(logs.some((log) => log.includes('create compiler'))).toBeTruthy(); delete process.env.DEBUG; - logger.level = 'log'; - - restore(); + logger.level = level; + await close(); }); test('should generate config files when dev (with DEBUG)', async ({ page }) => { + const { level } = logger; process.env.DEBUG = 'rsbuild'; logger.level = 'verbose'; const distRoot = 'dist-2'; - const { logs, restore } = proxyConsole(); - const rsbuild = await dev({ cwd: __dirname, rsbuildConfig: { @@ -74,15 +71,14 @@ test('should generate config files when dev (with DEBUG)', async ({ page }) => { expect(fs.existsSync(getBundlerConfig(distRoot))).toBeTruthy(); expect( - logs.some((log) => log.includes('config inspection completed')), + rsbuild.logs.some((log) => log.includes('config inspection completed')), ).toBeTruthy(); - expect(logs.some((log) => log.includes('create compiler'))).toBeTruthy(); + expect( + rsbuild.logs.some((log) => log.includes('create compiler')), + ).toBeTruthy(); delete process.env.DEBUG; - logger.level = 'log'; - + logger.level = level; await rsbuild.close(); - - restore(); }); diff --git a/e2e/cases/config/rspack-config-validate/index.test.ts b/e2e/cases/config/rspack-config-validate/index.test.ts index ead03aeb0f..64f0727426 100644 --- a/e2e/cases/config/rspack-config-validate/index.test.ts +++ b/e2e/cases/config/rspack-config-validate/index.test.ts @@ -1,5 +1,5 @@ import { stripVTControlCharacters as stripAnsi } from 'node:util'; -import { build, proxyConsole, rspackOnlyTest } from '@e2e/helper'; +import { build, rspackOnlyTest } from '@e2e/helper'; import { expect } from '@playwright/test'; import { pluginReact } from '@rsbuild/plugin-react'; @@ -23,8 +23,7 @@ rspackOnlyTest('should validate Rspack config by default', async () => { }); rspackOnlyTest('should warn when passing unrecognized keys', async () => { - const { logs, restore } = proxyConsole(); - await build({ + const rsbuild = await build({ cwd: __dirname, rsbuildConfig: { tools: { @@ -37,20 +36,18 @@ rspackOnlyTest('should warn when passing unrecognized keys', async () => { }); expect( - logs.some((log) => + rsbuild.logs.some((log) => log.includes(`Unrecognized key(s) in object: 'unrecognized'`), ), ); - restore(); + await rsbuild.close(); }); rspackOnlyTest('should allow to override Rspack config validate', async () => { const { RSPACK_CONFIG_VALIDATE } = process.env; process.env.RSPACK_CONFIG_VALIDATE = 'loose'; - const { logs, restore } = proxyConsole(); - - await build({ + const rsbuild = await build({ cwd: __dirname, rsbuildConfig: { tools: { @@ -62,10 +59,14 @@ rspackOnlyTest('should allow to override Rspack config validate', async () => { }, }); - expect(logs.some((log) => log.includes('Expected object, received number'))); + expect( + rsbuild.logs.some((log) => + log.includes('Expected object, received number'), + ), + ); process.env.RSPACK_CONFIG_VALIDATE = RSPACK_CONFIG_VALIDATE; - restore(); + await rsbuild.close(); }); rspackOnlyTest( diff --git a/e2e/cases/config/stats-module-trace/index.test.ts b/e2e/cases/config/stats-module-trace/index.test.ts index 33946d40c2..f182d85003 100644 --- a/e2e/cases/config/stats-module-trace/index.test.ts +++ b/e2e/cases/config/stats-module-trace/index.test.ts @@ -1,17 +1,15 @@ -import { build, proxyConsole } from '@e2e/helper'; +import { build } from '@e2e/helper'; import { expect, test } from '@playwright/test'; test('should log error module trace', async () => { - const { restore, logs } = proxyConsole(); - - await expect( - build({ - cwd: __dirname, - rsbuildConfig: {}, - }), - ).rejects.toThrowError('build failed'); - - expect(logs.some((log) => log.includes('@ ./src/index.tsx'))).toBeTruthy(); - - restore(); + const rsbuild = await build({ + cwd: __dirname, + catchBuildError: true, + }); + + expect(rsbuild.buildError).toBeTruthy(); + expect( + rsbuild.logs.some((log) => log.includes('@ ./src/index.tsx')), + ).toBeTruthy(); + await rsbuild.close(); }); diff --git a/e2e/cases/config/stats-options/index.test.ts b/e2e/cases/config/stats-options/index.test.ts index 198dec8be4..a6a4b15d03 100644 --- a/e2e/cases/config/stats-options/index.test.ts +++ b/e2e/cases/config/stats-options/index.test.ts @@ -1,27 +1,22 @@ -import { build, proxyConsole } from '@e2e/helper'; +import { build } from '@e2e/helper'; import { expect, test } from '@playwright/test'; test('should log warning by default', async () => { - const { restore, logs } = proxyConsole(); - - await build({ + const rsbuild = await build({ cwd: __dirname, - rsbuildConfig: {}, }); expect( - logs.some((log) => + rsbuild.logs.some((log) => log.includes('Using / for division outside of calc() is deprecated'), ), ).toBeTruthy(); - restore(); + await rsbuild.close(); }); test('should not log warning when set stats.warnings false', async () => { - const { restore, logs } = proxyConsole(); - - await build({ + const rsbuild = await build({ cwd: __dirname, rsbuildConfig: { tools: { @@ -35,10 +30,10 @@ test('should not log warning when set stats.warnings false', async () => { }); expect( - logs.some((log) => + rsbuild.logs.some((log) => log.includes('Using / for division outside of calc() is deprecated'), ), ).toBeFalsy(); - restore(); + await rsbuild.close(); }); diff --git a/e2e/cases/css/enable-experiments-css/index.test.ts b/e2e/cases/css/enable-experiments-css/index.test.ts index b4d5377279..191957d234 100644 --- a/e2e/cases/css/enable-experiments-css/index.test.ts +++ b/e2e/cases/css/enable-experiments-css/index.test.ts @@ -1,9 +1,7 @@ -import { build, proxyConsole, rspackOnlyTest } from '@e2e/helper'; +import { build, rspackOnlyTest } from '@e2e/helper'; import { expect } from '@playwright/test'; rspackOnlyTest('should allow to enable Rspack experiments.css', async () => { - const { logs, restore } = proxyConsole(); - const rsbuild = await build({ cwd: __dirname, }); @@ -13,16 +11,16 @@ rspackOnlyTest('should allow to enable Rspack experiments.css', async () => { expect(content).toEqual('body{color:red}'); // should have no warnings - expect(logs.some((log) => log.includes('Compile Warning'))).toBeFalsy(); + expect( + rsbuild.logs.some((log) => log.includes('Compile Warning')), + ).toBeFalsy(); - restore(); + await rsbuild.close(); }); rspackOnlyTest( 'should allow to enable Rspack experiments.css with style-loader', async () => { - const { logs, restore } = proxyConsole(); - const rsbuild = await build({ cwd: __dirname, rsbuildConfig: { @@ -38,8 +36,10 @@ rspackOnlyTest( expect(content).toContain('color:red'); // should have no warnings - expect(logs.some((log) => log.includes('Compile Warning'))).toBeFalsy(); + expect( + rsbuild.logs.some((log) => log.includes('Compile Warning')), + ).toBeFalsy(); - restore(); + await rsbuild.close(); }, ); diff --git a/e2e/cases/css/import-common-css/index.test.ts b/e2e/cases/css/import-common-css/index.test.ts index 79aaad74c2..d51da54ed8 100644 --- a/e2e/cases/css/import-common-css/index.test.ts +++ b/e2e/cases/css/import-common-css/index.test.ts @@ -1,9 +1,7 @@ -import { build, proxyConsole, rspackOnlyTest } from '@e2e/helper'; +import { build, rspackOnlyTest } from '@e2e/helper'; import { expect } from '@playwright/test'; rspackOnlyTest('should compile common CSS import correctly', async () => { - const { restore, logs } = proxyConsole(); - const rsbuild = await build({ cwd: __dirname, rsbuildConfig: { @@ -20,12 +18,14 @@ rspackOnlyTest('should compile common CSS import correctly', async () => { // there will be a deprecation log for `~`. expect( - logs.some((log) => log.includes(`a request starts with '~' is deprecated`)), + rsbuild.logs.some((log) => + log.includes(`a request starts with '~' is deprecated`), + ), ); expect(files[cssFiles]).toEqual( 'html{min-height:100%}#a{color:red}#b{color:#00f}', ); - restore(); + await rsbuild.close(); }); diff --git a/e2e/cases/css/nested-npm-import/index.test.ts b/e2e/cases/css/nested-npm-import/index.test.ts index 297f4524d2..acb87defe3 100644 --- a/e2e/cases/css/nested-npm-import/index.test.ts +++ b/e2e/cases/css/nested-npm-import/index.test.ts @@ -1,11 +1,9 @@ import fs from 'node:fs'; import path from 'node:path'; -import { build, proxyConsole, rspackOnlyTest } from '@e2e/helper'; +import { build, rspackOnlyTest } from '@e2e/helper'; import { expect } from '@playwright/test'; rspackOnlyTest('should compile nested npm import correctly', async () => { - const { restore, logs } = proxyConsole(); - fs.cpSync( path.resolve(__dirname, '_node_modules'), path.resolve(__dirname, 'node_modules'), @@ -25,8 +23,10 @@ rspackOnlyTest('should compile nested npm import correctly', async () => { // there will be a deprecation log for `~`. expect( - logs.some((log) => log.includes(`a request starts with '~' is deprecated`)), + rsbuild.logs.some((log) => + log.includes(`a request starts with '~' is deprecated`), + ), ); - restore(); + await rsbuild.close(); }); diff --git a/e2e/cases/css/resolve-ts-paths/index.test.ts b/e2e/cases/css/resolve-ts-paths/index.test.ts index d2b99f5778..176495e1f1 100644 --- a/e2e/cases/css/resolve-ts-paths/index.test.ts +++ b/e2e/cases/css/resolve-ts-paths/index.test.ts @@ -1,20 +1,16 @@ -import { build, proxyConsole, rspackOnlyTest } from '@e2e/helper'; +import { build, rspackOnlyTest } from '@e2e/helper'; import { expect } from '@playwright/test'; rspackOnlyTest('should resolve ts paths correctly in SCSS file', async () => { - const { restore } = proxyConsole(); - try { - const rsbuild = await build({ - cwd: __dirname, - }); + const rsbuild = await build({ + cwd: __dirname, + }); - const files = await rsbuild.getDistFiles(); + const files = await rsbuild.getDistFiles(); - const content = - files[Object.keys(files).find((file) => file.endsWith('.css'))!]; + const content = + files[Object.keys(files).find((file) => file.endsWith('.css'))!]; - expect(content).toContain('background-image:url(/static/image/icon'); - } finally { - restore(); - } + expect(content).toContain('background-image:url(/static/image/icon'); + await rsbuild.close(); }); diff --git a/e2e/cases/javascript-api/custom-logger/index.test.ts b/e2e/cases/javascript-api/custom-logger/index.test.ts index 77f4db5274..c4b536d754 100644 --- a/e2e/cases/javascript-api/custom-logger/index.test.ts +++ b/e2e/cases/javascript-api/custom-logger/index.test.ts @@ -1,14 +1,13 @@ -import { build, proxyConsole, rspackOnlyTest } from '@e2e/helper'; +import { build, rspackOnlyTest } from '@e2e/helper'; import { expect } from '@playwright/test'; rspackOnlyTest('should allow to customize logger', async () => { - const { logs, restore } = proxyConsole('log'); - - await build({ + const rsbuild = await build({ cwd: __dirname, }); - expect(logs.find((item) => item.includes('[READY] built in'))).toBeTruthy(); - - restore(); + expect( + rsbuild.logs.find((item) => item.includes('[READY] built in')), + ).toBeTruthy(); + await rsbuild.close(); }); diff --git a/e2e/cases/lazy-compilation/basic/index.test.ts b/e2e/cases/lazy-compilation/basic/index.test.ts index fa1dc730fe..69c860dd55 100644 --- a/e2e/cases/lazy-compilation/basic/index.test.ts +++ b/e2e/cases/lazy-compilation/basic/index.test.ts @@ -1,4 +1,4 @@ -import { dev, expectPoll, gotoPage, proxyConsole } from '@e2e/helper'; +import { dev, expectPoll, gotoPage } from '@e2e/helper'; import { expect, test } from '@playwright/test'; // TODO: failed to run this case after updating playwright @@ -11,7 +11,6 @@ test.skip('should render pages correctly when using lazy compilation', async ({ test.skip(); } - const { logs, restore } = proxyConsole(); const rsbuild = await dev({ cwd: __dirname, }); @@ -19,18 +18,17 @@ test.skip('should render pages correctly when using lazy compilation', async ({ await gotoPage(page, rsbuild, 'page1'); await expect(page.locator('#test')).toHaveText('Page 1'); await expectPoll(() => - logs.some((log) => log.includes('building src/page1/index.js')), + rsbuild.logs.some((log) => log.includes('building src/page1/index.js')), ).toBeTruthy(); expect( - logs.some((log) => log.includes('building src/page2/index.js')), + rsbuild.logs.some((log) => log.includes('building src/page2/index.js')), ).toBeFalsy(); await gotoPage(page, rsbuild, 'page2'); await expect(page.locator('#test')).toHaveText('Page 2'); await expectPoll(() => - logs.some((log) => log.includes('building src/page2/index.js')), + rsbuild.logs.some((log) => log.includes('building src/page2/index.js')), ).toBeTruthy(); await rsbuild.close(); - restore(); }); diff --git a/e2e/cases/lazy-compilation/dynamic-import/index.test.ts b/e2e/cases/lazy-compilation/dynamic-import/index.test.ts index 81db40e16f..59e85064fd 100644 --- a/e2e/cases/lazy-compilation/dynamic-import/index.test.ts +++ b/e2e/cases/lazy-compilation/dynamic-import/index.test.ts @@ -1,4 +1,4 @@ -import { dev, expectPoll, gotoPage, proxyConsole } from '@e2e/helper'; +import { dev, expectPoll, gotoPage } from '@e2e/helper'; import { expect, test } from '@playwright/test'; // TODO: failed to run this case after updating playwright @@ -9,21 +9,21 @@ test.skip('should lazy compile dynamic imported modules', async ({ page }) => { test.skip(); } - const { logs, restore } = proxyConsole(); const rsbuild = await dev({ cwd: __dirname, }); await expectPoll(() => - logs.some((log) => log.includes('built in ')), + rsbuild.logs.some((log) => log.includes('built in ')), ).toBeTruthy(); - expect(logs.some((log) => log.includes('building src/foo.js'))).toBeFalsy(); + expect( + rsbuild.logs.some((log) => log.includes('building src/foo.js')), + ).toBeFalsy(); await gotoPage(page, rsbuild, 'index'); await expectPoll(() => - logs.some((log) => log.includes('building src/foo.js')), + rsbuild.logs.some((log) => log.includes('building src/foo.js')), ).toBeTruthy(); await rsbuild.close(); - restore(); }); diff --git a/e2e/cases/lazy-compilation/port-placeholder/index.test.ts b/e2e/cases/lazy-compilation/port-placeholder/index.test.ts index ea0c52b6e1..2c60c760b2 100644 --- a/e2e/cases/lazy-compilation/port-placeholder/index.test.ts +++ b/e2e/cases/lazy-compilation/port-placeholder/index.test.ts @@ -1,4 +1,4 @@ -import { dev, expectPoll, gotoPage, proxyConsole } from '@e2e/helper'; +import { dev, expectPoll, gotoPage } from '@e2e/helper'; import { expect, test } from '@playwright/test'; // TODO: failed to run this case after updating playwright @@ -11,7 +11,6 @@ test.skip('should replace port placeholder with actual port', async ({ test.skip(); } - const { logs, restore } = proxyConsole(); const rsbuild = await dev({ cwd: __dirname, }); @@ -19,18 +18,17 @@ test.skip('should replace port placeholder with actual port', async ({ await gotoPage(page, rsbuild, 'page1'); await expect(page.locator('#test')).toHaveText('Page 1'); await expectPoll(() => - logs.some((log) => log.includes('building src/page1/index.js')), + rsbuild.logs.some((log) => log.includes('building src/page1/index.js')), ).toBeTruthy(); expect( - logs.some((log) => log.includes('building src/page2/index.js')), + rsbuild.logs.some((log) => log.includes('building src/page2/index.js')), ).toBeFalsy(); await gotoPage(page, rsbuild, 'page2'); await expect(page.locator('#test')).toHaveText('Page 2'); await expectPoll(() => - logs.some((log) => log.includes('building src/page2/index.js')), + rsbuild.logs.some((log) => log.includes('building src/page2/index.js')), ).toBeTruthy(); await rsbuild.close(); - restore(); }); diff --git a/e2e/cases/module/exports-presence/index.test.ts b/e2e/cases/module/exports-presence/index.test.ts index 2bc0f09d4a..a2eab29348 100644 --- a/e2e/cases/module/exports-presence/index.test.ts +++ b/e2e/cases/module/exports-presence/index.test.ts @@ -1,20 +1,18 @@ -import { build, proxyConsole } from '@e2e/helper'; +import { build } from '@e2e/helper'; import { expect, test } from '@playwright/test'; test('should throw error by default (exportsPresence error)', async () => { - const { logs, restore } = proxyConsole(); - - await expect( - build({ - cwd: __dirname, - }), - ).rejects.toThrowError(); - - restore(); + const rsbuild = await build({ + cwd: __dirname, + catchBuildError: true, + }); + expect(rsbuild.buildError).toBeTruthy(); expect( - logs.find((log) => + rsbuild.logs.find((log) => log.includes(`export 'aa' (imported as 'aa') was not found in './test'`), ), ).toBeTruthy(); + + await rsbuild.close(); }); diff --git a/e2e/cases/node-polyfill-tip/with-protocol/index.test.ts b/e2e/cases/node-polyfill-tip/with-protocol/index.test.ts index 606aa1e73d..b0f6607a83 100644 --- a/e2e/cases/node-polyfill-tip/with-protocol/index.test.ts +++ b/e2e/cases/node-polyfill-tip/with-protocol/index.test.ts @@ -1,19 +1,20 @@ -import { build, proxyConsole } from '@e2e/helper'; +import { build } from '@e2e/helper'; import { expect, test } from '@playwright/test'; test('should print tips if resolve Node.js builtin module failed', async () => { - const { logs, restore } = proxyConsole(); + const rsbuild = await build({ + cwd: __dirname, + catchBuildError: true, + }); - try { - await build({ cwd: __dirname }); - } catch {} - - restore(); + expect(rsbuild.buildError).toBeTruthy(); expect( - logs.some((log) => + rsbuild.logs.some((log) => log.includes( '"querystring" is a built-in Node.js module and cannot be imported in client-side code.', ), ), ); + + await rsbuild.close(); }); diff --git a/e2e/cases/node-polyfill-tip/without-protocol/index.test.ts b/e2e/cases/node-polyfill-tip/without-protocol/index.test.ts index 606aa1e73d..b0f6607a83 100644 --- a/e2e/cases/node-polyfill-tip/without-protocol/index.test.ts +++ b/e2e/cases/node-polyfill-tip/without-protocol/index.test.ts @@ -1,19 +1,20 @@ -import { build, proxyConsole } from '@e2e/helper'; +import { build } from '@e2e/helper'; import { expect, test } from '@playwright/test'; test('should print tips if resolve Node.js builtin module failed', async () => { - const { logs, restore } = proxyConsole(); + const rsbuild = await build({ + cwd: __dirname, + catchBuildError: true, + }); - try { - await build({ cwd: __dirname }); - } catch {} - - restore(); + expect(rsbuild.buildError).toBeTruthy(); expect( - logs.some((log) => + rsbuild.logs.some((log) => log.includes( '"querystring" is a built-in Node.js module and cannot be imported in client-side code.', ), ), ); + + await rsbuild.close(); }); diff --git a/e2e/cases/output/clean-dist-path/index.test.ts b/e2e/cases/output/clean-dist-path/index.test.ts index b9f6e68bfe..e04e8864a5 100644 --- a/e2e/cases/output/clean-dist-path/index.test.ts +++ b/e2e/cases/output/clean-dist-path/index.test.ts @@ -1,6 +1,6 @@ import fs from 'node:fs'; import { join } from 'node:path'; -import { build, dev, proxyConsole } from '@e2e/helper'; +import { build, dev } from '@e2e/helper'; import { expect, test } from '@playwright/test'; import fse, { remove } from 'fs-extra'; @@ -50,11 +50,10 @@ test('should clean dist path in dev mode when writeToDisk is true', async () => }); test('should not clean dist path if it is outside root', async () => { - const { logs, restore } = proxyConsole(); const testOutsideFile = join(cwd, '../node_modules/test.json'); await fse.outputFile(testOutsideFile, `{ "test": 1 }`); - await build({ + const rsbuild = await build({ cwd, rsbuildConfig: { output: { @@ -66,13 +65,15 @@ test('should not clean dist path if it is outside root', async () => { }); expect( - logs.find((log) => log.includes('dist path is not a subdir of root path')), + rsbuild.logs.find((log) => + log.includes('dist path is not a subdir of root path'), + ), ).toBeTruthy(); expect(fs.existsSync(testOutsideFile)).toBeTruthy(); await remove(testOutsideFile); - restore(); + await rsbuild.close(); }); test('should allow to disable cleanDistPath', async () => { diff --git a/e2e/cases/performance/bundle-analyzer/index.test.ts b/e2e/cases/performance/bundle-analyzer/index.test.ts index a462e6c7e5..d285fd978b 100644 --- a/e2e/cases/performance/bundle-analyzer/index.test.ts +++ b/e2e/cases/performance/bundle-analyzer/index.test.ts @@ -1,12 +1,10 @@ import { join } from 'node:path'; -import { build, dev, proxyConsole, readDirContents } from '@e2e/helper'; +import { build, dev, readDirContents } from '@e2e/helper'; import { expect, test } from '@playwright/test'; test('should emit bundle analyze report correctly when dev', async ({ page, }) => { - const { logs, restore } = proxyConsole(); - const rsbuild = await dev({ cwd: __dirname, }); @@ -22,17 +20,14 @@ test('should emit bundle analyze report correctly when dev', async ({ expect(filePaths.length).toBe(1); expect( - logs.some((log) => log.includes('Webpack Bundle Analyzer saved report to')), + rsbuild.logs.some((log) => + log.includes('Webpack Bundle Analyzer saved report to'), + ), ).toBeTruthy(); - await rsbuild.close(); - - restore(); }); test('should emit bundle analyze report correctly when build', async () => { - const { logs, restore } = proxyConsole(); - const rsbuild = await build({ cwd: __dirname, }); @@ -43,10 +38,11 @@ test('should emit bundle analyze report correctly when build', async () => { ); expect( - logs.some((log) => log.includes('Webpack Bundle Analyzer saved report to')), + rsbuild.logs.some((log) => + log.includes('Webpack Bundle Analyzer saved report to'), + ), ).toBeTruthy(); expect(filePaths.length).toBe(1); - - restore(); + await rsbuild.close(); }); diff --git a/e2e/cases/plugin-api/plugin-transform-error-handle/index.test.ts b/e2e/cases/plugin-api/plugin-transform-error-handle/index.test.ts index 5a93e461c2..eaeaf22115 100644 --- a/e2e/cases/plugin-api/plugin-transform-error-handle/index.test.ts +++ b/e2e/cases/plugin-api/plugin-transform-error-handle/index.test.ts @@ -1,17 +1,15 @@ -import { dev, expectPoll, proxyConsole, rspackOnlyTest } from '@e2e/helper'; +import { dev, expectPoll, rspackOnlyTest } from '@e2e/helper'; rspackOnlyTest('should handle transform error in dev mode', async () => { - const { logs, restore } = proxyConsole(); const rsbuild = await dev({ cwd: __dirname, }); await expectPoll(() => - logs.some( + rsbuild.logs.some( (log) => log.includes('transform error') && log.includes('Build error'), ), ).toBeTruthy(); - restore(); await rsbuild.close(); }); diff --git a/e2e/cases/plugin-less/plugin-hints/index.test.ts b/e2e/cases/plugin-less/plugin-hints/index.test.ts index 50a22caffb..743704002f 100644 --- a/e2e/cases/plugin-less/plugin-hints/index.test.ts +++ b/e2e/cases/plugin-less/plugin-hints/index.test.ts @@ -1,20 +1,18 @@ -import { build, proxyConsole, rspackOnlyTest } from '@e2e/helper'; +import { build, rspackOnlyTest } from '@e2e/helper'; import { expect } from '@playwright/test'; rspackOnlyTest('should print Less plugin hints as expected', async () => { - const { logs, restore } = proxyConsole(); - - await expect( - build({ - cwd: __dirname, - }), - ).rejects.toThrowError('build failed'); + const rsbuild = await build({ + cwd: __dirname, + catchBuildError: true, + }); + expect(rsbuild.buildError).toBeTruthy(); expect( - logs.some((log) => + rsbuild.logs.some((log) => log.includes('To enable support for Less, use "@rsbuild/plugin-less"'), ), ).toBeTruthy(); - restore(); + await rsbuild.close(); }); diff --git a/e2e/cases/plugin-sass/plugin-hints/index.test.ts b/e2e/cases/plugin-sass/plugin-hints/index.test.ts index 93fb5ffe3b..d96afe3cc0 100644 --- a/e2e/cases/plugin-sass/plugin-hints/index.test.ts +++ b/e2e/cases/plugin-sass/plugin-hints/index.test.ts @@ -1,20 +1,18 @@ -import { build, proxyConsole, rspackOnlyTest } from '@e2e/helper'; +import { build, rspackOnlyTest } from '@e2e/helper'; import { expect } from '@playwright/test'; rspackOnlyTest('should print Sass plugin hints as expected', async () => { - const { logs, restore } = proxyConsole(); - - await expect( - build({ - cwd: __dirname, - }), - ).rejects.toThrowError('build failed'); + const rsbuild = await build({ + cwd: __dirname, + catchBuildError: true, + }); + expect(rsbuild.buildError).toBeTruthy(); expect( - logs.some((log) => + rsbuild.logs.some((log) => log.includes('To enable support for Sass, use "@rsbuild/plugin-sass"'), ), ).toBeTruthy(); - restore(); + await rsbuild.close(); }); diff --git a/e2e/cases/plugin-stylus/plugin-hints/index.test.ts b/e2e/cases/plugin-stylus/plugin-hints/index.test.ts index 80b4479e94..6e79480c8c 100644 --- a/e2e/cases/plugin-stylus/plugin-hints/index.test.ts +++ b/e2e/cases/plugin-stylus/plugin-hints/index.test.ts @@ -1,22 +1,20 @@ -import { build, proxyConsole, rspackOnlyTest } from '@e2e/helper'; +import { build, rspackOnlyTest } from '@e2e/helper'; import { expect } from '@playwright/test'; rspackOnlyTest('should print Stylus plugin hints as expected', async () => { - const { logs, restore } = proxyConsole(); - - await expect( - build({ - cwd: __dirname, - }), - ).rejects.toThrowError('build failed'); + const rsbuild = await build({ + cwd: __dirname, + catchBuildError: true, + }); + expect(rsbuild.buildError).toBeTruthy(); expect( - logs.some((log) => + rsbuild.logs.some((log) => log.includes( 'To enable support for Stylus, use "@rsbuild/plugin-stylus"', ), ), ).toBeTruthy(); - restore(); + await rsbuild.close(); }); diff --git a/e2e/cases/print-file-size/basic/index.test.ts b/e2e/cases/print-file-size/basic/index.test.ts index f61c437e3e..f80f485706 100644 --- a/e2e/cases/print-file-size/basic/index.test.ts +++ b/e2e/cases/print-file-size/basic/index.test.ts @@ -1,4 +1,4 @@ -import { build, proxyConsole } from '@e2e/helper'; +import { build } from '@e2e/helper'; import { expect, test } from '@playwright/test'; const cwd = __dirname; @@ -37,21 +37,8 @@ function extractFileSizeLogs(logs: string[]) { } test.describe('should print file size correctly', async () => { - let logs: string[]; - let restore: () => void; - - test.beforeEach(() => { - const result = proxyConsole(); - logs = result.logs; - restore = result.restore; - }); - - test.afterEach(() => { - restore(); - }); - test('printFileSize: true should work', async () => { - await build({ + const rsbuild = await build({ cwd, rsbuildConfig: { performance: { @@ -60,7 +47,7 @@ test.describe('should print file size correctly', async () => { }, }); - expect(extractFileSizeLogs(logs)).toEqual(` + expect(extractFileSizeLogs(rsbuild.logs)).toEqual(` File (web) Size Gzip dist/static/css/index.[[hash]].css X.X kB X.X kB dist/index.html X.X kB X.X kB @@ -68,10 +55,12 @@ dist/static/js/index.[[hash]].js X.X kB X.X kB dist/static/image/icon.[[hash]].png X.X kB dist/static/js/lib-react.[[hash]].js X.X kB X.X kB Total: X.X kB X.X kB`); + + await rsbuild.close(); }); test('should print size of multiple environments correctly', async () => { - await build({ + const rsbuild = await build({ cwd, rsbuildConfig: { output: { @@ -98,7 +87,7 @@ dist/static/js/lib-react.[[hash]].js X.X kB X.X kB }, }); - expect(extractFileSizeLogs(logs)).toEqual(` + expect(extractFileSizeLogs(rsbuild.logs)).toEqual(` File (node) Size dist/server/static/image/icon.png X.X kB dist/server/index.js X.X kB @@ -110,10 +99,12 @@ dist/static/js/index.js X.X kB X.X kB dist/static/image/icon.png X.X kB dist/static/js/lib-react.js X.X kB X.X kB Total: X.X kB X.X kB`); + + await rsbuild.close(); }); test('printFileSize: false should not print logs', async () => { - await build({ + const rsbuild = await build({ cwd, rsbuildConfig: { performance: { @@ -122,11 +113,13 @@ dist/static/js/lib-react.js X.X kB X.X kB }, }); - expect(extractFileSizeLogs(logs)).toEqual(''); + expect(extractFileSizeLogs(rsbuild.logs)).toEqual(''); + + await rsbuild.close(); }); test('printFileSize.detail: false should work', async () => { - await build({ + const rsbuild = await build({ cwd, rsbuildConfig: { performance: { @@ -137,12 +130,14 @@ dist/static/js/lib-react.js X.X kB X.X kB }, }); - expect(extractFileSizeLogs(logs)).toEqual(` + expect(extractFileSizeLogs(rsbuild.logs)).toEqual(` Total size (web): X.X kB (X.X kB gzipped)`); + + await rsbuild.close(); }); test('printFileSize.total: false should work', async () => { - await build({ + const rsbuild = await build({ cwd, rsbuildConfig: { performance: { @@ -153,17 +148,19 @@ Total size (web): X.X kB (X.X kB gzipped)`); }, }); - expect(extractFileSizeLogs(logs)).toEqual(` + expect(extractFileSizeLogs(rsbuild.logs)).toEqual(` File (web) Size Gzip dist/static/css/index.[[hash]].css X.X kB X.X kB dist/index.html X.X kB X.X kB dist/static/js/index.[[hash]].js X.X kB X.X kB dist/static/image/icon.[[hash]].png X.X kB dist/static/js/lib-react.[[hash]].js X.X kB X.X kB`); + + await rsbuild.close(); }); test('should print dist folder correctly if it is not a subdir of root', async () => { - await build({ + const rsbuild = await build({ cwd, rsbuildConfig: { performance: { @@ -177,7 +174,7 @@ dist/static/js/lib-react.[[hash]].js X.X kB X.X kB`); }, }); - expect(extractFileSizeLogs(logs)).toEqual(` + expect(extractFileSizeLogs(rsbuild.logs)).toEqual(` File (web) Size Gzip ../test-temp-folder/dist/static/css/index.[[hash]].css X.X kB X.X kB ../test-temp-folder/dist/index.html X.X kB X.X kB @@ -185,10 +182,12 @@ File (web) Size Gzip ../test-temp-folder/dist/static/image/icon.[[hash]].png X.X kB ../test-temp-folder/dist/static/js/lib-react.[[hash]].js X.X kB X.X kB Total: X.X kB X.X kB`); + + await rsbuild.close(); }); test('should allow to disable gzip-compressed size', async () => { - await build({ + const rsbuild = await build({ cwd, rsbuildConfig: { performance: { @@ -199,7 +198,7 @@ File (web) Size Gzip }, }); - expect(extractFileSizeLogs(logs)).toEqual(` + expect(extractFileSizeLogs(rsbuild.logs)).toEqual(` File (web) Size dist/static/css/index.[[hash]].css X.X kB dist/index.html X.X kB @@ -207,10 +206,12 @@ dist/static/js/index.[[hash]].js X.X kB dist/static/image/icon.[[hash]].png X.X kB dist/static/js/lib-react.[[hash]].js X.X kB Total: X.X kB`); + + await rsbuild.close(); }); test('should allow to filter assets by name', async () => { - await build({ + const rsbuild = await build({ cwd, rsbuildConfig: { performance: { @@ -221,15 +222,17 @@ dist/static/js/lib-react.[[hash]].js X.X kB }, }); - expect(extractFileSizeLogs(logs)).toEqual(` + expect(extractFileSizeLogs(rsbuild.logs)).toEqual(` File (web) Size Gzip dist/static/js/index.[[hash]].js X.X kB X.X kB dist/static/js/lib-react.[[hash]].js X.X kB X.X kB Total: X.X kB X.X kB`); + + await rsbuild.close(); }); test('should allow to filter assets by size', async () => { - await build({ + const rsbuild = await build({ cwd, rsbuildConfig: { performance: { @@ -240,13 +243,15 @@ dist/static/js/lib-react.[[hash]].js X.X kB X.X kB }, }); - expect(extractFileSizeLogs(logs)).toEqual(` + expect(extractFileSizeLogs(rsbuild.logs)).toEqual(` File (web) Size Gzip dist/static/js/lib-react.[[hash]].js X.X kB X.X kB`); + + await rsbuild.close(); }); test('should allow to custom exclude function', async () => { - await build({ + const rsbuild = await build({ cwd, rsbuildConfig: { performance: { @@ -259,17 +264,19 @@ dist/static/js/lib-react.[[hash]].js X.X kB X.X kB`); }, }); - expect(extractFileSizeLogs(logs)).toEqual(` + expect(extractFileSizeLogs(rsbuild.logs)).toEqual(` File (web) Size Gzip dist/static/css/index.[[hash]].css X.X kB X.X kB dist/static/js/index.[[hash]].js X.X kB X.X kB dist/static/image/icon.[[hash]].png X.X kB dist/static/js/lib-react.[[hash]].js X.X kB X.X kB Total: X.X kB X.X kB`); + + await rsbuild.close(); }); test('should not calculate gzip size if the asset is not compressible', async () => { - await build({ + const rsbuild = await build({ cwd, rsbuildConfig: { performance: { @@ -278,7 +285,7 @@ dist/static/js/lib-react.[[hash]].js X.X kB X.X kB }, }); - expect(extractFileSizeLogs(logs)).toEqual(` + expect(extractFileSizeLogs(rsbuild.logs)).toEqual(` File (web) Size Gzip dist/static/css/index.[[hash]].css X.X kB X.X kB dist/index.html X.X kB X.X kB @@ -286,5 +293,7 @@ dist/static/js/index.[[hash]].js X.X kB X.X kB dist/static/image/icon.[[hash]].png X.X kB dist/static/js/lib-react.[[hash]].js X.X kB X.X kB Total: X.X kB X.X kB`); + + await rsbuild.close(); }); }); diff --git a/e2e/cases/print-file-size/with-error/index.test.ts b/e2e/cases/print-file-size/with-error/index.test.ts index 23bfdc4123..2173d5d352 100644 --- a/e2e/cases/print-file-size/with-error/index.test.ts +++ b/e2e/cases/print-file-size/with-error/index.test.ts @@ -1,24 +1,21 @@ -import { build, proxyConsole } from '@e2e/helper'; +import { build } from '@e2e/helper'; import { expect, test } from '@playwright/test'; const cwd = __dirname; test('should not print file size if has errors', async () => { - const { logs, restore } = proxyConsole(); - - try { - await build({ - cwd, - rsbuildConfig: { - performance: { - printFileSize: true, - }, + const rsbuild = await build({ + cwd, + catchBuildError: true, + rsbuildConfig: { + performance: { + printFileSize: true, }, - }); - } catch (err) { - expect(err).toBeTruthy(); - } + }, + }); + + expect(rsbuild.buildError).toBeTruthy(); + expect(rsbuild.logs.some((log) => log.includes('Total:'))).toBeFalsy(); - expect(logs.some((log) => log.includes('Total:'))).toBeFalsy(); - restore(); + await rsbuild.close(); }); diff --git a/e2e/cases/server/base-url/index.test.ts b/e2e/cases/server/base-url/index.test.ts index 3b2e144853..c6027cee88 100644 --- a/e2e/cases/server/base-url/index.test.ts +++ b/e2e/cases/server/base-url/index.test.ts @@ -1,9 +1,7 @@ -import { build, dev, proxyConsole } from '@e2e/helper'; +import { build, dev } from '@e2e/helper'; import { expect, test } from '@playwright/test'; test('server.base when dev', async ({ page }) => { - const { logs, restore } = proxyConsole('log'); - const rsbuild = await dev({ cwd: __dirname, page, @@ -21,7 +19,7 @@ test('server.base when dev', async ({ page }) => { expect(page.url().includes('/base/')).toBeTruthy(); // should print url with base path - const baseUrlLog = logs.find( + const baseUrlLog = rsbuild.logs.find( (log) => log.includes('Local:') && log.includes(`localhost:${rsbuild.port}/base`), ); @@ -45,7 +43,6 @@ test('server.base when dev', async ({ page }) => { expect(await page.content()).toContain('aaaa'); - restore(); await rsbuild.close(); }); @@ -75,8 +72,6 @@ test('server.base with dev.assetPrefix: true', async ({ page }) => { }); test('server.base when build & preview', async ({ page }) => { - const { logs, restore } = proxyConsole('log'); - const rsbuild = await build({ cwd: __dirname, page, @@ -94,7 +89,7 @@ test('server.base when build & preview', async ({ page }) => { expect(page.url().includes('/base/')).toBeTruthy(); // should print url with base path - const baseUrlLog = logs.find( + const baseUrlLog = rsbuild.logs.find( (log) => log.includes('Local:') && log.includes(`localhost:${rsbuild.port}/base`), ); @@ -118,7 +113,6 @@ test('server.base when build & preview', async ({ page }) => { expect(await page.content()).toContain('aaaa'); - restore(); await rsbuild.close(); }); diff --git a/e2e/cases/server/hmr-logs/index.test.ts b/e2e/cases/server/hmr-logs/index.test.ts index 90aadf1cd7..88a3d6139a 100644 --- a/e2e/cases/server/hmr-logs/index.test.ts +++ b/e2e/cases/server/hmr-logs/index.test.ts @@ -1,6 +1,6 @@ import fs from 'node:fs'; import { join } from 'node:path'; -import { dev, expectPoll, proxyConsole, rspackOnlyTest } from '@e2e/helper'; +import { dev, expectPoll, rspackOnlyTest } from '@e2e/helper'; import { expect, test } from '@playwright/test'; const cwd = __dirname; @@ -14,8 +14,6 @@ rspackOnlyTest('should print changed files in logs', async ({ page }) => { recursive: true, }); - const { logs, restore } = proxyConsole(); - const rsbuild = await dev({ cwd, page, @@ -41,11 +39,10 @@ rspackOnlyTest('should print changed files in logs', async ({ page }) => { ); await expectPoll(() => - logs.some((log) => log.includes('building test-temp-src/App.tsx')), + rsbuild.logs.some((log) => log.includes('building test-temp-src/App.tsx')), ).toBeTruthy(); await rsbuild.close(); - restore(); }); rspackOnlyTest('should print removed files in logs', async ({ page }) => { @@ -57,8 +54,6 @@ rspackOnlyTest('should print removed files in logs', async ({ page }) => { recursive: true, }); - const { logs, restore } = proxyConsole(); - const rsbuild = await dev({ cwd, page, @@ -79,9 +74,10 @@ rspackOnlyTest('should print removed files in logs', async ({ page }) => { await fs.promises.unlink(appPath); await expectPoll(() => - logs.some((log) => log.includes('building removed test-temp-src/App.tsx')), + rsbuild.logs.some((log) => + log.includes('building removed test-temp-src/App.tsx'), + ), ).toBeTruthy(); await rsbuild.close(); - restore(); }); diff --git a/e2e/cases/server/hmr-with-error/index.test.ts b/e2e/cases/server/hmr-with-error/index.test.ts index b845b51aa1..9beae56d5a 100644 --- a/e2e/cases/server/hmr-with-error/index.test.ts +++ b/e2e/cases/server/hmr-with-error/index.test.ts @@ -1,6 +1,6 @@ import fs from 'node:fs'; import { join } from 'node:path'; -import { dev, expectPoll, proxyConsole, rspackOnlyTest } from '@e2e/helper'; +import { dev, expectPoll, rspackOnlyTest } from '@e2e/helper'; import { expect, test } from '@playwright/test'; const cwd = __dirname; @@ -16,8 +16,6 @@ rspackOnlyTest( recursive: true, }); - const { logs, restore } = proxyConsole(); - const rsbuild = await dev({ cwd, page, @@ -46,7 +44,7 @@ rspackOnlyTest( ); await expectPoll(() => - logs.some((log) => log.includes('Module build failed')), + rsbuild.logs.some((log) => log.includes('Module build failed')), ).toBeTruthy(); await fs.promises.writeFile( @@ -61,7 +59,5 @@ rspackOnlyTest( await expect(locator).toHaveText('Hello Rsbuild2!'); await rsbuild.close(); - - restore(); }, ); diff --git a/e2e/cases/server/overlay-type-errors/index.test.ts b/e2e/cases/server/overlay-type-errors/index.test.ts index 08b68ea2b4..9e8b4b1263 100644 --- a/e2e/cases/server/overlay-type-errors/index.test.ts +++ b/e2e/cases/server/overlay-type-errors/index.test.ts @@ -1,11 +1,9 @@ -import { dev, expectPoll, proxyConsole } from '@e2e/helper'; +import { dev, expectPoll } from '@e2e/helper'; import { expect, test } from '@playwright/test'; const cwd = __dirname; test('should display type errors on overlay correctly', async ({ page }) => { - const { restore } = proxyConsole(); - const logs: string[] = []; page.on('console', (consoleMessage) => { logs.push(consoleMessage.text()); @@ -38,6 +36,4 @@ test('should display type errors on overlay correctly', async ({ page }) => { ).toBeTruthy(); await rsbuild.close(); - - restore(); }); diff --git a/e2e/cases/server/overlay/index.test.ts b/e2e/cases/server/overlay/index.test.ts index a2cbd8b1cc..3a683b68e7 100644 --- a/e2e/cases/server/overlay/index.test.ts +++ b/e2e/cases/server/overlay/index.test.ts @@ -1,6 +1,6 @@ import fs from 'node:fs'; import { join } from 'node:path'; -import { dev, expectPoll, proxyConsole } from '@e2e/helper'; +import { dev, expectPoll } from '@e2e/helper'; import { expect, test } from '@playwright/test'; const cwd = __dirname; @@ -11,8 +11,6 @@ test('should show overlay correctly', async ({ page }) => { test.skip(); } - const { restore } = proxyConsole(); - await fs.promises.cp(join(cwd, 'src'), join(cwd, 'test-temp-src'), { recursive: true, }); @@ -56,6 +54,4 @@ test('should show overlay correctly', async ({ page }) => { await expect(errorOverlay.locator('.title')).toHaveText('Build failed'); await rsbuild.close(); - - restore(); }); diff --git a/e2e/cases/server/print-urls/index.test.ts b/e2e/cases/server/print-urls/index.test.ts index 716d51e81c..87ff64275d 100644 --- a/e2e/cases/server/print-urls/index.test.ts +++ b/e2e/cases/server/print-urls/index.test.ts @@ -1,4 +1,4 @@ -import { build, dev, proxyConsole } from '@e2e/helper'; +import { build, dev } from '@e2e/helper'; import { expect, test } from '@playwright/test'; const cwd = __dirname; @@ -6,8 +6,6 @@ const cwd = __dirname; test('should print server urls correctly when printUrls is true', async ({ page, }) => { - const { logs, restore } = proxyConsole('log'); - const rsbuild = await dev({ cwd, rsbuildConfig: { @@ -19,29 +17,25 @@ test('should print server urls correctly when printUrls is true', async ({ await page.goto(`http://localhost:${rsbuild.port}`); - const localLog = logs.find( + const localLog = rsbuild.logs.find( (log) => log.includes('Local:') && log.includes(`http://localhost:${rsbuild.port}`), ); - const networkLog = logs.find( + const networkLog = rsbuild.logs.find( (log) => log.includes('Network:') && log.includes('http://'), ); expect(localLog).toBeTruthy(); expect(networkLog).toBeTruthy(); - expect(logs.find((log) => log.includes('/./'))).toBeFalsy(); - + expect(rsbuild.logs.find((log) => log.includes('/./'))).toBeFalsy(); await rsbuild.close(); - restore(); }); test('should print different environment server urls correctly', async ({ page, }) => { - const { logs, restore } = proxyConsole('log'); - const rsbuild = await dev({ cwd, rsbuildConfig: { @@ -77,27 +71,24 @@ test('should print different environment server urls correctly', async ({ await page.goto(`http://localhost:${rsbuild.port}`); - const localIndexLog = logs.find( + const localIndexLog = rsbuild.logs.find( (log) => log.includes('Local:') && log.includes('/html0'), ); expect(localIndexLog).toBeTruthy(); - const localMainLog = logs.find( + const localMainLog = rsbuild.logs.find( (log) => log.includes('Local:') && log.includes('/html1/main'), ); expect(localMainLog).toBeTruthy(); await rsbuild.close(); - restore(); }); test('should not print server urls when printUrls is false', async ({ page, }) => { - const { logs, restore } = proxyConsole('log'); - const rsbuild = await dev({ cwd, rsbuildConfig: { @@ -109,10 +100,10 @@ test('should not print server urls when printUrls is false', async ({ await page.goto(`http://localhost:${rsbuild.port}`); - const localLog = logs.find( + const localLog = rsbuild.logs.find( (log) => log.includes('Local:') && log.includes('http://localhost'), ); - const networkLog = logs.find( + const networkLog = rsbuild.logs.find( (log) => log.includes('Network:') && log.includes('http://'), ); @@ -120,12 +111,9 @@ test('should not print server urls when printUrls is false', async ({ expect(networkLog).toBeFalsy(); await rsbuild.close(); - restore(); }); test('should allow to custom urls', async ({ page }) => { - const { logs, restore } = proxyConsole('log'); - const rsbuild = await dev({ cwd, rsbuildConfig: { @@ -141,10 +129,10 @@ test('should allow to custom urls', async ({ page }) => { await page.goto(`http://localhost:${rsbuild.port}`); - const localLog = logs.find( + const localLog = rsbuild.logs.find( (log) => log.includes('Local:') && log.includes('http://localhost'), ); - const networkLog = logs.find( + const networkLog = rsbuild.logs.find( (log) => log.includes('Network:') && log.includes('http://'), ); @@ -152,12 +140,9 @@ test('should allow to custom urls', async ({ page }) => { expect(networkLog).toBeFalsy(); await rsbuild.close(); - restore(); }); test('should allow to modify and return new urls', async ({ page }) => { - const { logs, restore } = proxyConsole('log'); - const rsbuild = await dev({ cwd, rsbuildConfig: { @@ -169,12 +154,12 @@ test('should allow to modify and return new urls', async ({ page }) => { await page.goto(`http://localhost:${rsbuild.port}`); - const localLog = logs.find( + const localLog = rsbuild.logs.find( (log) => log.includes('Local:') && log.includes(`http://localhost:${rsbuild.port}/test/`), ); - const networkLog = logs.find( + const networkLog = rsbuild.logs.find( (log) => log.includes('Network:') && log.includes('http://') && @@ -185,12 +170,9 @@ test('should allow to modify and return new urls', async ({ page }) => { expect(networkLog).toBeFalsy(); await rsbuild.close(); - restore(); }); test('allow only listen to localhost for dev', async ({ page }) => { - const { logs, restore } = proxyConsole('log'); - const rsbuild = await dev({ cwd, rsbuildConfig: { @@ -203,10 +185,10 @@ test('allow only listen to localhost for dev', async ({ page }) => { await page.goto(`http://localhost:${rsbuild.port}`); - const localLog = logs.find( + const localLog = rsbuild.logs.find( (log) => log.includes('Local:') && log.includes('http://localhost'), ); - const networkLog = logs.find( + const networkLog = rsbuild.logs.find( (log) => log.includes('Network:') && log.includes('http://'), ); @@ -214,12 +196,9 @@ test('allow only listen to localhost for dev', async ({ page }) => { expect(networkLog).toBeFalsy(); await rsbuild.close(); - restore(); }); test('allow only listen to localhost for prod preview', async ({ page }) => { - const { logs, restore } = proxyConsole('log'); - const rsbuild = await build({ cwd, page, @@ -233,10 +212,10 @@ test('allow only listen to localhost for prod preview', async ({ page }) => { await page.goto(`http://localhost:${rsbuild.port}`); - const localLog = logs.find( + const localLog = rsbuild.logs.find( (log) => log.includes('Local:') && log.includes('http://localhost'), ); - const networkLog = logs.find( + const networkLog = rsbuild.logs.find( (log) => log.includes('Network:') && log.includes('http://'), ); @@ -244,12 +223,9 @@ test('allow only listen to localhost for prod preview', async ({ page }) => { expect(networkLog).toBeFalsy(); await rsbuild.close(); - restore(); }); test('should not print server urls when HTML is disabled', async ({ page }) => { - const { logs, restore } = proxyConsole('log'); - const rsbuild = await build({ cwd, page, @@ -260,10 +236,10 @@ test('should not print server urls when HTML is disabled', async ({ page }) => { }, }); - const localLog = logs.find( + const localLog = rsbuild.logs.find( (log) => log.includes('Local:') && log.includes('http://localhost'), ); - const networkLog = logs.find( + const networkLog = rsbuild.logs.find( (log) => log.includes('Network:') && log.includes('http://'), ); @@ -271,14 +247,11 @@ test('should not print server urls when HTML is disabled', async ({ page }) => { expect(networkLog).toBeFalsy(); await rsbuild.close(); - restore(); }); test('should print server urls when HTML is disabled but printUrls is a custom function', async ({ page, }) => { - const { logs, restore } = proxyConsole('log'); - const rsbuild = await build({ cwd, page, @@ -292,18 +265,15 @@ test('should print server urls when HTML is disabled but printUrls is a custom f }, }); - const localLog = logs.find((log) => + const localLog = rsbuild.logs.find((log) => log.includes(`➜ Network: http://localhost:${rsbuild.port}`), ); expect(localLog).toBeTruthy(); await rsbuild.close(); - restore(); }); test('should get posix route correctly', async ({ page }) => { - const { logs, restore } = proxyConsole('log'); - const rsbuild = await dev({ cwd, rsbuildConfig: { @@ -334,10 +304,10 @@ test('should get posix route correctly', async ({ page }) => { await page.goto(`http://localhost:${rsbuild.port}`); - const webLog = logs.find((log) => + const webLog = rsbuild.logs.find((log) => log.includes(`http://localhost:${rsbuild.port}/dist/`), ); - const web1Log = logs.find((log) => + const web1Log = rsbuild.logs.find((log) => log.includes(`http://localhost:${rsbuild.port}/.dist/web1/index1`), ); @@ -345,5 +315,4 @@ test('should get posix route correctly', async ({ page }) => { expect(web1Log).toBeTruthy(); await rsbuild.close(); - restore(); }); diff --git a/e2e/cases/server/proxy/index.test.ts b/e2e/cases/server/proxy/index.test.ts index 3b9989a28e..30d6081238 100644 --- a/e2e/cases/server/proxy/index.test.ts +++ b/e2e/cases/server/proxy/index.test.ts @@ -1,5 +1,5 @@ import { join } from 'node:path'; -import { dev, proxyConsole } from '@e2e/helper'; +import { dev } from '@e2e/helper'; import { expect, test } from '@playwright/test'; const prj1 = join(__dirname, 'project1'); @@ -42,8 +42,7 @@ test('should apply basic proxy rules correctly', async ({ page }) => { }); test('should handle proxy error correctly', async ({ page }) => { - const { logs, restore } = proxyConsole(); - const rsbuild1 = await dev({ + const rsbuild = await dev({ cwd: prj1, rsbuildConfig: { source: { @@ -65,15 +64,15 @@ test('should handle proxy error correctly', async ({ page }) => { }, }); - const res = await page.goto(`http://localhost:${rsbuild1.port}/api`); + const res = await page.goto(`http://localhost:${rsbuild.port}/api`); expect(res?.status()).toBe(504); expect( - logs.some((log) => log.includes('Error occurred while proxying request')), + rsbuild.logs.some((log) => + log.includes('Error occurred while proxying request'), + ), ).toBeTruthy(); - await rsbuild1.close(); - - restore(); + await rsbuild.close(); }); diff --git a/e2e/cases/server/ssr/index.test.ts b/e2e/cases/server/ssr/index.test.ts index 6bfbaab3b1..c1368b8677 100644 --- a/e2e/cases/server/ssr/index.test.ts +++ b/e2e/cases/server/ssr/index.test.ts @@ -1,12 +1,9 @@ -import { dev, proxyConsole, rspackOnlyTest } from '@e2e/helper'; +import { dev, rspackOnlyTest } from '@e2e/helper'; import { expect } from '@playwright/test'; rspackOnlyTest('support SSR', async ({ page }) => { - const { logs, restore } = proxyConsole('log'); - const rsbuild = await dev({ cwd: __dirname, - rsbuildConfig: {}, }); const url = new URL(`http://localhost:${rsbuild.port}`); @@ -18,16 +15,12 @@ rspackOnlyTest('support SSR', async ({ page }) => { await page.goto(url.href); // bundle result should cacheable and only load once. - expect(logs.filter((log) => log.includes('load SSR')).length).toBe(1); + expect(rsbuild.logs.filter((log) => log.includes('load SSR')).length).toBe(1); await rsbuild.close(); - - restore(); }); rspackOnlyTest('support SSR with external', async ({ page }) => { - const { logs, restore } = proxyConsole('log'); - const rsbuild = await dev({ cwd: __dirname, rsbuildConfig: { @@ -49,11 +42,9 @@ rspackOnlyTest('support SSR with external', async ({ page }) => { await page.goto(url.href); // bundle result should cacheable and only load once. - expect(logs.filter((log) => log.includes('load SSR')).length).toBe(1); + expect(rsbuild.logs.filter((log) => log.includes('load SSR')).length).toBe(1); await rsbuild.close(); - - restore(); }); rspackOnlyTest('support SSR with esm target', async ({ page }) => { diff --git a/e2e/cases/source/define/index.test.ts b/e2e/cases/source/define/index.test.ts index 1764ac197b..22f1621539 100644 --- a/e2e/cases/source/define/index.test.ts +++ b/e2e/cases/source/define/index.test.ts @@ -1,4 +1,4 @@ -import { build, dev, gotoPage, proxyConsole } from '@e2e/helper'; +import { build, dev, gotoPage } from '@e2e/helper'; import { expect, test } from '@playwright/test'; test('should allow to define global variables in development', async ({ @@ -34,8 +34,7 @@ test('should allow to define global variables in production build', async ({ }); test('should warn when define `process.env`', async ({ page }) => { - const { logs, restore } = proxyConsole(); - await build({ + const rsbuild = await build({ cwd: __dirname, page, rsbuildConfig: { @@ -48,17 +47,16 @@ test('should warn when define `process.env`', async ({ page }) => { }); expect( - logs.some((log) => + rsbuild.logs.some((log) => log.includes('The "source.define" option includes an object'), ), ).toBe(true); - restore(); + await rsbuild.close(); }); test('should warn when define stringified `process.env`', async ({ page }) => { - const { logs, restore } = proxyConsole(); - await build({ + const rsbuild = await build({ cwd: __dirname, page, rsbuildConfig: { @@ -71,10 +69,10 @@ test('should warn when define stringified `process.env`', async ({ page }) => { }); expect( - logs.some((log) => + rsbuild.logs.some((log) => log.includes('The "source.define" option includes an object'), ), ).toBe(true); - restore(); + await rsbuild.close(); }); diff --git a/e2e/cases/source/source-exclude/index.test.ts b/e2e/cases/source/source-exclude/index.test.ts index e523047c2c..20386aed75 100644 --- a/e2e/cases/source/source-exclude/index.test.ts +++ b/e2e/cases/source/source-exclude/index.test.ts @@ -1,31 +1,28 @@ import path from 'node:path'; -import { build, proxyConsole } from '@e2e/helper'; +import { build } from '@e2e/helper'; import { expect, test } from '@playwright/test'; import { pluginCheckSyntax } from '@rsbuild/plugin-check-syntax'; import { normalizeToPosixPath } from '@scripts/test-helper'; test('should not compile specified file when source.exclude', async () => { - const { logs, restore } = proxyConsole(); - await expect( - build({ - cwd: __dirname, - plugins: [pluginCheckSyntax()], - rsbuildConfig: { - source: { - exclude: [path.resolve(__dirname, './src/test.js')], - }, - output: { - overrideBrowserslist: ['ie 11'], - }, + const rsbuild = await build({ + cwd: __dirname, + plugins: [pluginCheckSyntax()], + catchBuildError: true, + rsbuildConfig: { + source: { + exclude: [path.resolve(__dirname, './src/test.js')], }, - }), - ).rejects.toThrowError('[@rsbuild/plugin-check-syntax]'); - - restore(); + output: { + overrideBrowserslist: ['ie 11'], + }, + }, + }); - expect(logs.find((log) => log.includes('ERROR 1'))).toBeTruthy(); + expect(rsbuild.buildError).toBeTruthy(); + expect(rsbuild.logs.find((log) => log.includes('ERROR 1'))).toBeTruthy(); expect( - logs.find( + rsbuild.logs.find( (log) => log.includes('source:') && normalizeToPosixPath(log).includes('/dist/static/js/index'), diff --git a/e2e/cases/source/source-include/index.test.ts b/e2e/cases/source/source-include/index.test.ts index 7d1040d986..fb2694e626 100644 --- a/e2e/cases/source/source-include/index.test.ts +++ b/e2e/cases/source/source-include/index.test.ts @@ -1,21 +1,23 @@ -import { build, proxyConsole } from '@e2e/helper'; +import { build } from '@e2e/helper'; import { expect, test } from '@playwright/test'; import { pluginCheckSyntax } from '@rsbuild/plugin-check-syntax'; test('should compile modules outside of project by default', async () => { - const { logs, restore } = proxyConsole(); - await expect( - build({ - cwd: __dirname, - plugins: [pluginCheckSyntax()], - rsbuildConfig: { - output: { - overrideBrowserslist: ['ie 11'], - }, + const rsbuild = await build({ + cwd: __dirname, + plugins: [pluginCheckSyntax()], + catchBuildError: true, + rsbuildConfig: { + output: { + overrideBrowserslist: ['ie 11'], }, - }), - ).resolves.toBeDefined(); + }, + }); - expect(logs.find((log) => log.includes('Syntax check passed'))).toBeTruthy(); - restore(); + expect(rsbuild.buildError).toBeFalsy(); + expect( + rsbuild.logs.find((log) => log.includes('Syntax check passed')), + ).toBeTruthy(); + + await rsbuild.close(); }); diff --git a/e2e/cases/sri/enable-dev/index.test.ts b/e2e/cases/sri/enable-dev/index.test.ts index 152105df30..0b4f3fc332 100644 --- a/e2e/cases/sri/enable-dev/index.test.ts +++ b/e2e/cases/sri/enable-dev/index.test.ts @@ -1,11 +1,9 @@ -import { dev, proxyConsole, rspackOnlyTest } from '@e2e/helper'; +import { dev, rspackOnlyTest } from '@e2e/helper'; import { expect } from '@playwright/test'; rspackOnlyTest( 'generate integrity for script and style tags in dev build', async ({ page }) => { - const { logs, restore } = proxyConsole(); - const rsbuild = await dev({ cwd: __dirname, page, @@ -20,16 +18,14 @@ rspackOnlyTest( ), ).toMatch(/sha384-[A-Za-z0-9+/=]+/); - await rsbuild.close(); - expect( - logs.some((log) => + rsbuild.logs.some((log) => log.includes( 'SubResourceIntegrityPlugin may interfere with hot reloading', ), ), ).toBe(true); - restore(); + await rsbuild.close(); }, ); diff --git a/e2e/cases/syntax/decorator-2022-03/index.test.ts b/e2e/cases/syntax/decorator-2022-03/index.test.ts index 5e07b136b1..e82e6a6c33 100644 --- a/e2e/cases/syntax/decorator-2022-03/index.test.ts +++ b/e2e/cases/syntax/decorator-2022-03/index.test.ts @@ -1,4 +1,4 @@ -import { build, proxyConsole, rspackOnlyTest } from '@e2e/helper'; +import { build, rspackOnlyTest } from '@e2e/helper'; import { expect, test } from '@playwright/test'; import { pluginBabel } from '@rsbuild/plugin-babel'; @@ -35,8 +35,6 @@ rspackOnlyTest( test.fail( 'stage 3 decorators do not support decoratorBeforeExport', async ({ page }) => { - const { logs, restore } = proxyConsole(); - // SyntaxError: Decorators must be placed *after* the 'export' keyword const rsbuild = await build({ cwd: __dirname, @@ -57,13 +55,13 @@ test.fail( await rsbuild.close(); expect( - logs.find((log) => + rsbuild.logs.find((log) => log.includes( 'Using the export keyword between a decorator and a class is not allowed', ), ), ).toBeTruthy(); - restore(); + await rsbuild.close(); }, ); diff --git a/e2e/scripts/helper.ts b/e2e/scripts/helper.ts index 81e9bde60b..9731a40512 100644 --- a/e2e/scripts/helper.ts +++ b/e2e/scripts/helper.ts @@ -3,7 +3,7 @@ import { platform } from 'node:os'; import { join } from 'node:path'; import { stripVTControlCharacters as stripAnsi } from 'node:util'; import { expect, test } from '@playwright/test'; -import type { ConsoleType } from '@rsbuild/core'; +import type { ConsoleType, LogLevel } from '@rsbuild/core'; import glob, { convertPathToPattern, type Options as GlobOptions, @@ -74,13 +74,24 @@ export const readDirContents = async (path: string, options?: GlobOptions) => { export const expectFile = (dir: string) => expectPoll(() => fs.existsSync(dir)).toBeTruthy(); +export type ProxyConsoleOptions = { + types?: ConsoleType | ConsoleType[]; + keepAnsi?: boolean; + logLevel?: LogLevel | 'verbose'; +}; + +export type ProxyConsoleResult = { + logs: string[]; + restore: () => void; +}; + /** * Proxy the console methods to capture the logs */ -export const proxyConsole = ( - types: ConsoleType | ConsoleType[] = ['log', 'warn', 'info', 'error'], +export const proxyConsole = ({ + types = ['log', 'warn', 'info', 'error'], keepAnsi = false, -) => { +}: ProxyConsoleOptions = {}): ProxyConsoleResult => { const logs: string[] = []; const restores: Array<() => void> = []; diff --git a/e2e/scripts/shared.ts b/e2e/scripts/shared.ts index 4d114af1dd..7f1409f1d9 100644 --- a/e2e/scripts/shared.ts +++ b/e2e/scripts/shared.ts @@ -9,7 +9,11 @@ import type { } from '@rsbuild/core'; import { pluginSwc } from '@rsbuild/plugin-webpack-swc'; import type { Page } from 'playwright'; -import { readDirContents } from './helper'; +import { + type ProxyConsoleOptions, + proxyConsole, + readDirContents, +} from './helper'; /** * Build an URL based on the entry name and port @@ -135,7 +139,13 @@ const updateConfigForTest = async ( }, }; - return mergeRsbuildConfig(baseConfig, loadedConfig, originalConfig); + const mergedConfig = mergeRsbuildConfig( + baseConfig, + loadedConfig, + originalConfig, + ); + + return mergedConfig; }; /** @@ -155,6 +165,7 @@ const getDistFiles = async (distPath: string, ignoreMap = true) => { export async function dev({ plugins, page, + captureLogs = true, waitFirstCompileDone = true, ...options }: CreateRsbuildOptions & { @@ -165,6 +176,10 @@ export async function dev({ * This method will automatically goto the page. */ page?: Page; + /** + * Call `proxyConsole` to capture the console logs. + */ + captureLogs?: ProxyConsoleOptions | boolean; /** * The done of `dev` does not mean the compile is done. * If your test relies on the completion of compilation you should `waitFirstCompileDone` @@ -174,6 +189,11 @@ export async function dev({ }) { process.env.NODE_ENV = 'development'; + const proxyConsoleResult = + captureLogs === false + ? null + : proxyConsole(captureLogs === true ? {} : captureLogs); + options.rsbuildConfig = await updateConfigForTest( options.rsbuildConfig || {}, options.cwd, @@ -223,10 +243,14 @@ export async function dev({ return { ...result, + logs: proxyConsoleResult?.logs || [], instance: rsbuild, getDistFiles: (ignoreMap?: boolean) => getDistFiles(rsbuild.context.distPath, ignoreMap), - close: async () => result.server.close(), + close: async () => { + await result.server.close(); + proxyConsoleResult?.restore(); + }, }; } @@ -235,12 +259,19 @@ export async function dev({ */ export async function build({ plugins, + captureLogs = true, + catchBuildError = false, runServer = false, page, ...options }: CreateRsbuildOptions & { plugins?: RsbuildPlugins; rsbuildConfig?: RsbuildConfig; + /** + * Whether to catch the build error. + * @default false + */ + catchBuildError?: boolean; /** * Whether to run the server. */ @@ -250,9 +281,18 @@ export async function build({ * This method will automatically run the server and goto the page. */ page?: Page; + /** + * Call `proxyConsole` to capture the console logs. + */ + captureLogs?: ProxyConsoleOptions | boolean; }) { process.env.NODE_ENV = 'production'; + const proxyConsoleResult = + captureLogs === false + ? null + : proxyConsole(captureLogs === true ? {} : captureLogs); + options.rsbuildConfig = await updateConfigForTest( options.rsbuildConfig || {}, options.cwd, @@ -260,7 +300,17 @@ export async function build({ const rsbuild = await createRsbuild(options, plugins); - await rsbuild.build(); + let buildError: Error | undefined; + + try { + await rsbuild.build(); + } catch (error) { + buildError = error as Error; + + if (!catchBuildError) { + throw buildError; + } + } const { distPath } = rsbuild.context; @@ -293,9 +343,14 @@ export async function build({ } return { + logs: proxyConsoleResult?.logs || [], distPath, port, - close: server.close, + close: async () => { + await server.close(); + proxyConsoleResult?.restore(); + }, + buildError, getDistFiles: (ignoreMap?: boolean) => getDistFiles(distPath, ignoreMap), getIndexFile, instance: rsbuild,