diff --git a/modules/testing/builder/package.json b/modules/testing/builder/package.json index 176c6825b53e..d61b5633635a 100644 --- a/modules/testing/builder/package.json +++ b/modules/testing/builder/package.json @@ -4,12 +4,12 @@ "@angular-devkit/build-angular": "workspace:*", "@angular-devkit/core": "workspace:*", "@angular/ssr": "workspace:*", - "@vitest/coverage-v8": "4.1.11", + "@vitest/coverage-v8": "5.0.0", "browser-sync": "3.0.4", "istanbul-lib-instrument": "6.0.3", "jsdom": "30.0.1", "ng-packagr": "22.2.0-next.5", "rxjs": "7.8.2", - "vitest": "4.1.11" + "vitest": "5.0.0" } } diff --git a/packages/angular/build/package.json b/packages/angular/build/package.json index d1c1cb74f948..cd8b393873f7 100644 --- a/packages/angular/build/package.json +++ b/packages/angular/build/package.json @@ -60,7 +60,7 @@ "postcss": "8.5.26", "rollup": "4.63.1", "rxjs": "7.8.2", - "vitest": "4.1.11" + "vitest": "5.0.0" }, "peerDependencies": { "@angular/compiler": "0.0.0-ANGULAR-FW-PEER-DEP", @@ -80,7 +80,7 @@ "tailwindcss": "^2.0.0 || ^3.0.0 || ^4.0.0", "tslib": "^2.3.0", "typescript": ">=6.0 <6.1", - "vitest": "^4.0.8" + "vitest": "^4.0.8 || ^5.0.0" }, "peerDependenciesMeta": { "@angular/core": { diff --git a/packages/angular/build/src/builders/unit-test/runners/vitest/plugins.ts b/packages/angular/build/src/builders/unit-test/runners/vitest/plugins.ts index 29455b50cc7c..ee81e417bb5d 100644 --- a/packages/angular/build/src/builders/unit-test/runners/vitest/plugins.ts +++ b/packages/angular/build/src/builders/unit-test/runners/vitest/plugins.ts @@ -16,7 +16,6 @@ import type { ResolvedConfig, UserWorkspaceConfig, Vite, - VitestPlugin, VitestPluginContext, } from 'vitest/node'; import { createBuildAssetsMiddleware } from '../../../../tools/vite/middlewares/assets-middleware'; @@ -32,8 +31,6 @@ interface ExistingRawSourceMap { mappings?: string; } -type VitestPlugins = Awaited>; - interface PluginOptions { workspaceRoot: string; projectSourceRoot: string; @@ -151,7 +148,7 @@ function getBrowsersToCheck( export async function createVitestConfigPlugin( options: VitestConfigPluginOptions, -): Promise { +): Promise { const { include, browser, @@ -248,6 +245,7 @@ export async function createVitestConfigPlugin( const projectResolver = createProjectResolver(projectSourceRoot); const projectDefaults: Vite.UserConfig & UserWorkspaceConfig = { + extends: false, test: { setupFiles, globals: true, @@ -268,6 +266,7 @@ export async function createVitestConfigPlugin( const { optimizeDeps, resolve } = config; const projectOverrides: Vite.UserConfig & UserWorkspaceConfig = { + extends: false, test: { name: projectName, include, @@ -313,7 +312,7 @@ async function loadResultFile(file: ResultFile): Promise { return readFile(file.inputPath, 'utf-8'); } -export function createVitestPlugins(pluginOptions: PluginOptions): VitestPlugins { +export function createVitestPlugins(pluginOptions: PluginOptions): Vite.Plugin[] { const { workspaceRoot, buildResultFiles, testFileToEntryPoint } = pluginOptions; const isWindows = platform() === 'win32'; let vitestConfig: ResolvedConfig; diff --git a/packages/angular/build/src/builders/unit-test/schema.json b/packages/angular/build/src/builders/unit-test/schema.json index 5e9a62cf495d..58a9592986b1 100644 --- a/packages/angular/build/src/builders/unit-test/schema.json +++ b/packages/angular/build/src/builders/unit-test/schema.json @@ -21,7 +21,7 @@ }, "runnerConfig": { "type": ["string", "boolean"], - "description": "Specifies the configuration file for the selected test runner. If a string is provided, it will be used as the path to the configuration file. If `true`, the builder will search for a default configuration file (e.g., `vitest-base.config.ts` or `karma.conf.js`). If `false`, no external configuration file will be used.\\nFor Vitest, this enables advanced options and the use of custom plugins. Please note that while the file is loaded, the Angular team does not provide direct support for its specific contents or any third-party plugins used within it.", + "description": "Specifies the configuration file for the selected test runner. If a string is provided, it will be used as the path to the configuration file. If `true`, the builder will search for a default configuration file (e.g., `vitest-base.config.mts` or `karma.conf.js`). If `false`, no external configuration file will be used.\\nFor Vitest, this enables advanced options and the use of custom plugins. Please note that while the file is loaded, the Angular team does not provide direct support for its specific contents or any third-party plugins used within it.", "default": false }, "browsers": { @@ -80,7 +80,8 @@ "splitting": { "type": "boolean", "description": "Enables code splitting for test execution. When enabled, shared code between test files is split into separate chunks. Issues with live ESM bindings in Node.js environments (such as uninitialized exports or mocking failures) can be resolved by disabling splitting. This option is only available for the Vitest runner.", - "default": true + "default": true, + "x-deprecated": "No longer needed with Vitest 5." }, "quiet": { "type": "boolean", diff --git a/packages/angular/build/src/builders/unit-test/tests/behavior/runner-config-vitest_spec.ts b/packages/angular/build/src/builders/unit-test/tests/behavior/runner-config-vitest_spec.ts index ccd745ba5def..95107d1baec2 100644 --- a/packages/angular/build/src/builders/unit-test/tests/behavior/runner-config-vitest_spec.ts +++ b/packages/angular/build/src/builders/unit-test/tests/behavior/runner-config-vitest_spec.ts @@ -32,10 +32,10 @@ describeBuilder(execute, UNIT_TEST_BUILDER_INFO, (harness) => { it('should use custom reporters defined in runnerConfig file', async () => { harness.useTarget('test', { ...BASE_OPTIONS, - runnerConfig: 'vitest.config.ts', + runnerConfig: 'vitest.config.mts', }); - harness.writeFile('vitest.config.ts', VITEST_CONFIG_CONTENT); + harness.writeFile('vitest.config.mts', VITEST_CONFIG_CONTENT); const { result } = await harness.executeOnce(); expect(result?.success).toBeTrue(); @@ -45,11 +45,11 @@ describeBuilder(execute, UNIT_TEST_BUILDER_INFO, (harness) => { it('should use custom reporters and outputFile defined as an object in runnerConfig file', async () => { harness.useTarget('test', { ...BASE_OPTIONS, - runnerConfig: 'vitest.config.ts', + runnerConfig: 'vitest.config.mts', }); harness.writeFile( - 'vitest.config.ts', + 'vitest.config.mts', ` import { defineConfig } from 'vitest/config'; export default defineConfig({ @@ -71,12 +71,12 @@ describeBuilder(execute, UNIT_TEST_BUILDER_INFO, (harness) => { it('should preserve custom coverage options (e.g. clean: false) from runnerConfig file', async () => { harness.useTarget('test', { ...BASE_OPTIONS, - runnerConfig: 'vitest.config.ts', + runnerConfig: 'vitest.config.mts', coverage: true, }); harness.writeFile( - 'vitest.config.ts', + 'vitest.config.mts', ` import { defineConfig } from 'vitest/config'; export default defineConfig({ @@ -102,11 +102,11 @@ describeBuilder(execute, UNIT_TEST_BUILDER_INFO, (harness) => { it('should override reporters defined in runnerConfig file when CLI option is present', async () => { harness.useTarget('test', { ...BASE_OPTIONS, - runnerConfig: 'vitest.config.ts', + runnerConfig: 'vitest.config.mts', reporters: ['default'], }); - harness.writeFile('vitest.config.ts', VITEST_CONFIG_CONTENT); + harness.writeFile('vitest.config.mts', VITEST_CONFIG_CONTENT); const { result } = await harness.executeOnce(); expect(result?.success).toBeTrue(); @@ -117,12 +117,12 @@ describeBuilder(execute, UNIT_TEST_BUILDER_INFO, (harness) => { it('should use custom reportsDirectory defined in runnerConfig file', async () => { harness.useTarget('test', { ...BASE_OPTIONS, - runnerConfig: 'vitest.config.ts', + runnerConfig: 'vitest.config.mts', coverage: true, }); harness.writeFile( - 'vitest.config.ts', + 'vitest.config.mts', ` import { defineConfig } from 'vitest/config'; export default defineConfig({ @@ -144,11 +144,11 @@ describeBuilder(execute, UNIT_TEST_BUILDER_INFO, (harness) => { harness.useTarget('test', { ...BASE_OPTIONS, coverage: true, - runnerConfig: 'vitest.config.ts', + runnerConfig: 'vitest.config.mts', }); harness.writeFile( - 'vitest.config.ts', + 'vitest.config.mts', ` import { defineConfig } from 'vitest/config'; export default defineConfig({ @@ -167,11 +167,11 @@ describeBuilder(execute, UNIT_TEST_BUILDER_INFO, (harness) => { it('should enable coverage when set in runnerConfig file without builder option', async () => { harness.useTarget('test', { ...BASE_OPTIONS, - runnerConfig: 'vitest.config.ts', + runnerConfig: 'vitest.config.mts', }); harness.writeFile( - 'vitest.config.ts', + 'vitest.config.mts', ` import { defineConfig } from 'vitest/config'; export default defineConfig({ @@ -192,11 +192,11 @@ describeBuilder(execute, UNIT_TEST_BUILDER_INFO, (harness) => { it('should exclude test files based on runnerConfig file', async () => { harness.useTarget('test', { ...BASE_OPTIONS, - runnerConfig: 'vitest.config.ts', + runnerConfig: 'vitest.config.mts', }); harness.writeFile( - 'vitest.config.ts', + 'vitest.config.mts', ` import { defineConfig } from 'vitest/config'; export default defineConfig({ @@ -240,12 +240,12 @@ describeBuilder(execute, UNIT_TEST_BUILDER_INFO, (harness) => { harness.useTarget('test', { ...BASE_OPTIONS, coverage: true, - runnerConfig: 'vitest.config.ts', + runnerConfig: 'vitest.config.mts', coverageExclude: ['src/app/cli-excluded.ts'], }); harness.writeFile( - 'vitest.config.ts', + 'vitest.config.mts', ` import { defineConfig } from 'vitest/config'; export default defineConfig({ @@ -292,11 +292,11 @@ describeBuilder(execute, UNIT_TEST_BUILDER_INFO, (harness) => { it('should allow overriding globals to false via runnerConfig file', async () => { harness.useTarget('test', { ...BASE_OPTIONS, - runnerConfig: 'vitest.config.ts', + runnerConfig: 'vitest.config.mts', }); harness.writeFile( - 'vitest.config.ts', + 'vitest.config.mts', ` import { defineConfig } from 'vitest/config'; export default defineConfig({ @@ -325,11 +325,11 @@ describeBuilder(execute, UNIT_TEST_BUILDER_INFO, (harness) => { it('should initialize environment even when globals are disabled in runnerConfig file', async () => { harness.useTarget('test', { ...BASE_OPTIONS, - runnerConfig: 'vitest.config.ts', + runnerConfig: 'vitest.config.mts', }); harness.writeFile( - 'vitest.config.ts', + 'vitest.config.mts', ` import { defineConfig } from 'vitest/config'; export default defineConfig({ @@ -357,11 +357,11 @@ describeBuilder(execute, UNIT_TEST_BUILDER_INFO, (harness) => { it('should fail when a DOM-dependent test is run in a node environment', async () => { harness.useTarget('test', { ...BASE_OPTIONS, - runnerConfig: 'vitest.config.ts', + runnerConfig: 'vitest.config.mts', }); harness.writeFile( - 'vitest.config.ts', + 'vitest.config.mts', ` import { defineConfig } from 'vitest/config'; export default defineConfig({ @@ -379,11 +379,11 @@ describeBuilder(execute, UNIT_TEST_BUILDER_INFO, (harness) => { it('should warn and ignore "test.projects" option from runnerConfig file', async () => { harness.useTarget('test', { ...BASE_OPTIONS, - runnerConfig: 'vitest.config.ts', + runnerConfig: 'vitest.config.mts', }); harness.writeFile( - 'vitest.config.ts', + 'vitest.config.mts', ` import { defineConfig } from 'vitest/config'; export default defineConfig({ @@ -411,11 +411,11 @@ describeBuilder(execute, UNIT_TEST_BUILDER_INFO, (harness) => { it('should warn and ignore "test.include" option from runnerConfig file', async () => { harness.useTarget('test', { ...BASE_OPTIONS, - runnerConfig: 'vitest.config.ts', + runnerConfig: 'vitest.config.mts', }); harness.writeFile( - 'vitest.config.ts', + 'vitest.config.mts', ` import { defineConfig } from 'vitest/config'; export default defineConfig({ @@ -444,11 +444,11 @@ describeBuilder(execute, UNIT_TEST_BUILDER_INFO, (harness) => { harness.useTarget('test', { ...BASE_OPTIONS, watch: false, - runnerConfig: 'vitest.config.ts', + runnerConfig: 'vitest.config.mts', }); harness.writeFile( - 'vitest.config.ts', + 'vitest.config.mts', ` import { defineConfig } from 'vitest/config'; export default defineConfig({ @@ -476,11 +476,11 @@ describeBuilder(execute, UNIT_TEST_BUILDER_INFO, (harness) => { it('should warn about performance when "test.exclude" option is in runnerConfig file', async () => { harness.useTarget('test', { ...BASE_OPTIONS, - runnerConfig: 'vitest.config.ts', + runnerConfig: 'vitest.config.mts', }); harness.writeFile( - 'vitest.config.ts', + 'vitest.config.mts', ` import { defineConfig } from 'vitest/config'; export default defineConfig({ @@ -508,11 +508,11 @@ describeBuilder(execute, UNIT_TEST_BUILDER_INFO, (harness) => { it(`should append "test.setupFiles" (string) from runnerConfig to the CLI's setup`, async () => { harness.useTarget('test', { ...BASE_OPTIONS, - runnerConfig: 'vitest.config.ts', + runnerConfig: 'vitest.config.mts', }); harness.writeFile( - 'vitest.config.ts', + 'vitest.config.mts', ` import { defineConfig } from 'vitest/config'; export default defineConfig({ @@ -542,11 +542,11 @@ describeBuilder(execute, UNIT_TEST_BUILDER_INFO, (harness) => { it(`should append "test.setupFiles" (array) from runnerConfig to the CLI's setup`, async () => { harness.useTarget('test', { ...BASE_OPTIONS, - runnerConfig: 'vitest.config.ts', + runnerConfig: 'vitest.config.mts', }); harness.writeFile( - 'vitest.config.ts', + 'vitest.config.mts', ` import { defineConfig } from 'vitest/config'; export default defineConfig({ @@ -578,11 +578,11 @@ describeBuilder(execute, UNIT_TEST_BUILDER_INFO, (harness) => { it('should merge and apply custom Vite plugins from runnerConfig file', async () => { harness.useTarget('test', { ...BASE_OPTIONS, - runnerConfig: 'vitest.config.ts', + runnerConfig: 'vitest.config.mts', }); harness.writeFile( - 'vitest.config.ts', + 'vitest.config.mts', ` import { defineConfig } from 'vitest/config'; export default defineConfig({ diff --git a/packages/angular/build/src/builders/unit-test/tests/behavior/vitest-shared-chunk-init_spec.ts b/packages/angular/build/src/builders/unit-test/tests/behavior/vitest-shared-chunk-init_spec.ts index afccfc2c06e1..1cddec79a14d 100644 --- a/packages/angular/build/src/builders/unit-test/tests/behavior/vitest-shared-chunk-init_spec.ts +++ b/packages/angular/build/src/builders/unit-test/tests/behavior/vitest-shared-chunk-init_spec.ts @@ -16,28 +16,11 @@ import { describeBuilder(execute, UNIT_TEST_BUILDER_INFO, (harness) => { describe('Behavior: "Vitest shared chunk initialization"', () => { - // Regression test for https://github.com/angular/angular-cli/issues/33728. - // - // Without `disableCodeSplitting`, esbuild hoists a module imported by more than one spec - // entry point into a shared chunk behind a lazy `__esm` initializer, and a class-field - // initializer in another chunk reads the exported value as `undefined` under the jsdom - // runner. All four trigger conditions are required and encoded below: - // 1. two spec entry points import the shared module (so it lands in a shared chunk); - // 2. a component in one entry reads the export during class-field initialization; - // 3. that component's spec file contains an `async` test callback (no `await` needed); - // 4. zone.js is in the polyfills (the `setupApplicationTarget` default), which downlevels - // async and makes esbuild emit the spec entry CommonJS-wrapped. - // - // NOTE: the failure this guards against is sensitive to inert content — adding a top-level - // side effect (even a `console.log`) to the shared or importing module below defused it - // during reduction. Mirror https://github.com/jonmarozick/ng-shared-chunk-repro when - // modifying these fixtures. it('should provide shared-module exports to class-field initializers in async specs', async () => { setupApplicationTarget(harness); harness.useTarget('test', { ...BASE_OPTIONS, - splitting: false, }); // Keep the default project's spec deterministic; a third spec entry that does not touch diff --git a/packages/angular/build/src/builders/unit-test/tests/options/isolate_spec.ts b/packages/angular/build/src/builders/unit-test/tests/options/isolate_spec.ts index a37bf597e91a..28fbb855a91f 100644 --- a/packages/angular/build/src/builders/unit-test/tests/options/isolate_spec.ts +++ b/packages/angular/build/src/builders/unit-test/tests/options/isolate_spec.ts @@ -57,7 +57,7 @@ describeBuilder(execute, UNIT_TEST_BUILDER_INFO, (harness) => { it('should override isolate from the Vitest config file when set to false', async () => { harness.writeFile( - 'vitest-base.config.ts', + 'vitest-base.config.mts', ` import { defineConfig } from 'vitest/config'; diff --git a/packages/angular/build/src/builders/unit-test/tests/options/runner-config-coverage_spec.ts b/packages/angular/build/src/builders/unit-test/tests/options/runner-config-coverage_spec.ts index c46c38da79ad..9998caea72e3 100644 --- a/packages/angular/build/src/builders/unit-test/tests/options/runner-config-coverage_spec.ts +++ b/packages/angular/build/src/builders/unit-test/tests/options/runner-config-coverage_spec.ts @@ -23,7 +23,7 @@ describeBuilder(execute, UNIT_TEST_BUILDER_INFO, (harness) => { describe('Vitest Runner', () => { it('should preserve thresholds from Vitest config when not overridden by CLI', async () => { harness.writeFile( - 'vitest-base.config.ts', + 'vitest-base.config.mts', ` import { defineConfig } from 'vitest/config'; export default defineConfig({ @@ -52,7 +52,7 @@ describeBuilder(execute, UNIT_TEST_BUILDER_INFO, (harness) => { it('should override Vitest config thresholds with CLI thresholds', async () => { harness.writeFile( - 'vitest-base.config.ts', + 'vitest-base.config.mts', ` import { defineConfig } from 'vitest/config'; export default defineConfig({ @@ -84,7 +84,7 @@ describeBuilder(execute, UNIT_TEST_BUILDER_INFO, (harness) => { it('should merge partial CLI thresholds with Vitest config thresholds', async () => { harness.writeFile( - 'vitest-base.config.ts', + 'vitest-base.config.mts', ` import { defineConfig } from 'vitest/config'; export default defineConfig({ diff --git a/packages/angular/build/src/builders/unit-test/tests/options/runner-config_spec.ts b/packages/angular/build/src/builders/unit-test/tests/options/runner-config_spec.ts index b061b88e990c..fa467f21e174 100644 --- a/packages/angular/build/src/builders/unit-test/tests/options/runner-config_spec.ts +++ b/packages/angular/build/src/builders/unit-test/tests/options/runner-config_spec.ts @@ -31,10 +31,10 @@ describeBuilder(execute, UNIT_TEST_BUILDER_INFO, (harness) => { describe('Vitest Runner', () => { it('should use a specified config file path', async () => { - harness.writeFile('custom-vitest.config.ts', VITEST_CONFIG_CONTENT); + harness.writeFile('custom-vitest.config.mts', VITEST_CONFIG_CONTENT); harness.useTarget('test', { ...BASE_OPTIONS, - runnerConfig: 'custom-vitest.config.ts', + runnerConfig: 'custom-vitest.config.mts', }); const { result } = await harness.executeOnce(); @@ -44,7 +44,7 @@ describeBuilder(execute, UNIT_TEST_BUILDER_INFO, (harness) => { }); it('should search for a config file when `true`', async () => { - harness.writeFile('vitest-base.config.ts', VITEST_CONFIG_CONTENT); + harness.writeFile('vitest-base.config.mts', VITEST_CONFIG_CONTENT); harness.useTarget('test', { ...BASE_OPTIONS, runnerConfig: true, @@ -57,7 +57,7 @@ describeBuilder(execute, UNIT_TEST_BUILDER_INFO, (harness) => { }); it('should ignore config file when `false`', async () => { - harness.writeFile('vitest-base.config.ts', VITEST_CONFIG_CONTENT); + harness.writeFile('vitest-base.config.mts', VITEST_CONFIG_CONTENT); harness.useTarget('test', { ...BASE_OPTIONS, runnerConfig: false, @@ -70,7 +70,7 @@ describeBuilder(execute, UNIT_TEST_BUILDER_INFO, (harness) => { }); it('should ignore config file by default', async () => { - harness.writeFile('vitest-base.config.ts', VITEST_CONFIG_CONTENT); + harness.writeFile('vitest-base.config.mts', VITEST_CONFIG_CONTENT); harness.useTarget('test', { ...BASE_OPTIONS, }); @@ -98,7 +98,7 @@ describeBuilder(execute, UNIT_TEST_BUILDER_INFO, (harness) => { // This file should be ignored because the new logic looks for `vitest-base.config.*`. harness.writeFile('vitest.config.ts', VITEST_CONFIG_CONTENT); // The workspace root is the directory containing the project root in the test harness. - harness.writeFile('vitest-base.config.js', VITEST_CONFIG_CONTENT); + harness.writeFile('vitest-base.config.mjs', VITEST_CONFIG_CONTENT); harness.useTarget('test', { ...BASE_OPTIONS, runnerConfig: true, @@ -113,7 +113,7 @@ describeBuilder(execute, UNIT_TEST_BUILDER_INFO, (harness) => { it('should fallback to in-memory config when no base config is found', async () => { // This file should be ignored because the new logic looks for `vitest-base.config.*` // and when `runnerConfig` is true, it should not fall back to the default search. - harness.writeFile('vitest.config.ts', VITEST_CONFIG_CONTENT); + harness.writeFile('vitest.config.mts', VITEST_CONFIG_CONTENT); harness.useTarget('test', { ...BASE_OPTIONS, runnerConfig: true, diff --git a/packages/schematics/angular/config/files/vitest-base.config.ts.template b/packages/schematics/angular/config/files/vitest-base.config.mts.template similarity index 100% rename from packages/schematics/angular/config/files/vitest-base.config.ts.template rename to packages/schematics/angular/config/files/vitest-base.config.mts.template diff --git a/packages/schematics/angular/config/index.ts b/packages/schematics/angular/config/index.ts index 73818699a134..131ab6dc1ceb 100644 --- a/packages/schematics/angular/config/index.ts +++ b/packages/schematics/angular/config/index.ts @@ -72,7 +72,7 @@ function addVitestConfig(options: ConfigOptions): Rule { if (testTarget.options.runner === 'karma') { context.logger.warn( `The "test" target is configured to use the "karma" runner in the main options.` + - ' The generated "vitest-base.config.ts" file may not be used.', + ' The generated "vitest-base.config.mts" file may not be used.', ); } @@ -85,14 +85,14 @@ function addVitestConfig(options: ConfigOptions): Rule { ) { context.logger.warn( `The "test" target's "${name}" configuration is configured to use the "karma" runner.` + - ' The generated "vitest-base.config.ts" file may not be used for that configuration.', + ' The generated "vitest-base.config.mts" file may not be used for that configuration.', ); } } return mergeWith( apply(url('./files'), [ - filter((p) => p.endsWith('vitest-base.config.ts.template')), + filter((p) => p.endsWith('vitest-base.config.mts.template')), applyTemplates({}), move(project.root), ]), diff --git a/packages/schematics/angular/config/index_spec.ts b/packages/schematics/angular/config/index_spec.ts index bc1715c4866a..a76c4e70567d 100644 --- a/packages/schematics/angular/config/index_spec.ts +++ b/packages/schematics/angular/config/index_spec.ts @@ -194,9 +194,9 @@ describe('Config Schematic', () => { applicationTree.overwrite('angular.json', JSON.stringify(angularJson)); }); - it('should create a vitest-base.config.ts file', async () => { + it('should create a vitest-base.config.mts file', async () => { const tree = await runConfigSchematic(ConfigType.Vitest); - expect(tree.exists('projects/foo/vitest-base.config.ts')).toBeTrue(); + expect(tree.exists('projects/foo/vitest-base.config.mts')).toBeTrue(); }); it(`should set 'runnerConfig' in test builder`, async () => { diff --git a/packages/schematics/angular/migrations/migrate-karma-to-vitest/karma-processor.ts b/packages/schematics/angular/migrations/migrate-karma-to-vitest/karma-processor.ts index 43e64eb2033a..a02eb01f8bdd 100644 --- a/packages/schematics/angular/migrations/migrate-karma-to-vitest/karma-processor.ts +++ b/packages/schematics/angular/migrations/migrate-karma-to-vitest/karma-processor.ts @@ -163,7 +163,7 @@ export async function processKarmaConfig( context.logger.warn( `Project "${projectName}" uses a custom Karma configuration file "${karmaConfig}". ` + `Tests have been migrated to use Vitest, but you may need to manually migrate custom settings ` + - `from this Karma config to a Vitest config (e.g. "vitest-base.config.ts") ` + + `from this Karma config to a Vitest config (e.g. "vitest-base.config.mts") ` + `and set the "runnerConfig" option to true.`, ); manualMigrationFiles.push(karmaConfig); diff --git a/packages/schematics/angular/utility/latest-versions/package.json b/packages/schematics/angular/utility/latest-versions/package.json index 41ba63058ad4..30a45ad40fe2 100644 --- a/packages/schematics/angular/utility/latest-versions/package.json +++ b/packages/schematics/angular/utility/latest-versions/package.json @@ -25,12 +25,12 @@ "@tailwindcss/postcss": "^4.1.12", "tslib": "^2.3.0", "typescript": "~6.0.2", - "vitest": "^4.0.8", - "@vitest/coverage-v8": "^4.0.8", - "@vitest/coverage-istanbul": "^4.0.8", - "@vitest/browser-playwright": "^4.0.8", - "@vitest/browser-webdriverio": "^4.0.8", - "@vitest/browser-preview": "^4.0.8", + "vitest": "^5.0.0", + "@vitest/coverage-v8": "^5.0.0", + "@vitest/coverage-istanbul": "^5.0.0", + "@vitest/browser-playwright": "^5.0.0", + "@vitest/browser-webdriverio": "^5.0.0-rc.1", + "@vitest/browser-preview": "^5.0.0", "playwright": "^1.48.0", "webdriverio": "^9.0.0", "zone.js": "~0.16.0" diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index d552878ec912..4dc40c6fb6f3 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -293,8 +293,8 @@ importers: specifier: workspace:* version: link:../../../packages/angular/ssr '@vitest/coverage-v8': - specifier: 4.1.11 - version: 4.1.11(vitest@4.1.11) + specifier: 5.0.0 + version: 5.0.0(vitest@5.0.0) browser-sync: specifier: 3.0.4 version: 3.0.4(bufferutil@4.1.0)(debug@4.4.3(supports-color@11.0.0))(supports-color@11.0.0)(utf-8-validate@6.0.6) @@ -311,8 +311,8 @@ importers: specifier: 7.8.2 version: 7.8.2 vitest: - specifier: 4.1.11 - version: 4.1.11(@opentelemetry/api@1.9.1)(@types/node@22.20.1)(@vitest/coverage-v8@4.1.11)(esbuild@0.28.2)(jiti@2.7.0)(jsdom@30.0.1)(less@4.9.0(supports-color@11.0.0))(sass-embedded@1.103.1)(sass@1.103.1)(terser@5.51.2)(tsx@4.23.13)(yaml@2.9.0) + specifier: 5.0.0 + version: 5.0.0(@opentelemetry/api@1.9.1)(@types/node@22.20.1)(@vitest/coverage-v8@5.0.0)(jsdom@30.0.1)(vite@8.2.2(@types/node@22.20.1)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.0(supports-color@11.0.0))(sass-embedded@1.103.1)(sass@1.103.1)(terser@5.51.2)(tsx@4.23.13)(yaml@2.9.0)) packages/angular/build: dependencies: @@ -429,8 +429,8 @@ importers: specifier: 7.8.2 version: 7.8.2 vitest: - specifier: 4.1.11 - version: 4.1.11(@opentelemetry/api@1.9.1)(@types/node@22.20.1)(@vitest/coverage-v8@4.1.11)(esbuild@0.28.2)(jiti@2.7.0)(jsdom@30.0.1)(less@4.9.0(supports-color@11.0.0))(sass-embedded@1.103.1)(sass@1.103.1)(terser@5.51.2)(tsx@4.23.13)(yaml@2.9.0) + specifier: 5.0.0 + version: 5.0.0(@opentelemetry/api@1.9.1)(@types/node@22.20.1)(@vitest/coverage-v8@5.0.0)(jsdom@30.0.1)(vite@8.2.2(@types/node@22.20.1)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.0(supports-color@11.0.0))(sass-embedded@1.103.1)(sass@1.103.1)(terser@5.51.2)(tsx@4.23.13)(yaml@2.9.0)) optionalDependencies: lmdb: specifier: 3.5.6 @@ -2811,48 +2811,97 @@ packages: resolution: {integrity: sha512-eSYWTm620tTk45EKSedaUL8MFYI8hW164hIXsgIHyxu3VobUB3fFCu5t0hQby6OoWRPsG1KkKUG2M5UadiLiVg==} engines: {node: '>=14'} + '@oxc-parser/binding-android-arm-eabi@0.147.0': + resolution: {integrity: sha512-fOtoGvIoirkvxQVw9J1WJPxz571XPgLsPf9uhRD+PJteUnvrJHMDmK9pw2yZEGGyismtRoEsp+JcXUdF/JDMDw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm] + os: [android] + '@oxc-parser/binding-android-arm-eabi@0.148.0': resolution: {integrity: sha512-pHASv9g5pASxb7akHERZNSkrEqPhFaUix98o7d9hbTpolnnFWl7UiRrcMhCsV1+iVO4/cJwKsbKRJTFNs2tdBQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm] os: [android] + '@oxc-parser/binding-android-arm64@0.147.0': + resolution: {integrity: sha512-emjQHOYJaomo4ykaXQ1EItunr/I94Nk01oqBmU4dSkKSTupIDx6OysVDf2e8Eytm77rb+4ZxzgElyWP7rcEX7A==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [android] + '@oxc-parser/binding-android-arm64@0.148.0': resolution: {integrity: sha512-sg/6Ez0KdAygsu0POELux9wN1Po2CP93WY8eNl4DBKIGprsd4QSHBXOb471Pu9i2OCD5sLkISSb2agZEhVn2Zw==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [android] + '@oxc-parser/binding-darwin-arm64@0.147.0': + resolution: {integrity: sha512-kXvBPJL7RmDPJ2mze/vXPPVQimCDtFr9OFLjf7dyhV5Dx64cgcXh9KKrA1sMWvCObvJll9CZZUO0FBlFwD0l6A==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [darwin] + '@oxc-parser/binding-darwin-arm64@0.148.0': resolution: {integrity: sha512-yiSJmzGUvCUaJT8X3j40gVcX+ckuHQMuiOtF8DvzTs5+JtB/7XuHFPp4M+vv5u+HlBtDUd4Ks5pyHpWz8mfnkg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [darwin] + '@oxc-parser/binding-darwin-x64@0.147.0': + resolution: {integrity: sha512-mgFF8pLU6R64LbT27lSrtVRspVC/3IcZ0qyIikzmi78Y3Ik2OPnlAHHI0UEBRcC3qmNgtjaef7zkFt7/uPxIcw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [darwin] + '@oxc-parser/binding-darwin-x64@0.148.0': resolution: {integrity: sha512-6ZeklaamrMy4H2JmhvcJg6iip59tYILtuLaILxyAHT3l5FDxnI5ihVievAft5ZmAbqtlWHErOi1OpJK8gy1wcA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [darwin] + '@oxc-parser/binding-freebsd-x64@0.147.0': + resolution: {integrity: sha512-v38aiF11qufOTBcCAKL4skgQf0zJ4NEvRlivq7B5kHrlyvjCLjvNrMtNWDTz1SDUL6/xVsJRmLDxv2e+Cp4oWw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [freebsd] + '@oxc-parser/binding-freebsd-x64@0.148.0': resolution: {integrity: sha512-vFsPx+a/qFECPnz/H8nC6x6MDvnWscLTCo/5muojEF54ERUq1kdgbvnWo95YnkhjF9sTIcG/uDxQBh1gffaufQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [freebsd] + '@oxc-parser/binding-linux-arm-gnueabihf@0.147.0': + resolution: {integrity: sha512-AeIiBbwUaP0H1+4/qGW9l5qHecS/+XA5iMuieVcGb1T+tyc2dVGspFW13BWk/XrLsiGP/CiDJTJqAPLLCzZHkw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm] + os: [linux] + '@oxc-parser/binding-linux-arm-gnueabihf@0.148.0': resolution: {integrity: sha512-eOr3M+6iGbbxNL4PSS0VtsyQ2eOUxSBh00BqO22SbolDimPSYsBuLr/LCrZBkiqW2BoabhR6V4R8jrRAay7hjg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm] os: [linux] + '@oxc-parser/binding-linux-arm-musleabihf@0.147.0': + resolution: {integrity: sha512-/41MKPW4RgPY4DJco0NCF0RYX3IMZaVlRNMNzvhaxRavc7tN3Txm+qllZbh0aMRs0VHdgUlbI8TcAOiTai4TKg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm] + os: [linux] + '@oxc-parser/binding-linux-arm-musleabihf@0.148.0': resolution: {integrity: sha512-58ZKDw0mQRbCNfrd2IDyV4o8T7enzGERJn41BH2tjrZVGyiKiFzcfDicuB7Zcpb/1xIOrObovr8Dja6lZi8dLw==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm] os: [linux] + '@oxc-parser/binding-linux-arm64-gnu@0.147.0': + resolution: {integrity: sha512-bmpw/RPhVXgZbtb3xBDuwW5s8+LvZYdqcDSX/sP2ltL77aTio3DP/B5ZTwwgoJ6Mr9vJs4RrmgEKW9XkLNUU1g==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [linux] + libc: [glibc] + '@oxc-parser/binding-linux-arm64-gnu@0.148.0': resolution: {integrity: sha512-Fnu95O4eZ5i++GPvIzBEZ8y4ddTLR+D9paYa8JRaRk6ZK7nHQiWP5xtrhcPQsXqgat1d7sU/d5rbbI0p1FTHSQ==} engines: {node: ^20.19.0 || >=22.12.0} @@ -2860,6 +2909,13 @@ packages: os: [linux] libc: [glibc] + '@oxc-parser/binding-linux-arm64-musl@0.147.0': + resolution: {integrity: sha512-gd7VX/FDVOw6mjQcu45iIcp4QkgybgJwh3a0OFG2NxmPCj628mQWD96QGu1kK8+mZF9qK4b/gIEyC63vQoB7+Q==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [linux] + libc: [musl] + '@oxc-parser/binding-linux-arm64-musl@0.148.0': resolution: {integrity: sha512-3CQy/BMdx7N7H3qrcPxUL+a2CwUZodUcf6oq8iJuNZ9C6Ol1aq3mcWzsgySJ7CHFLvpX21ZDPp1r1X0QLbu/AQ==} engines: {node: ^20.19.0 || >=22.12.0} @@ -2867,6 +2923,13 @@ packages: os: [linux] libc: [musl] + '@oxc-parser/binding-linux-ppc64-gnu@0.147.0': + resolution: {integrity: sha512-HnAzcfki7dSUNHf510Q2NmbJlz8Ys7rn8l9l588Pkx0tYe1BHLZnmELIgqizJ4WPhHGSwN8Ce+B/menVxS3odA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [ppc64] + os: [linux] + libc: [glibc] + '@oxc-parser/binding-linux-ppc64-gnu@0.148.0': resolution: {integrity: sha512-9LkaYvfiF8hMOw900csAvkf1oxE8XlmMeGowu5BcastSSwV8mKvKRMNU7HsV+ycyj1dQD8pX5qgOw8ja6SJacg==} engines: {node: ^20.19.0 || >=22.12.0} @@ -2874,6 +2937,13 @@ packages: os: [linux] libc: [glibc] + '@oxc-parser/binding-linux-riscv64-gnu@0.147.0': + resolution: {integrity: sha512-qlkOL6wT44U+fT5s/+sR6Shx0OdwvQF83JyIPZUxG/ovqZF5/7atOtjH+JPZ5/7ATQLbFBBSmghcy/+2NVB/ew==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [riscv64] + os: [linux] + libc: [glibc] + '@oxc-parser/binding-linux-riscv64-gnu@0.148.0': resolution: {integrity: sha512-2GBiM9h26dR4WJfhoMvnFMnFLf7m/kYs4UMqjvrOfQG4BV1nuTJDH22Zc2MQr3INZF7nSKYQ6xlhD3hQ7A6gug==} engines: {node: ^20.19.0 || >=22.12.0} @@ -2881,6 +2951,13 @@ packages: os: [linux] libc: [glibc] + '@oxc-parser/binding-linux-riscv64-musl@0.147.0': + resolution: {integrity: sha512-DlefD7L7sMXs/3hIBH23Egk0phj8kG0SA81dVGOQ3S1ekjOlmTLH2E+F2Thwfh1slKx6aH+lNc5fQYAw0GU7/g==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [riscv64] + os: [linux] + libc: [musl] + '@oxc-parser/binding-linux-riscv64-musl@0.148.0': resolution: {integrity: sha512-uPqZexvKJmEgq4mAu36qe2xTfXZE7oyik1R7KtZ5tl8qKlq1U1fIqTFRUEBZqRGvforoTrGIpatRzcoPKO66RA==} engines: {node: ^20.19.0 || >=22.12.0} @@ -2888,6 +2965,13 @@ packages: os: [linux] libc: [musl] + '@oxc-parser/binding-linux-s390x-gnu@0.147.0': + resolution: {integrity: sha512-Xqpagk/031IvZ4svrk2FF01YEqM/iN3MJV3SVZadKg/CsGlDCGoREqKHXYnoV5+8SfGe/m6RM1szXFLusTu/Uw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [s390x] + os: [linux] + libc: [glibc] + '@oxc-parser/binding-linux-s390x-gnu@0.148.0': resolution: {integrity: sha512-9oUHvnTbp7ZraFsTC8PN6XhdhPSSxZumYvixWl7Smi353gEULvK6yV0sXNVrdFMHQeaDKFCi8TgDhNK7/A+Y+Q==} engines: {node: ^20.19.0 || >=22.12.0} @@ -2895,6 +2979,13 @@ packages: os: [linux] libc: [glibc] + '@oxc-parser/binding-linux-x64-gnu@0.147.0': + resolution: {integrity: sha512-QioQOeUbI4ATUr0S2z88uA3Cds2R3Mm5Ge7U8XNYtlTb2GJF3rWlcj70z0AJhhOlbdm0YgVjqPBldUNbFylDIg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [linux] + libc: [glibc] + '@oxc-parser/binding-linux-x64-gnu@0.148.0': resolution: {integrity: sha512-2qhDSJwKzbSZzF7lDqqk8sr/yXsmwr3PeUa4/nazIF+zFAYz1gVPEfC34GQtGxzJUUmklaYAL63368LEfrMeyw==} engines: {node: ^20.19.0 || >=22.12.0} @@ -2902,6 +2993,13 @@ packages: os: [linux] libc: [glibc] + '@oxc-parser/binding-linux-x64-musl@0.147.0': + resolution: {integrity: sha512-NXy1tv/OdC+pPTwf9RiCZWPK53V/Xq/2cjSnjOSyKopajdaDqMIkgtDY+jXZemp2e8px5FeWfY2L2LwhKZQovg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [linux] + libc: [musl] + '@oxc-parser/binding-linux-x64-musl@0.148.0': resolution: {integrity: sha512-qQoPDZUFV0bh9xA09XydmkjMBpgc1ukJuhMvzQ9QeVmFaHTS9W5TE5CoLmSl3QQyUP9OuHO3x/WPZTIIZPWR3Q==} engines: {node: ^20.19.0 || >=22.12.0} @@ -2909,30 +3007,57 @@ packages: os: [linux] libc: [musl] + '@oxc-parser/binding-openharmony-arm64@0.147.0': + resolution: {integrity: sha512-GpGWZ6oKz4bjCWW9Mz5pCaGPyk2Aaze6zEoaslIQqpSLtpx5pXj/ap5gUNb5Jn2LIbqWyjkGLX9yv3NMuNcBVQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [openharmony] + '@oxc-parser/binding-openharmony-arm64@0.148.0': resolution: {integrity: sha512-1UGbaQWEXUCLqAmaR5kwRDjx/R4S5LQKZkM9CHmaHkuKhriOF32aRLfS0jCRNE2yGQJLMEA1z9UucbBVqjXnDw==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [openharmony] + '@oxc-parser/binding-win32-arm64-msvc@0.147.0': + resolution: {integrity: sha512-a8mlt7CC8z7LUdCfaxhff4kCd+vSjE+NEFL0cxA8ukfuSnvAto/pWTjytW4BuVLnQGcCVdHJwcRKOfs++H+tjw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [win32] + '@oxc-parser/binding-win32-arm64-msvc@0.148.0': resolution: {integrity: sha512-pWKdzRDNG2+NK4h/V6U/CYERcfYD6u28h5IB/VJVsrZaD3muvE58tUj22lieL5vLZ+XFi1GPv9YXckZbJZ9BLA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [win32] + '@oxc-parser/binding-win32-ia32-msvc@0.147.0': + resolution: {integrity: sha512-M5ViVDBcFLnl2632AuuWuP35zEL5oikK1jTx8r3+902VEDeSNHxFZAB6RZyfZ7MU6Oi5QTOG8MmMkIeHsudSaw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [ia32] + os: [win32] + '@oxc-parser/binding-win32-ia32-msvc@0.148.0': resolution: {integrity: sha512-i3p4x+mvwtjcE1J5HM6V7ggsbXiznExN/4MkNyOy3dfXrVV3bnkSfmZxvo6/84qCVX4ShkpNE1SKt9biIF31GQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [ia32] os: [win32] + '@oxc-parser/binding-win32-x64-msvc@0.147.0': + resolution: {integrity: sha512-DUaE13OwnUSlHpLZNcC/nuT10ivlWqc5EZgsfgXuAmWYw0r3nDxGeLD1zlGwYwIgVk1/ZMAxoXpV+05stvbHaA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [win32] + '@oxc-parser/binding-win32-x64-msvc@0.148.0': resolution: {integrity: sha512-Ye6vB7VQulghWYkYkECOBYFRVEizz4XyRTUAv+t8BuyurhKU7uD0P9eowL+mKG5Mf8MSYx+DI3Cm8SKZvYG7bQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [win32] + '@oxc-project/types@0.147.0': + resolution: {integrity: sha512-IJ3s6ltHLp45S0bh7phkX+gJO7A1Wuz2EaqpAhb8WjqDwbzMiWKHhyyT42tskaWjEYXtHtVCPpnBJVT9+dcRLg==} + '@oxc-project/types@0.148.0': resolution: {integrity: sha512-Nm4s/jB+4FpFsPhWGEC4h7rzksesmtnMXomo6rCMcg/b8zLQuOziRgkCS1fxDCXOlJB/6Q8oABOZ/OP6RIPj9A==} @@ -3765,20 +3890,25 @@ packages: peerDependencies: vite: ^6.0.0 || ^7.0.0 || ^8.0.0 - '@vitest/coverage-v8@4.1.11': - resolution: {integrity: sha512-8MVGEFnJIcdGjcbfKmeq8z0pZHH0JlVtoVZH9Q/qwUp6wyFnEJUBMrw9DCaj+ra3vShGmhavjalMIhPNxZAUcw==} + '@vitest/coverage-v8@5.0.0': + resolution: {integrity: sha512-toMg6PZGCIa/lQNCDoASrfb1ly4hsUKXFtFYC9kD4t78o5Y6LyNJU7AENt8eHPr3quYdxaxK7hj2mnbFfUk9NA==} peerDependencies: - '@vitest/browser': 4.1.11 - vitest: 4.1.11 + '@vitest/browser': 5.0.0 + vitest: 5.0.0 peerDependenciesMeta: '@vitest/browser': optional: true - '@vitest/expect@4.1.11': - resolution: {integrity: sha512-VX2x5vNJXET47KAFzwERI+KRMtTTCSWTfSMKsW7JsUsXV4psq++e3DvZpuTDOpHcxytiDs6p2nhVb2tVDiiUYw==} + '@vitest/istanbul-lib-coverage@1.0.1': + resolution: {integrity: sha512-k3DJZ8LhMBK9NS4SclF1ASD3OgXEWDorbIcPTRDK0/Zae6fRvu+fJRxtFdLfHsa9Y24beCdPnoNZ4LviTNstfA==} + engines: {node: '>=22'} + + '@vitest/istanbul-lib-report@1.0.1': + resolution: {integrity: sha512-1EOLRfsTMnyAr3+kEAsP4o9dhaDlGPpD7H5iLBBeq//YpNB1VIahkPhB+eRp9N2Dkfw8oySROjE3yf9XDeaIkQ==} + engines: {node: '>=22'} - '@vitest/mocker@4.1.11': - resolution: {integrity: sha512-2XJVD55d1o5AZous5CCGKS74g/riOj9odEt2bQpCVZeblHyHdnMeFl4jl0XjU21stf4mbjUkew2eXQZt65g5CQ==} + '@vitest/mocker@5.0.0': + resolution: {integrity: sha512-66PGTMIiVJP3t4a5yxU9qPtf7MdTBs8jmToMvy+HVflB3Yy13WJZTtPePdvU+wjRV02SKK5doLbSA6o9pwOmiA==} peerDependencies: msw: ^2.4.9 vite: ^6.0.0 || ^7.0.0 || ^8.0.0 @@ -3788,20 +3918,8 @@ packages: vite: optional: true - '@vitest/pretty-format@4.1.11': - resolution: {integrity: sha512-yiZzPbGTS9Sr/JpFl8zHrcIkAofNbFV6k21vIgQN/cY/oxZeXhJv5sc/MBJ5jFKWmWs+oJHw0UXLZjmf931+Vw==} - - '@vitest/runner@4.1.11': - resolution: {integrity: sha512-LztvUgdwMNJMIkj3hQnnxiC2Xy1zNxq928W/xhjCLaNCzqTZOudjwbQf6v9IntZGPw132i2Lq2rgTRZHD3JHNw==} - - '@vitest/snapshot@4.1.11': - resolution: {integrity: sha512-pN7ikn1ON7h8ee4gIAp4AzyK+zBtJPzVbqOgu5LCEh4VaJVbPQcgYQYJIMGQPXVeJJq1fnfazis7a5pFNPahog==} - - '@vitest/spy@4.1.11': - resolution: {integrity: sha512-apNa/prQy2qCeywhnixOHPRCgGNhvg7T4Dapfl1GahLp/R+uhBm5cPyFoNVyqsNd2h1nJxL6BqqdIjiABL60YA==} - - '@vitest/utils@4.1.11': - resolution: {integrity: sha512-zTCVGpyFsGWBhllOyKlTw/vnr6D9qxsfSDyfbyZmTyjHw5N/VuvzHpHoQjm2ZJzn4RJgx5w4r7V0er69CmLgPQ==} + '@vitest/spy@5.0.0': + resolution: {integrity: sha512-uy+luWBAPw9XfthoHi5AkfHUnuPYEESjl0p/r+meoBnU8bxg5GDQ3Ey8MjcJ6sqahkL4PFyrvfMJJBw7LbU06g==} '@webassemblyjs/ast@1.14.1': resolution: {integrity: sha512-nuBEDgQfm1ccRp/8bCQrx1frohyufl4JlbMMZ4P1wpeOfDhF6FQkxZJ1b/e+PLwr6X1Nhw6OLme5usuBWYBvuQ==} @@ -6722,6 +6840,10 @@ packages: resolution: {integrity: sha512-19YVAg7T+WTrxggPukVq7DjTv6+PJ867TmhCvBsYwmbFCsZd344rq2Ld1p0wo8f8Qrrhgp82c6FJRqdXWtSEhg==} engines: {node: '>= 0.4'} + oxc-parser@0.147.0: + resolution: {integrity: sha512-5xaug6t7GfV3BO5Iv+xHW1rmQkDEQ3BEu3L8g3InsvWO5i8CYGc4tCZ2X985QcwWNycFJam+aOns6Nr2XAThTA==} + engines: {node: ^20.19.0 || >=22.12.0} + oxc-parser@0.148.0: resolution: {integrity: sha512-syxUKHeUll89RIABQADcI7sikYrwyssvA6gj4phSSIPezKVM8yMaLAiLLSc7fmzVvrwybfFGFbW5zme9sX87rg==} engines: {node: ^20.19.0 || >=22.12.0} @@ -6818,9 +6940,6 @@ packages: resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} engines: {node: '>=8'} - pathe@2.0.3: - resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==} - peek-stream@1.1.3: resolution: {integrity: sha512-FhJ+YbOSBb9/rIl2ZeE/QHEsWn7PqNYt8ARAY3kIgNGOk13g9FGyIY6JIl/xB/3TFRVoTv5as0l11weORrTekA==} @@ -7808,8 +7927,9 @@ packages: tiny-inflate@1.0.3: resolution: {integrity: sha512-pkY1fj1cKHb2seWDy0B16HeWyczlJA9/WW3u3c4z/NiWDsO3DOU5D7nhTLE9CF0yXv/QZFY7sEJmj24dK+Rrqw==} - tinybench@2.9.0: - resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==} + tinybench@6.1.4: + resolution: {integrity: sha512-9APumHG7r4yOk4X4WlkmE71aZcv1gvin1czO3OQ1U9iJcFA5Ja/ygyb0vPOVHTthFozUYs8CLoLUlM8grb2lTQ==} + engines: {node: '>=20.0.0'} tinyexec@1.3.0: resolution: {integrity: sha512-QKAl9m8gWWGHV8jZcPeym6j+XULi6tOf1mT83WYJ4Lk2ytW/uwAWkrP0uFsdoYMdueVJ0qs26wZ+23xeB4ibNQ==} @@ -8139,22 +8259,23 @@ packages: yaml: optional: true - vitest@4.1.11: - resolution: {integrity: sha512-fhACrNXUidIbGSBr5FlbuBkO7VWC1ZyLl0DO4CU2DrQoAPxX84Ysxs+HeGQpii5lZWV1Q4gBZTTu49mF+A6Edw==} - engines: {node: ^20.0.0 || ^22.0.0 || >=24.0.0} + vitest@5.0.0: + resolution: {integrity: sha512-gpsMNoRhMjMktVxPtstOH4/PJuPyovVaMDr4oDilXaGH1EcqM2OE96SoHT2VIQ6fTGtTjqmHDrEu2X9RQiXf8Q==} + engines: {node: ^22.12.0 || ^24.0.0 || >=26.0.0} hasBin: true peerDependencies: '@edge-runtime/vm': '*' '@opentelemetry/api': ^1.9.0 - '@types/node': ^20.0.0 || ^22.0.0 || >=24.0.0 - '@vitest/browser-playwright': 4.1.11 - '@vitest/browser-preview': 4.1.11 - '@vitest/browser-webdriverio': 4.1.11 - '@vitest/coverage-istanbul': 4.1.11 - '@vitest/coverage-v8': 4.1.11 - '@vitest/ui': 4.1.11 + '@types/node': ^22.0.0 || >=24.0.0 + '@vitest/browser-playwright': 5.0.0 + '@vitest/browser-preview': 5.0.0 + '@vitest/browser-webdriverio': ^5.0.0-beta.5 || >=5.0.0 + '@vitest/coverage-istanbul': 5.0.0 + '@vitest/coverage-v8': 5.0.0 + '@vitest/ui': 5.0.0 happy-dom: '*' jsdom: '*' + vite: ^6.4.0 || ^7.0.0 || ^8.0.0 peerDependenciesMeta: '@edge-runtime/vm': optional: true @@ -10694,63 +10815,122 @@ snapshots: '@opentelemetry/semantic-conventions@1.43.0': {} + '@oxc-parser/binding-android-arm-eabi@0.147.0': + optional: true + '@oxc-parser/binding-android-arm-eabi@0.148.0': optional: true + '@oxc-parser/binding-android-arm64@0.147.0': + optional: true + '@oxc-parser/binding-android-arm64@0.148.0': optional: true + '@oxc-parser/binding-darwin-arm64@0.147.0': + optional: true + '@oxc-parser/binding-darwin-arm64@0.148.0': optional: true + '@oxc-parser/binding-darwin-x64@0.147.0': + optional: true + '@oxc-parser/binding-darwin-x64@0.148.0': optional: true + '@oxc-parser/binding-freebsd-x64@0.147.0': + optional: true + '@oxc-parser/binding-freebsd-x64@0.148.0': optional: true + '@oxc-parser/binding-linux-arm-gnueabihf@0.147.0': + optional: true + '@oxc-parser/binding-linux-arm-gnueabihf@0.148.0': optional: true + '@oxc-parser/binding-linux-arm-musleabihf@0.147.0': + optional: true + '@oxc-parser/binding-linux-arm-musleabihf@0.148.0': optional: true + '@oxc-parser/binding-linux-arm64-gnu@0.147.0': + optional: true + '@oxc-parser/binding-linux-arm64-gnu@0.148.0': optional: true + '@oxc-parser/binding-linux-arm64-musl@0.147.0': + optional: true + '@oxc-parser/binding-linux-arm64-musl@0.148.0': optional: true + '@oxc-parser/binding-linux-ppc64-gnu@0.147.0': + optional: true + '@oxc-parser/binding-linux-ppc64-gnu@0.148.0': optional: true + '@oxc-parser/binding-linux-riscv64-gnu@0.147.0': + optional: true + '@oxc-parser/binding-linux-riscv64-gnu@0.148.0': optional: true + '@oxc-parser/binding-linux-riscv64-musl@0.147.0': + optional: true + '@oxc-parser/binding-linux-riscv64-musl@0.148.0': optional: true + '@oxc-parser/binding-linux-s390x-gnu@0.147.0': + optional: true + '@oxc-parser/binding-linux-s390x-gnu@0.148.0': optional: true + '@oxc-parser/binding-linux-x64-gnu@0.147.0': + optional: true + '@oxc-parser/binding-linux-x64-gnu@0.148.0': optional: true + '@oxc-parser/binding-linux-x64-musl@0.147.0': + optional: true + '@oxc-parser/binding-linux-x64-musl@0.148.0': optional: true + '@oxc-parser/binding-openharmony-arm64@0.147.0': + optional: true + '@oxc-parser/binding-openharmony-arm64@0.148.0': optional: true + '@oxc-parser/binding-win32-arm64-msvc@0.147.0': + optional: true + '@oxc-parser/binding-win32-arm64-msvc@0.148.0': optional: true + '@oxc-parser/binding-win32-ia32-msvc@0.147.0': + optional: true + '@oxc-parser/binding-win32-ia32-msvc@0.148.0': optional: true + '@oxc-parser/binding-win32-x64-msvc@0.147.0': + optional: true + '@oxc-parser/binding-win32-x64-msvc@0.148.0': optional: true + '@oxc-project/types@0.147.0': {} + '@oxc-project/types@0.148.0': {} '@parcel/watcher-android-arm64@2.6.0': @@ -11622,60 +11802,34 @@ snapshots: dependencies: vite: 8.2.2(@types/node@22.20.1)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.0(supports-color@11.0.0))(sass-embedded@1.103.1)(sass@1.103.1)(terser@5.51.2)(tsx@4.23.13)(yaml@2.9.0) - '@vitest/coverage-v8@4.1.11(vitest@4.1.11)': + '@vitest/coverage-v8@5.0.0(vitest@5.0.0)': dependencies: '@bcoe/v8-coverage': 1.0.2 - '@vitest/utils': 4.1.11 + '@vitest/istanbul-lib-coverage': 1.0.1 + '@vitest/istanbul-lib-report': 1.0.1 ast-v8-to-istanbul: 1.0.5 - istanbul-lib-coverage: 3.2.2 - istanbul-lib-report: 3.0.1 - istanbul-reports: 3.2.0 magicast: 0.5.4 obug: 2.1.4 std-env: 4.2.0 tinyrainbow: 3.1.1 - vitest: 4.1.11(@opentelemetry/api@1.9.1)(@types/node@22.20.1)(@vitest/coverage-v8@4.1.11)(esbuild@0.28.2)(jiti@2.7.0)(jsdom@30.0.1)(less@4.9.0(supports-color@11.0.0))(sass-embedded@1.103.1)(sass@1.103.1)(terser@5.51.2)(tsx@4.23.13)(yaml@2.9.0) + vitest: 5.0.0(@opentelemetry/api@1.9.1)(@types/node@22.20.1)(@vitest/coverage-v8@5.0.0)(jsdom@30.0.1)(vite@8.2.2(@types/node@22.20.1)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.0(supports-color@11.0.0))(sass-embedded@1.103.1)(sass@1.103.1)(terser@5.51.2)(tsx@4.23.13)(yaml@2.9.0)) - '@vitest/expect@4.1.11': + '@vitest/istanbul-lib-coverage@1.0.1': {} + + '@vitest/istanbul-lib-report@1.0.1': dependencies: - '@standard-schema/spec': 1.1.0 - '@types/chai': 5.2.3 - '@vitest/spy': 4.1.11 - '@vitest/utils': 4.1.11 - chai: 6.2.2 - tinyrainbow: 3.1.1 + '@vitest/istanbul-lib-coverage': 1.0.1 - '@vitest/mocker@4.1.11(vite@8.2.2(@types/node@22.20.1)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.0(supports-color@11.0.0))(sass-embedded@1.103.1)(sass@1.103.1)(terser@5.51.2)(tsx@4.23.13)(yaml@2.9.0))': + '@vitest/mocker@5.0.0(vite@8.2.2(@types/node@22.20.1)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.0(supports-color@11.0.0))(sass-embedded@1.103.1)(sass@1.103.1)(terser@5.51.2)(tsx@4.23.13)(yaml@2.9.0))': dependencies: - '@vitest/spy': 4.1.11 + '@jridgewell/trace-mapping': 0.3.31 + '@vitest/spy': 5.0.0 estree-walker: 3.0.3 - magic-string: 0.30.21 + magic-string: 1.2.3 optionalDependencies: vite: 8.2.2(@types/node@22.20.1)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.0(supports-color@11.0.0))(sass-embedded@1.103.1)(sass@1.103.1)(terser@5.51.2)(tsx@4.23.13)(yaml@2.9.0) - '@vitest/pretty-format@4.1.11': - dependencies: - tinyrainbow: 3.1.1 - - '@vitest/runner@4.1.11': - dependencies: - '@vitest/utils': 4.1.11 - pathe: 2.0.3 - - '@vitest/snapshot@4.1.11': - dependencies: - '@vitest/pretty-format': 4.1.11 - '@vitest/utils': 4.1.11 - magic-string: 0.30.21 - pathe: 2.0.3 - - '@vitest/spy@4.1.11': {} - - '@vitest/utils@4.1.11': - dependencies: - '@vitest/pretty-format': 4.1.11 - convert-source-map: 2.0.0 - tinyrainbow: 3.1.1 + '@vitest/spy@5.0.0': {} '@webassemblyjs/ast@1.14.1': dependencies: @@ -14920,6 +15074,30 @@ snapshots: object-keys: 1.1.1 safe-push-apply: 1.0.0 + oxc-parser@0.147.0: + dependencies: + '@oxc-project/types': 0.147.0 + optionalDependencies: + '@oxc-parser/binding-android-arm-eabi': 0.147.0 + '@oxc-parser/binding-android-arm64': 0.147.0 + '@oxc-parser/binding-darwin-arm64': 0.147.0 + '@oxc-parser/binding-darwin-x64': 0.147.0 + '@oxc-parser/binding-freebsd-x64': 0.147.0 + '@oxc-parser/binding-linux-arm-gnueabihf': 0.147.0 + '@oxc-parser/binding-linux-arm-musleabihf': 0.147.0 + '@oxc-parser/binding-linux-arm64-gnu': 0.147.0 + '@oxc-parser/binding-linux-arm64-musl': 0.147.0 + '@oxc-parser/binding-linux-ppc64-gnu': 0.147.0 + '@oxc-parser/binding-linux-riscv64-gnu': 0.147.0 + '@oxc-parser/binding-linux-riscv64-musl': 0.147.0 + '@oxc-parser/binding-linux-s390x-gnu': 0.147.0 + '@oxc-parser/binding-linux-x64-gnu': 0.147.0 + '@oxc-parser/binding-linux-x64-musl': 0.147.0 + '@oxc-parser/binding-openharmony-arm64': 0.147.0 + '@oxc-parser/binding-win32-arm64-msvc': 0.147.0 + '@oxc-parser/binding-win32-ia32-msvc': 0.147.0 + '@oxc-parser/binding-win32-x64-msvc': 0.147.0 + oxc-parser@0.148.0: dependencies: '@oxc-project/types': 0.148.0 @@ -15029,8 +15207,6 @@ snapshots: path-type@4.0.0: {} - pathe@2.0.3: {} - peek-stream@1.1.3: dependencies: buffer-from: 1.1.2 @@ -16194,7 +16370,7 @@ snapshots: tiny-inflate@1.0.3: {} - tinybench@2.9.0: {} + tinybench@6.1.4: {} tinyexec@1.3.0: {} @@ -16523,46 +16699,29 @@ snapshots: tsx: 4.23.13 yaml: 2.9.0 - vitest@4.1.11(@opentelemetry/api@1.9.1)(@types/node@22.20.1)(@vitest/coverage-v8@4.1.11)(esbuild@0.28.2)(jiti@2.7.0)(jsdom@30.0.1)(less@4.9.0(supports-color@11.0.0))(sass-embedded@1.103.1)(sass@1.103.1)(terser@5.51.2)(tsx@4.23.13)(yaml@2.9.0): + vitest@5.0.0(@opentelemetry/api@1.9.1)(@types/node@22.20.1)(@vitest/coverage-v8@5.0.0)(jsdom@30.0.1)(vite@8.2.2(@types/node@22.20.1)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.0(supports-color@11.0.0))(sass-embedded@1.103.1)(sass@1.103.1)(terser@5.51.2)(tsx@4.23.13)(yaml@2.9.0)): dependencies: - '@vitest/expect': 4.1.11 - '@vitest/mocker': 4.1.11(vite@8.2.2(@types/node@22.20.1)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.0(supports-color@11.0.0))(sass-embedded@1.103.1)(sass@1.103.1)(terser@5.51.2)(tsx@4.23.13)(yaml@2.9.0)) - '@vitest/pretty-format': 4.1.11 - '@vitest/runner': 4.1.11 - '@vitest/snapshot': 4.1.11 - '@vitest/spy': 4.1.11 - '@vitest/utils': 4.1.11 + '@types/chai': 5.2.3 + '@vitest/mocker': 5.0.0(vite@8.2.2(@types/node@22.20.1)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.0(supports-color@11.0.0))(sass-embedded@1.103.1)(sass@1.103.1)(terser@5.51.2)(tsx@4.23.13)(yaml@2.9.0)) + chai: 6.2.2 es-module-lexer: 2.3.2 expect-type: 1.4.0 - magic-string: 0.30.21 + magic-string: 1.2.3 obug: 2.1.4 - pathe: 2.0.3 picomatch: 4.0.7 std-env: 4.2.0 - tinybench: 2.9.0 + tinybench: 6.1.4 tinyexec: 1.3.0 tinyglobby: 0.2.17 - tinyrainbow: 3.1.1 vite: 8.2.2(@types/node@22.20.1)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.0(supports-color@11.0.0))(sass-embedded@1.103.1)(sass@1.103.1)(terser@5.51.2)(tsx@4.23.13)(yaml@2.9.0) why-is-node-running: 2.3.0 optionalDependencies: '@opentelemetry/api': 1.9.1 '@types/node': 22.20.1 - '@vitest/coverage-v8': 4.1.11(vitest@4.1.11) + '@vitest/coverage-v8': 5.0.0(vitest@5.0.0) jsdom: 30.0.1 transitivePeerDependencies: - - '@vitejs/devtools' - - esbuild - - jiti - - less - msw - - sass - - sass-embedded - - stylus - - sugarss - - terser - - tsx - - yaml void-elements@2.0.1: {} diff --git a/tests/e2e/tests/build/esbuild-unsupported.ts b/tests/e2e/tests/build/unix-esbuild-unsupported.ts similarity index 100% rename from tests/e2e/tests/build/esbuild-unsupported.ts rename to tests/e2e/tests/build/unix-esbuild-unsupported.ts diff --git a/tests/e2e/tests/build/rebuild-replacements.ts b/tests/e2e/tests/build/unix-rebuild-replacements.ts similarity index 100% rename from tests/e2e/tests/build/rebuild-replacements.ts rename to tests/e2e/tests/build/unix-rebuild-replacements.ts diff --git a/tests/e2e/tests/vitest/browser-coverage-istanbul.ts b/tests/e2e/tests/vitest/browser-coverage-istanbul.ts index 21f3987a3d1d..66f73162d586 100644 --- a/tests/e2e/tests/vitest/browser-coverage-istanbul.ts +++ b/tests/e2e/tests/vitest/browser-coverage-istanbul.ts @@ -1,16 +1,15 @@ import { ng } from '../../utils/process'; import { applyVitestBuilder } from '../../utils/vitest'; import assert from 'node:assert'; -import { installPackage } from '../../utils/packages'; import { expectFileToExist, readFile } from '../../utils/fs'; import { updateJsonFile } from '../../utils/project'; export default async function (): Promise { - await applyVitestBuilder(); - // Install ONLY Istanbul coverage package. // This will trigger the auto-detection logic to use Istanbul even for Node tests. - await installPackage('@vitest/coverage-istanbul@4'); + await applyVitestBuilder({ + coverageIstanbul: true, + }); // Use the 'json' reporter to get a machine-readable output for assertions. await updateJsonFile('angular.json', (json) => { diff --git a/tests/e2e/tests/vitest/browser-coverage-sourcemaps.ts b/tests/e2e/tests/vitest/browser-coverage-sourcemaps.ts index db8b91a0abbe..476c15c41d38 100644 --- a/tests/e2e/tests/vitest/browser-coverage-sourcemaps.ts +++ b/tests/e2e/tests/vitest/browser-coverage-sourcemaps.ts @@ -1,14 +1,13 @@ import assert from 'node:assert/strict'; import { applyVitestBuilder } from '../../utils/vitest'; import { ng } from '../../utils/process'; -import { installPackage } from '../../utils/packages'; import { expectFileToExist, readFile } from '../../utils/fs'; export default async function (): Promise { - await applyVitestBuilder(); - await installPackage('playwright@1'); - await installPackage('@vitest/browser-playwright@4'); - await installPackage('@vitest/coverage-v8@4'); + await applyVitestBuilder({ + playwright: true, + coverageV8: true, + }); // Run tests with coverage in browser mode. // We use the default passing tests generated for the project. diff --git a/tests/e2e/tests/vitest/browser-coverage-validation.ts b/tests/e2e/tests/vitest/browser-coverage-validation.ts index 9124af1bb3a8..e98da6495f0b 100644 --- a/tests/e2e/tests/vitest/browser-coverage-validation.ts +++ b/tests/e2e/tests/vitest/browser-coverage-validation.ts @@ -2,17 +2,14 @@ import assert from 'node:assert/strict'; import path from 'node:path'; import { applyVitestBuilder } from '../../utils/vitest'; import { execAndCaptureError } from '../../utils/process'; -import { installPackage } from '../../utils/packages'; import { writeFile } from '../../utils/fs'; import { stripVTControlCharacters } from 'node:util'; import { unlink } from 'node:fs/promises'; export default async function (): Promise { - await applyVitestBuilder(); - - // Install necessary packages to pass the browser provider check - await installPackage('playwright@1'); - await installPackage('@vitest/browser-playwright@4'); + await applyVitestBuilder({ + playwright: true, + }); // === Case 1: Browser configured via CLI option === const error1 = await execAndCaptureError('ng', [ @@ -29,24 +26,29 @@ export default async function (): Promise { 'Expected validation error for missing coverage packages.', ); - await installPackage('@vitest/coverage-v8@4'); + await applyVitestBuilder({ + playwright: true, + coverageV8: true, + }); - const configPath = 'vitest.config.ts'; + const configPath = 'vitest.config.mts'; const absoluteConfigPath = path.resolve(configPath); try { - // === Case 2: Browser configured via vitest.config.ts (name) === + // === Case 2: Browser configured via vitest.config.mts (name) === await writeFile( configPath, ` import { defineConfig } from 'vitest/config'; + import { playwright } from '@vitest/browser-playwright'; + export default defineConfig({ test: { coverage: { provider: 'v8' }, browser: { enabled: true, name: 'firefox', - provider: 'playwright', + provider: playwright(), }, }, }); @@ -66,17 +68,19 @@ export default async function (): Promise { 'Expected validation error for unsupported browser with coverage (config name).', ); - // === Case 3: Browser configured via vitest.config.ts (instances) === + // === Case 3: Browser configured via vitest.config.mts (instances) === await writeFile( configPath, ` import { defineConfig } from 'vitest/config'; + import { playwright } from '@vitest/browser-playwright'; + export default defineConfig({ test: { coverage: { provider: 'v8' }, browser: { enabled: true, - provider: 'playwright', + provider: playwright(), instances: [{ browser: 'firefox' }], } as any, }, diff --git a/tests/e2e/tests/vitest/browser-custom-config-vitest-v4.ts b/tests/e2e/tests/vitest/browser-custom-config-vitest-v4.ts new file mode 100644 index 000000000000..7865830f3b82 --- /dev/null +++ b/tests/e2e/tests/vitest/browser-custom-config-vitest-v4.ts @@ -0,0 +1,67 @@ +import assert from 'node:assert/strict'; +import { applyVitestBuilder } from '../../utils/vitest'; +import { ng } from '../../utils/process'; +import { writeFile } from '../../utils/fs'; +import { installWorkspacePackages } from '../../utils/packages'; +import { updateJsonFile } from '../../utils/project'; + +export default async function (): Promise { + await applyVitestBuilder({ + skipInstall: true, + }); + + await updateJsonFile('package.json', (json) => { + json.devDependencies = { + ...json.devDependencies, + '@vitest/browser-playwright': '^4', + 'vitest': '^4', + 'playwright': '^1', + }; + }); + + await installWorkspacePackages(); + + await ng('generate', 'component', 'my-comp'); + + // Create vitest-base.config.mts + await writeFile( + 'vitest-base.config.mts', + ` + import { defineConfig } from 'vitest/config'; + import { playwright } from '@vitest/browser-playwright'; + + export default defineConfig({ + test: { + browser: { + enabled: true, + provider: playwright({launchOptions: {executablePath: process.env['CHROME_BIN']}}), + instances: [ + { browser: 'chromium' }, + ], + headless: true, + }, + }, + }); + `, + ); + + // Create a spec file that asserts browser environment + await writeFile( + 'src/browser.spec.ts', + ` + describe('Browser Environment Check', () => { + it('should be running in Chromium', () => { + const ua = navigator.userAgent; + // Fail the test if it's not Chrome/Chromium + if (!ua.includes('Chrome') && !ua.includes('Chromium')) { + throw new Error('Expected to be running in Chrome/Chromium, but User Agent is: ' + ua); + } + }); + }); + `, + ); + + const { stdout } = await ng('test', '--no-watch', '--runner-config'); + + assert.match(stdout, /3 passed/, 'Expected 3 tests to pass.'); +} diff --git a/tests/e2e/tests/vitest/browser-custom-config.ts b/tests/e2e/tests/vitest/browser-custom-config.ts index a523f421853f..ab9092d038af 100644 --- a/tests/e2e/tests/vitest/browser-custom-config.ts +++ b/tests/e2e/tests/vitest/browser-custom-config.ts @@ -1,18 +1,18 @@ import assert from 'node:assert/strict'; import { applyVitestBuilder } from '../../utils/vitest'; import { ng } from '../../utils/process'; -import { installPackage } from '../../utils/packages'; import { writeFile } from '../../utils/fs'; export default async function (): Promise { - await applyVitestBuilder(); - await installPackage('playwright@1'); - await installPackage('@vitest/browser-playwright@4'); + await applyVitestBuilder({ + playwright: true, + }); + await ng('generate', 'component', 'my-comp'); - // Create vitest-base.config.ts + // Create vitest-base.config.mts await writeFile( - 'vitest-base.config.ts', + 'vitest-base.config.mts', ` import { defineConfig } from 'vitest/config'; import { playwright } from '@vitest/browser-playwright'; diff --git a/tests/e2e/tests/vitest/browser-no-globals.ts b/tests/e2e/tests/vitest/browser-no-globals.ts index b25f8168c5f7..3a4fcde4b96c 100644 --- a/tests/e2e/tests/vitest/browser-no-globals.ts +++ b/tests/e2e/tests/vitest/browser-no-globals.ts @@ -1,6 +1,5 @@ import assert from 'node:assert/strict'; import { writeFile } from '../../utils/fs'; -import { installPackage } from '../../utils/packages'; import { ng } from '../../utils/process'; import { applyVitestBuilder } from '../../utils/vitest'; @@ -9,10 +8,9 @@ import { applyVitestBuilder } from '../../utils/vitest'; * @see https://github.com/angular/angular-cli/issues/31745 */ export default async function (): Promise { - await applyVitestBuilder(); - - await installPackage('playwright@1'); - await installPackage('@vitest/browser-playwright@4'); + await applyVitestBuilder({ + playwright: true, + }); await writeFile( 'src/app/app.spec.ts', diff --git a/tests/e2e/tests/vitest/browser-playwright.ts b/tests/e2e/tests/vitest/browser-playwright.ts index fc8e7e5b53b3..54d744e10208 100644 --- a/tests/e2e/tests/vitest/browser-playwright.ts +++ b/tests/e2e/tests/vitest/browser-playwright.ts @@ -1,14 +1,13 @@ import assert from 'node:assert/strict'; import { applyVitestBuilder } from '../../utils/vitest'; import { ng } from '../../utils/process'; -import { installPackage } from '../../utils/packages'; import { writeFile } from '../../utils/fs'; import { updateJsonFile } from '../../utils/project'; export default async function (): Promise { - await applyVitestBuilder(); - await installPackage('playwright@1'); - await installPackage('@vitest/browser-playwright@4'); + await applyVitestBuilder({ + playwright: true, + }); await ng('generate', 'component', 'my-comp'); await writeFile( diff --git a/tests/e2e/tests/vitest/browser-sourcemaps.ts b/tests/e2e/tests/vitest/browser-sourcemaps.ts index 90c04457c7c8..4bc025a7d2b9 100644 --- a/tests/e2e/tests/vitest/browser-sourcemaps.ts +++ b/tests/e2e/tests/vitest/browser-sourcemaps.ts @@ -1,14 +1,14 @@ import assert from 'node:assert/strict'; import { applyVitestBuilder } from '../../utils/vitest'; import { ng, noSilentNg } from '../../utils/process'; -import { installPackage } from '../../utils/packages'; import { writeFile } from '../../utils/fs'; import { stripVTControlCharacters } from 'node:util'; export default async function (): Promise { - await applyVitestBuilder(); - await installPackage('playwright@1'); - await installPackage('@vitest/browser-playwright@4'); + await applyVitestBuilder({ + playwright: true, + }); + await ng('generate', 'component', 'my-comp'); // Add a failing test to verify source map support diff --git a/tests/e2e/tests/vitest/browser-webdriverio.ts b/tests/e2e/tests/vitest/browser-webdriverio.ts index 0838761eb2ad..231f5fca4041 100644 --- a/tests/e2e/tests/vitest/browser-webdriverio.ts +++ b/tests/e2e/tests/vitest/browser-webdriverio.ts @@ -1,14 +1,13 @@ import assert from 'node:assert/strict'; import { applyVitestBuilder } from '../../utils/vitest'; import { ng } from '../../utils/process'; -import { installPackage } from '../../utils/packages'; import { writeFile } from '../../utils/fs'; import { updateJsonFile } from '../../utils/project'; export default async function (): Promise { - await applyVitestBuilder(); - await installPackage('webdriverio@9'); - await installPackage('@vitest/browser-webdriverio@4'); + await applyVitestBuilder({ + webdriver: true, + }); await ng('generate', 'component', 'my-comp'); diff --git a/tests/e2e/tests/vitest/larger-project-coverage.ts b/tests/e2e/tests/vitest/larger-project-coverage.ts index 3594bdc7dfee..d5fa94c0b82c 100644 --- a/tests/e2e/tests/vitest/larger-project-coverage.ts +++ b/tests/e2e/tests/vitest/larger-project-coverage.ts @@ -1,13 +1,14 @@ import { ng } from '../../utils/process'; import { applyVitestBuilder } from '../../utils/vitest'; import assert from 'node:assert'; -import { installPackage } from '../../utils/packages'; import { updateJsonFile } from '../../utils/project'; import { readFile } from '../../utils/fs'; export default async function () { - await applyVitestBuilder(); - await installPackage('@vitest/coverage-v8@4'); + await applyVitestBuilder({ + coverageV8: true, + playwright: true, + }); // Add coverage and threshold configuration to ensure coverage is calculated. // Use the 'json' reporter to get a machine-readable output for assertions. @@ -44,10 +45,6 @@ export default async function () { assert.ok(found, `Expected ${file} to be in the JSDOM coverage report.`); } - // Setup for browser mode - await installPackage('playwright@1'); - await installPackage('@vitest/browser-playwright@4'); - // Run tests in browser mode with coverage const { stdout: browserStdout } = await ng( 'test', diff --git a/tests/e2e/tests/vitest/larger-project.ts b/tests/e2e/tests/vitest/larger-project.ts index 7b8db953c30c..9b9db25bb067 100644 --- a/tests/e2e/tests/vitest/larger-project.ts +++ b/tests/e2e/tests/vitest/larger-project.ts @@ -1,12 +1,13 @@ import assert from 'node:assert'; import { mkdir, writeFile } from 'node:fs/promises'; import { dirname } from 'node:path'; -import { installPackage } from '../../utils/packages'; import { ng } from '../../utils/process'; import { applyVitestBuilder } from '../../utils/vitest'; export default async function () { - await applyVitestBuilder(); + await applyVitestBuilder({ + playwright: true, + }); const artifactCount = 500; // A new project starts with 1 test file (app.spec.ts) @@ -22,10 +23,6 @@ export default async function () { const { stdout: jsdomStdout } = await ng('test', '--no-watch'); assert.match(jsdomStdout, expectedMessage, `Expected ${totalTests} tests to pass in JSDOM mode.`); - // Setup for browser mode - await installPackage('playwright@1'); - await installPackage('@vitest/browser-playwright@4'); - // Run tests in browser mode const { stdout: browserStdout } = await ng( 'test', diff --git a/tests/e2e/tests/vitest/tslib-resolution.ts b/tests/e2e/tests/vitest/tslib-resolution.ts index 759d5e2b5728..091f5105ba7f 100644 --- a/tests/e2e/tests/vitest/tslib-resolution.ts +++ b/tests/e2e/tests/vitest/tslib-resolution.ts @@ -1,13 +1,12 @@ import { writeFile } from '../../utils/fs'; -import { installPackage } from '../../utils/packages'; import { ng } from '../../utils/process'; import { applyVitestBuilder } from '../../utils/vitest'; import assert from 'node:assert'; export default async function () { - await applyVitestBuilder(); - await installPackage('playwright@1'); - await installPackage('@vitest/browser-playwright@4'); + await applyVitestBuilder({ + playwright: true, + }); // Add a custom decorator to trigger tslib usage await writeFile( diff --git a/tests/e2e/utils/vitest.ts b/tests/e2e/utils/vitest.ts index 471ca030169e..ebb9d9d12298 100644 --- a/tests/e2e/utils/vitest.ts +++ b/tests/e2e/utils/vitest.ts @@ -1,11 +1,69 @@ -import { installPackage } from './packages'; +import { createRequire } from 'node:module'; +import { installWorkspacePackages } from './packages'; import { updateJsonFile } from './project'; +import { readFile } from 'node:fs/promises'; +import { resolve } from 'node:path'; /** Updates the `test` builder in the current workspace to use Vitest. */ -export async function applyVitestBuilder(): Promise { - // These deps matches the deps in `@schematics/angular` - await installPackage('vitest@^4.0.8'); - await installPackage('jsdom@^27.1.0'); +export async function applyVitestBuilder(options?: { + coverageV8?: boolean; + coverageIstanbul?: boolean; + playwright?: boolean; + webdriver?: boolean; + skipInstall?: boolean; +}): Promise { + const { coverageV8, coverageIstanbul, playwright, webdriver, skipInstall } = options ?? {}; + + const schematicsAngular = createRequire(process.cwd() + '/').resolve( + '@schematics/angular/package.json', + ); + + const latestVersionsPath = resolve(schematicsAngular, '../utility/latest-versions/package.json'); + + const { dependencies: latestVersion } = JSON.parse(await readFile(latestVersionsPath, 'utf-8')); + + await updateJsonFile('package.json', (json) => { + [ + 'karma', + 'karma-chrome-launcher', + 'karma-coverage', + 'karma-jasmine', + 'karma-jasmine-html-reporter', + 'jasmine-core', + '@types/jasmine', + 'istanbul-lib-instrument', + ].forEach((dep) => { + delete json.devDependencies[dep]; + }); + + json.devDependencies['vitest'] = latestVersion['vitest']; + json.devDependencies['jsdom'] = latestVersion['jsdom']; + + if (webdriver) { + json.devDependencies['webdriverio'] = latestVersion['webdriverio']; + json.devDependencies['@vitest/browser-webdriverio'] = + latestVersion['@vitest/browser-webdriverio']; + } + + if (playwright) { + json.devDependencies['playwright'] = latestVersion['playwright']; + json.devDependencies['@vitest/browser-playwright'] = + latestVersion['@vitest/browser-playwright']; + } + + if (coverageV8) { + json.devDependencies['@vitest/coverage-v8'] = latestVersion['@vitest/coverage-v8']; + } + + if (coverageIstanbul) { + json.devDependencies['@vitest/coverage-istanbul'] = + latestVersion['@vitest/coverage-istanbul']; + } + }); + + if (!skipInstall) { + await installWorkspacePackages(); + } await updateJsonFile('angular.json', (json) => { const projects = Object.values(json['projects']); diff --git a/tests/e2e_runner.ts b/tests/e2e_runner.ts index f77d6e367e9b..3f1945905089 100644 --- a/tests/e2e_runner.ts +++ b/tests/e2e_runner.ts @@ -116,6 +116,7 @@ const testGlob = (process.env.TESTBRIDGE_TEST_ONLY ?? argv.glob).replace(/\.ts$/ const e2eRoot = path.join(__dirname, 'e2e'); const allSetups = glob.sync(`setup/**/*.js`, { cwd: e2eRoot }).sort(); const allInitializers = glob.sync(`initialize/**/*.js`, { cwd: e2eRoot }).sort(); +const isWindows = process.platform === 'win32'; const allTests = glob .sync(testGlob, { cwd: e2eRoot, ignore: argv.ignore }) @@ -140,6 +141,14 @@ const allTests = glob return false; } + if (isWindows) { + if (fileName.startsWith('unix-')) { + return false; + } + } else if (fileName.startsWith('windows-')) { + return false; + } + return true; }) .sort();