From 85877e3e18429166fbbcaf8131a8338f7cd1c6bf Mon Sep 17 00:00:00 2001 From: Jack Hsu Date: Mon, 30 Sep 2024 09:00:01 -0400 Subject: [PATCH] feat(react): make vitest the default test runner since it supports ESM and different moduleResolution better (#28153) This PR updates the default test runner for React/Web apps to be `vitest`. It aligned better with our emphasis on modern tooling, and the lack of ESM and proper TS support (using `module` other than `commonjs`) in Jest makes it hard to use in some workspaces. ## Current Behavior ## Expected Behavior ## Related Issue(s) Fixes # --- .../packages/next/generators/library.json | 5 +++-- .../packages/react/generators/application.json | 4 ++-- .../packages/react/generators/library.json | 3 ++- .../packages/remix/generators/library.json | 2 +- .../generated/packages/vite/generators/vitest.json | 6 ++++++ .../packages/web/generators/application.json | 3 ++- e2e/eslint/src/linter.test.ts | 4 +++- e2e/nx/src/run.test.ts | 2 -- e2e/react/src/react.test.ts | 8 ++++---- e2e/web/src/web-vite.test.ts | 4 +++- e2e/web/src/web.test.ts | 2 +- .../src/__snapshots__/webpack.legacy.test.ts.snap | 14 +++++++------- packages/js/src/generators/library/library.ts | 1 + packages/next/src/generators/library/schema.json | 5 +++-- .../react/src/generators/application/schema.json | 4 ++-- packages/react/src/generators/library/library.ts | 1 + packages/react/src/generators/library/schema.json | 3 ++- packages/remix/src/generators/library/schema.json | 2 +- .../src/generators/configuration/configuration.ts | 1 + packages/vite/src/generators/vitest/schema.d.ts | 1 + packages/vite/src/generators/vitest/schema.json | 6 ++++++ .../vite/src/generators/vitest/vitest-generator.ts | 10 +++++++++- .../web/src/generators/application/application.ts | 1 + .../web/src/generators/application/schema.json | 3 ++- 24 files changed, 64 insertions(+), 31 deletions(-) diff --git a/docs/generated/packages/next/generators/library.json b/docs/generated/packages/next/generators/library.json index 3f148199fa048..75f16d91b6459 100644 --- a/docs/generated/packages/next/generators/library.json +++ b/docs/generated/packages/next/generators/library.json @@ -70,8 +70,9 @@ }, "unitTestRunner": { "type": "string", - "enum": ["jest", "vitest", "none"], - "description": "Test runner to use for unit tests." + "enum": ["vitest", "jest", "none"], + "description": "Test runner to use for unit tests.", + "default": "vitest" }, "tags": { "type": "string", diff --git a/docs/generated/packages/react/generators/application.json b/docs/generated/packages/react/generators/application.json index 8052e62d02ce5..c882bda0f12bb 100644 --- a/docs/generated/packages/react/generators/application.json +++ b/docs/generated/packages/react/generators/application.json @@ -105,9 +105,9 @@ }, "unitTestRunner": { "type": "string", - "enum": ["jest", "vitest", "none"], + "enum": ["vitest", "jest", "none"], "description": "Test runner to use for unit tests.", - "default": "jest" + "default": "vitest" }, "inSourceTests": { "type": "boolean", diff --git a/docs/generated/packages/react/generators/library.json b/docs/generated/packages/react/generators/library.json index 1509cb577fedf..a6c32afe0efd1 100644 --- a/docs/generated/packages/react/generators/library.json +++ b/docs/generated/packages/react/generators/library.json @@ -80,7 +80,8 @@ }, "unitTestRunner": { "type": "string", - "enum": ["jest", "vitest", "none"], + "enum": ["vitest", "jest", "none"], + "default": "vitest", "description": "Test runner to use for unit tests.", "x-prompt": "What unit test runner should be used?" }, diff --git a/docs/generated/packages/remix/generators/library.json b/docs/generated/packages/remix/generators/library.json index 4a4b6dc7708e8..2baa96204a6ee 100644 --- a/docs/generated/packages/remix/generators/library.json +++ b/docs/generated/packages/remix/generators/library.json @@ -49,7 +49,7 @@ }, "unitTestRunner": { "type": "string", - "enum": ["jest", "vitest", "none"], + "enum": ["vitest", "jest", "none"], "description": "Test Runner to use for Unit Tests", "x-prompt": "What test runner should be used?", "default": "vitest" diff --git a/docs/generated/packages/vite/generators/vitest.json b/docs/generated/packages/vite/generators/vitest.json index a78a9fb8e8afd..405055be3de18 100644 --- a/docs/generated/packages/vite/generators/vitest.json +++ b/docs/generated/packages/vite/generators/vitest.json @@ -55,6 +55,12 @@ "runtimeTsconfigFileName": { "type": "string", "description": "The name of the project's tsconfig file that includes the runtime source files. If not provided, it will default to `tsconfig.lib.json` for libraries and `tsconfig.app.json` for applications." + }, + "compiler": { + "type": "string", + "enum": ["babel", "swc"], + "default": "babel", + "description": "The compiler to use" } }, "required": ["project"], diff --git a/docs/generated/packages/web/generators/application.json b/docs/generated/packages/web/generators/application.json index 94d166cd45a83..48b119a5e9449 100644 --- a/docs/generated/packages/web/generators/application.json +++ b/docs/generated/packages/web/generators/application.json @@ -74,7 +74,8 @@ }, "unitTestRunner": { "type": "string", - "enum": ["jest", "vitest", "none"], + "enum": ["vitest", "jest", "none"], + "default": "vitest", "description": "Test runner to use for unit tests. Default value is 'jest' when using 'webpack' or 'none' as the bundler and 'vitest' when using 'vite' as the bundler" }, "inSourceTests": { diff --git a/e2e/eslint/src/linter.test.ts b/e2e/eslint/src/linter.test.ts index e4be2f44e56e7..d3cb8d71e5639 100644 --- a/e2e/eslint/src/linter.test.ts +++ b/e2e/eslint/src/linter.test.ts @@ -685,7 +685,9 @@ describe('Linter', () => { const myapp = uniq('myapp'); const mylib = uniq('mylib'); - runCLI(`generate @nx/react:app ${myapp} --rootProject=true`); + runCLI( + `generate @nx/react:app ${myapp} --unitTestRunner=jest --rootProject=true` + ); verifySuccessfulStandaloneSetup(myapp); let appEslint = readJson('.eslintrc.json'); diff --git a/e2e/nx/src/run.test.ts b/e2e/nx/src/run.test.ts index 2d6064ce0e227..5842ba8edf08e 100644 --- a/e2e/nx/src/run.test.ts +++ b/e2e/nx/src/run.test.ts @@ -331,8 +331,6 @@ describe('Nx Running Tests', () => { .filter((r) => r); withBail = withBail.slice(withBail.indexOf('Failed tasks:')); - expect(withBail).toHaveLength(2); - if (withBail[1] === `- ${myapp1}:error`) { expect(withBail).not.toContain(`- ${myapp2}:error`); } else { diff --git a/e2e/react/src/react.test.ts b/e2e/react/src/react.test.ts index e627fda2f5eff..92fb1de5d0857 100644 --- a/e2e/react/src/react.test.ts +++ b/e2e/react/src/react.test.ts @@ -107,7 +107,7 @@ describe('React Applications', () => { const redSvg = ``; runCLI( - `generate @nx/react:app ${appName} --directory=apps/${appName} --style=css --bundler=webpack --no-interactive --skipFormat` + `generate @nx/react:app ${appName} --directory=apps/${appName} --style=css --bundler=webpack --unit-test-runner=jest --no-interactive --skipFormat` ); runCLI( `generate @nx/react:lib ${libName} --directory=libs${libName} --style=css --no-interactive --unit-test-runner=jest --skipFormat` @@ -234,7 +234,7 @@ describe('React Applications', () => { ); const appTestResults = await runCLIAsync(`test ${appName}`); expect(appTestResults.combinedOutput).toContain( - 'Test Suites: 2 passed, 2 total' + `Successfully ran target test for project ${appName}` ); lintResults = runCLI(`lint ${libName}`); @@ -243,7 +243,7 @@ describe('React Applications', () => { ); const libTestResults = await runCLIAsync(`test ${libName}`); expect(libTestResults.combinedOutput).toContain( - 'Test Suites: 2 passed, 2 total' + `Successfully ran target test for project ${libName}` ); }, 250_000); @@ -414,7 +414,7 @@ describe('React Applications', () => { const plainJsLib = uniq('jslib'); runCLI( - `generate @nx/react:app ${appName} --directory=apps/${appName} --bundler=webpack --no-interactive --js --skipFormat` + `generate @nx/react:app ${appName} --directory=apps/${appName} --bundler=webpack --unit-test-runner=jest --no-interactive --js --skipFormat` ); runCLI( `generate @nx/react:lib ${libName} --directory=libs/${libName} --no-interactive --js --unit-test-runner=none --skipFormat` diff --git a/e2e/web/src/web-vite.test.ts b/e2e/web/src/web-vite.test.ts index d1658f0f44d08..59b8d03190cf3 100644 --- a/e2e/web/src/web-vite.test.ts +++ b/e2e/web/src/web-vite.test.ts @@ -30,7 +30,9 @@ describe('Web Components Applications with bundler set as vite', () => { const testResults = await runCLIAsync(`test ${appName}`); - expect(testResults.combinedOutput).toContain(`PASS ${appName}`); + expect(testResults.combinedOutput).toContain( + `Successfully ran target test for project ${appName}` + ); const lintE2eResults = runCLI(`lint ${appName}-e2e`); diff --git a/e2e/web/src/web.test.ts b/e2e/web/src/web.test.ts index 408fc88ec952f..d2afe6f64ca00 100644 --- a/e2e/web/src/web.test.ts +++ b/e2e/web/src/web.test.ts @@ -35,7 +35,7 @@ describe('Web Components Applications', () => { const testResults = await runCLIAsync(`test ${appName}`); expect(testResults.combinedOutput).toContain( - 'Test Suites: 1 passed, 1 total' + `Successfully ran target test for project ${appName}` ); const lintE2eResults = runCLI(`lint ${appName}-e2e`); diff --git a/e2e/webpack/src/__snapshots__/webpack.legacy.test.ts.snap b/e2e/webpack/src/__snapshots__/webpack.legacy.test.ts.snap index 31219273146df..eef27f724d743 100644 --- a/e2e/webpack/src/__snapshots__/webpack.legacy.test.ts.snap +++ b/e2e/webpack/src/__snapshots__/webpack.legacy.test.ts.snap @@ -85,6 +85,13 @@ exports[`Webpack Plugin (legacy) ConvertConfigToWebpackPlugin, should convert wi } } }, + "test": { + "executor": "@nx/vite:test", + "outputs": ["{options.reportsDirectory}"], + "options": { + "reportsDirectory": "../coverage/app3224373" + } + }, "lint": { "executor": "@nx/eslint:lint" }, @@ -95,13 +102,6 @@ exports[`Webpack Plugin (legacy) ConvertConfigToWebpackPlugin, should convert wi "buildTarget": "app3224373:build", "spa": true } - }, - "test": { - "executor": "@nx/jest:jest", - "outputs": ["{workspaceRoot}/coverage/{projectRoot}"], - "options": { - "jestConfig": "app3224373/jest.config.ts" - } } } } diff --git a/packages/js/src/generators/library/library.ts b/packages/js/src/generators/library/library.ts index f30e30a4f2dc2..26a6d99ee5716 100644 --- a/packages/js/src/generators/library/library.ts +++ b/packages/js/src/generators/library/library.ts @@ -168,6 +168,7 @@ export async function libraryGeneratorInternal( skipFormat: true, testEnvironment: options.testEnvironment, runtimeTsconfigFileName: 'tsconfig.lib.json', + compiler: options.compiler === 'swc' ? 'swc' : 'babel', }); tasks.push(vitestTask); createOrEditViteConfig( diff --git a/packages/next/src/generators/library/schema.json b/packages/next/src/generators/library/schema.json index 16e0933003c00..1a383b6da94a2 100644 --- a/packages/next/src/generators/library/schema.json +++ b/packages/next/src/generators/library/schema.json @@ -73,8 +73,9 @@ }, "unitTestRunner": { "type": "string", - "enum": ["jest", "vitest", "none"], - "description": "Test runner to use for unit tests." + "enum": ["vitest", "jest", "none"], + "description": "Test runner to use for unit tests.", + "default": "vitest" }, "tags": { "type": "string", diff --git a/packages/react/src/generators/application/schema.json b/packages/react/src/generators/application/schema.json index 7d3bd32f70ad9..d368e1996d763 100644 --- a/packages/react/src/generators/application/schema.json +++ b/packages/react/src/generators/application/schema.json @@ -111,9 +111,9 @@ }, "unitTestRunner": { "type": "string", - "enum": ["jest", "vitest", "none"], + "enum": ["vitest", "jest", "none"], "description": "Test runner to use for unit tests.", - "default": "jest" + "default": "vitest" }, "inSourceTests": { "type": "boolean", diff --git a/packages/react/src/generators/library/library.ts b/packages/react/src/generators/library/library.ts index 1d4058bb91f81..195674f7ad573 100644 --- a/packages/react/src/generators/library/library.ts +++ b/packages/react/src/generators/library/library.ts @@ -158,6 +158,7 @@ export async function libraryGeneratorInternal(host: Tree, schema: Schema) { skipFormat: true, testEnvironment: 'jsdom', addPlugin: options.addPlugin, + compiler: options.compiler, }); tasks.push(vitestTask); createOrEditViteConfig( diff --git a/packages/react/src/generators/library/schema.json b/packages/react/src/generators/library/schema.json index 7379f0f3a0281..aa604bb570fc8 100644 --- a/packages/react/src/generators/library/schema.json +++ b/packages/react/src/generators/library/schema.json @@ -83,7 +83,8 @@ }, "unitTestRunner": { "type": "string", - "enum": ["jest", "vitest", "none"], + "enum": ["vitest", "jest", "none"], + "default": "vitest", "description": "Test runner to use for unit tests.", "x-prompt": "What unit test runner should be used?" }, diff --git a/packages/remix/src/generators/library/schema.json b/packages/remix/src/generators/library/schema.json index feb6c1f686ef2..a0853c6d422ca 100644 --- a/packages/remix/src/generators/library/schema.json +++ b/packages/remix/src/generators/library/schema.json @@ -49,7 +49,7 @@ }, "unitTestRunner": { "type": "string", - "enum": ["jest", "vitest", "none"], + "enum": ["vitest", "jest", "none"], "description": "Test Runner to use for Unit Tests", "x-prompt": "What test runner should be used?", "default": "vitest" diff --git a/packages/vite/src/generators/configuration/configuration.ts b/packages/vite/src/generators/configuration/configuration.ts index 7338886c6fbea..0b314c33914f1 100644 --- a/packages/vite/src/generators/configuration/configuration.ts +++ b/packages/vite/src/generators/configuration/configuration.ts @@ -163,6 +163,7 @@ export async function viteConfigurationGeneratorInternal( testTarget: 'test', skipFormat: true, addPlugin: schema.addPlugin, + compiler: schema.compiler, }); tasks.push(vitestTask); } diff --git a/packages/vite/src/generators/vitest/schema.d.ts b/packages/vite/src/generators/vitest/schema.d.ts index fa762ad61c97f..e876864ac4bac 100644 --- a/packages/vite/src/generators/vitest/schema.d.ts +++ b/packages/vite/src/generators/vitest/schema.d.ts @@ -9,4 +9,5 @@ export interface VitestGeneratorSchema { testEnvironment?: 'node' | 'jsdom' | 'happy-dom' | 'edge-runtime' | string; addPlugin?: boolean; runtimeTsconfigFileName?: string; + compiler?: 'babel' | 'swc'; // default: babel } diff --git a/packages/vite/src/generators/vitest/schema.json b/packages/vite/src/generators/vitest/schema.json index cc06c1be1b4c9..f228bee787178 100644 --- a/packages/vite/src/generators/vitest/schema.json +++ b/packages/vite/src/generators/vitest/schema.json @@ -54,6 +54,12 @@ "runtimeTsconfigFileName": { "type": "string", "description": "The name of the project's tsconfig file that includes the runtime source files. If not provided, it will default to `tsconfig.lib.json` for libraries and `tsconfig.app.json` for applications." + }, + "compiler": { + "type": "string", + "enum": ["babel", "swc"], + "default": "babel", + "description": "The compiler to use" } }, "required": ["project"] diff --git a/packages/vite/src/generators/vitest/vitest-generator.ts b/packages/vite/src/generators/vitest/vitest-generator.ts index ea9c68362e80a..d932ca24e2aeb 100644 --- a/packages/vite/src/generators/vitest/vitest-generator.ts +++ b/packages/vite/src/generators/vitest/vitest-generator.ts @@ -46,6 +46,10 @@ export async function vitestGeneratorInternal( schema: VitestGeneratorSchema, hasPlugin = false ) { + // Setting default to jsdom since it is the most common use case (React, Web). + // The @nx/js:lib generator specifically sets this to node to be more generic. + schema.testEnvironment ??= 'jsdom'; + const tasks: GeneratorCallback[] = []; const { root, projectType } = readProjectConfiguration(tree, schema.project); @@ -85,7 +89,11 @@ export async function vitestGeneratorInternal( "'react-dom'", "'react/jsx-runtime'", ], - imports: [`import react from '@vitejs/plugin-react'`], + imports: [ + schema.compiler === 'swc' + ? `import react from '@vitejs/plugin-react-swc'` + : `import react from '@vitejs/plugin-react'`, + ], plugins: ['react()'], coverageProvider: schema.coverageProvider, }, diff --git a/packages/web/src/generators/application/application.ts b/packages/web/src/generators/application/application.ts index b070e149df52d..b8d02b1e08753 100644 --- a/packages/web/src/generators/application/application.ts +++ b/packages/web/src/generators/application/application.ts @@ -325,6 +325,7 @@ export async function applicationGeneratorInternal(host: Tree, schema: Schema) { inSourceTests: options.inSourceTests, skipFormat: true, addPlugin: options.addPlugin, + compiler: options.compiler, }); tasks.push(vitestTask); createOrEditViteConfig( diff --git a/packages/web/src/generators/application/schema.json b/packages/web/src/generators/application/schema.json index a4b8798bf551c..1da0fa56f6531 100644 --- a/packages/web/src/generators/application/schema.json +++ b/packages/web/src/generators/application/schema.json @@ -77,7 +77,8 @@ }, "unitTestRunner": { "type": "string", - "enum": ["jest", "vitest", "none"], + "enum": ["vitest", "jest", "none"], + "default": "vitest", "description": "Test runner to use for unit tests. Default value is 'jest' when using 'webpack' or 'none' as the bundler and 'vitest' when using 'vite' as the bundler" }, "inSourceTests": {