From 486e73c5a478f0db87b89558203d15e5f4841e65 Mon Sep 17 00:00:00 2001 From: Alan Agius <17563226+alan-agius4@users.noreply.github.com> Date: Mon, 7 Sep 2026 07:42:58 +0000 Subject: [PATCH 1/9] build: update vitest monorepo to v5 See associated pull request for more information. Closes #34030 as a pr takeover --- modules/testing/builder/package.json | 4 +- packages/angular/build/package.json | 4 +- .../unit-test/runners/vitest/plugins.ts | 7 +- .../utility/latest-versions/package.json | 10 +- pnpm-lock.yaml | 377 +++++++++++++----- tests/e2e/utils/vitest.ts | 4 +- 6 files changed, 281 insertions(+), 125 deletions(-) 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..0dfd1dc4a8ce 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, @@ -313,7 +310,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/schematics/angular/utility/latest-versions/package.json b/packages/schematics/angular/utility/latest-versions/package.json index 41ba63058ad4..92b667724aaf 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": "^5.0.0", + "@vitest/coverage-v8": "^5.0.0", + "@vitest/coverage-istanbul": "^5.0.0", + "@vitest/browser-playwright": "^5.0.0", "@vitest/browser-webdriverio": "^4.0.8", - "@vitest/browser-preview": "^4.0.8", + "@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 2062ad7ce96d..fcbf01bd36f1 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -394,8 +394,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) @@ -412,8 +412,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: @@ -530,8 +530,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 @@ -2912,48 +2912,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} @@ -2961,6 +3010,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} @@ -2968,6 +3024,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} @@ -2975,6 +3038,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} @@ -2982,6 +3052,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} @@ -2989,6 +3066,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} @@ -2996,6 +3080,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} @@ -3003,6 +3094,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} @@ -3010,30 +3108,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==} @@ -3866,20 +3991,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 @@ -3889,20 +4019,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==} @@ -6823,6 +6941,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} @@ -6919,9 +7041,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==} @@ -7909,8 +8028,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==} @@ -8240,22 +8360,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 @@ -10795,63 +10916,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': @@ -11723,60 +11903,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: @@ -15021,6 +15175,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 @@ -15130,8 +15308,6 @@ snapshots: path-type@4.0.0: {} - pathe@2.0.3: {} - peek-stream@1.1.3: dependencies: buffer-from: 1.1.2 @@ -16295,7 +16471,7 @@ snapshots: tiny-inflate@1.0.3: {} - tinybench@2.9.0: {} + tinybench@6.1.4: {} tinyexec@1.3.0: {} @@ -16624,46 +16800,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/utils/vitest.ts b/tests/e2e/utils/vitest.ts index 471ca030169e..ec681368147e 100644 --- a/tests/e2e/utils/vitest.ts +++ b/tests/e2e/utils/vitest.ts @@ -4,8 +4,8 @@ import { updateJsonFile } from './project'; /** 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'); + await installPackage('vitest@^5.0.0'); + await installPackage('jsdom@^30.0.0'); await updateJsonFile('angular.json', (json) => { const projects = Object.values(json['projects']); From 089cb30a42ff3c180f296932006ceec0693f2278 Mon Sep 17 00:00:00 2001 From: Alan Agius <17563226+alan-agius4@users.noreply.github.com> Date: Mon, 7 Sep 2026 08:24:44 +0000 Subject: [PATCH 2/9] test: resolve vitest dependencies from latest-versions in e2e tests Refactor `applyVitestBuilder` to read dependency versions directly from `@schematics/angular/utility/latest-versions/package.json` and install them in a single batch using `installWorkspacePackages`. Update all Vitest E2E test suites to pass dependency options (`playwright`, `coverageV8`, `coverageIstanbul`, `webdriver`) directly to `applyVitestBuilder`, eliminating hardcoded major version installations and preventing version mismatches during major dependency upgrades. --- .../behavior/runner-config-vitest_spec.ts | 76 +++++++++---------- .../tests/options/runner-config_spec.ts | 8 +- ...pported.ts => unix-esbuild-unsupported.ts} | 0 ...ements.ts => unix-rebuild-replacements.ts} | 0 .../tests/vitest/browser-coverage-istanbul.ts | 7 +- .../vitest/browser-coverage-sourcemaps.ts | 9 +-- .../vitest/browser-coverage-validation.ts | 28 ++++--- .../e2e/tests/vitest/browser-custom-config.ts | 8 +- tests/e2e/tests/vitest/browser-no-globals.ts | 8 +- tests/e2e/tests/vitest/browser-playwright.ts | 7 +- tests/e2e/tests/vitest/browser-sourcemaps.ts | 8 +- tests/e2e/tests/vitest/browser-webdriverio.ts | 7 +- .../tests/vitest/larger-project-coverage.ts | 11 +-- tests/e2e/tests/vitest/larger-project.ts | 9 +-- tests/e2e/tests/vitest/tslib-resolution.ts | 7 +- tests/e2e/utils/vitest.ts | 52 +++++++++++-- tests/e2e_runner.ts | 9 +++ 17 files changed, 148 insertions(+), 106 deletions(-) rename tests/e2e/tests/build/{esbuild-unsupported.ts => unix-esbuild-unsupported.ts} (100%) rename tests/e2e/tests/build/{rebuild-replacements.ts => unix-rebuild-replacements.ts} (100%) 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/options/runner-config_spec.ts b/packages/angular/build/src/builders/unit-test/tests/options/runner-config_spec.ts index b061b88e990c..9f3b3972f1ee 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(); @@ -96,7 +96,7 @@ describeBuilder(execute, UNIT_TEST_BUILDER_INFO, (harness) => { it('should find and use a `vitest-base.config.js` in the workspace root', async () => { // This file should be ignored because the new logic looks for `vitest-base.config.*`. - harness.writeFile('vitest.config.ts', VITEST_CONFIG_CONTENT); + harness.writeFile('vitest.config.mts', 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.useTarget('test', { @@ -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/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.ts b/tests/e2e/tests/vitest/browser-custom-config.ts index a523f421853f..969b6efcacb7 100644 --- a/tests/e2e/tests/vitest/browser-custom-config.ts +++ b/tests/e2e/tests/vitest/browser-custom-config.ts @@ -1,13 +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'; 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 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 ec681368147e..01639c38996f 100644 --- a/tests/e2e/utils/vitest.ts +++ b/tests/e2e/utils/vitest.ts @@ -1,11 +1,53 @@ -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@^5.0.0'); - await installPackage('jsdom@^30.0.0'); +export async function applyVitestBuilder(options?: { + coverageV8?: boolean; + coverageIstanbul?: boolean; + playwright?: boolean; + webdriver?: boolean; +}): Promise { + const { coverageV8, coverageIstanbul, playwright, webdriver } = 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) => { + 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']; + } + }); + + 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(); From 5ced51a90a88f91532fef43859b6b7f19a2e7036 Mon Sep 17 00:00:00 2001 From: Alan Agius <17563226+alan-agius4@users.noreply.github.com> Date: Mon, 7 Sep 2026 08:53:16 +0000 Subject: [PATCH 3/9] refactor(@angular/build): deprecate splitting option in unit-test builder DEPRECATED: The `splitting` option in the unit-test builder is deprecated as it is no longer needed with Vitest 5. Disabling code splitting is no longer necessary with Vitest 5, as the issue where shared-module exports were uninitialized in class-field initializers under JSDOM has been resolved. --- .../build/src/builders/unit-test/schema.json | 5 +++-- .../behavior/vitest-shared-chunk-init_spec.ts | 17 ----------------- 2 files changed, 3 insertions(+), 19 deletions(-) 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/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 From af314348ccd0276a70faf9b1b2c8233c09624c68 Mon Sep 17 00:00:00 2001 From: Alan Agius <17563226+alan-agius4@users.noreply.github.com> Date: Mon, 7 Sep 2026 08:54:49 +0000 Subject: [PATCH 4/9] refactor(@schematics/angular): use .mts extension for generated Vitest configuration Update the generated Vitest base configuration file extension from `.ts` to `.mts` to ensure it is treated as an ES module by default. This avoids warnings from Vite regarding ESM syntax in CommonJS files when the workspace does not define `"type": "module"`. Also updates related schematics tests, karma migration hints, and builder integration test specs to use `vitest-base.config.mts`. --- .../builders/unit-test/tests/options/isolate_spec.ts | 2 +- .../tests/options/runner-config-coverage_spec.ts | 6 +++--- .../unit-test/tests/options/runner-config_spec.ts | 10 +++++----- ...fig.ts.template => vitest-base.config.mts.template} | 0 packages/schematics/angular/config/index.ts | 6 +++--- packages/schematics/angular/config/index_spec.ts | 4 ++-- .../migrate-karma-to-vitest/karma-processor.ts | 2 +- tests/e2e/tests/vitest/browser-custom-config.ts | 4 ++-- tests/e2e/utils/vitest.ts | 2 +- 9 files changed, 18 insertions(+), 18 deletions(-) rename packages/schematics/angular/config/files/{vitest-base.config.ts.template => vitest-base.config.mts.template} (100%) 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 9f3b3972f1ee..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 @@ -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, }); @@ -96,9 +96,9 @@ describeBuilder(execute, UNIT_TEST_BUILDER_INFO, (harness) => { it('should find and use a `vitest-base.config.js` in the workspace root', async () => { // This file should be ignored because the new logic looks for `vitest-base.config.*`. - harness.writeFile('vitest.config.mts', VITEST_CONFIG_CONTENT); + 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, 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/tests/e2e/tests/vitest/browser-custom-config.ts b/tests/e2e/tests/vitest/browser-custom-config.ts index 969b6efcacb7..ab9092d038af 100644 --- a/tests/e2e/tests/vitest/browser-custom-config.ts +++ b/tests/e2e/tests/vitest/browser-custom-config.ts @@ -10,9 +10,9 @@ export default async function (): Promise { 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/utils/vitest.ts b/tests/e2e/utils/vitest.ts index 01639c38996f..007c9287cece 100644 --- a/tests/e2e/utils/vitest.ts +++ b/tests/e2e/utils/vitest.ts @@ -47,7 +47,7 @@ export async function applyVitestBuilder(options?: { } }); - await installWorkspacePackages(); + await installWorkspacePackages({ force: true }); await updateJsonFile('angular.json', (json) => { const projects = Object.values(json['projects']); From 806fbd62c3d02f7933da829967490a198f40c8e9 Mon Sep 17 00:00:00 2001 From: Alan Agius <17563226+alan-agius4@users.noreply.github.com> Date: Mon, 7 Sep 2026 09:46:10 +0000 Subject: [PATCH 5/9] fix(@angular/build): disable root config extension for inline test project MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In Vitest 5, inline projects declared under `test.projects` extend the declaring root configuration by default (`extends: true`). Because the Angular CLI test runner already explicitly merges user-provided options from the configuration file into `projectConfig`, automatic root inheritance caused array options—such as `browser.instances` and plugins—to be merged and concatenated twice. Setting `extends: false` on the inline project configuration keeps it isolated from the declaring root config and prevents duplicate browser instance registrations and repeated test runs. --- .../build/src/builders/unit-test/runners/vitest/plugins.ts | 2 ++ 1 file changed, 2 insertions(+) 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 0dfd1dc4a8ce..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 @@ -245,6 +245,7 @@ export async function createVitestConfigPlugin( const projectResolver = createProjectResolver(projectSourceRoot); const projectDefaults: Vite.UserConfig & UserWorkspaceConfig = { + extends: false, test: { setupFiles, globals: true, @@ -265,6 +266,7 @@ export async function createVitestConfigPlugin( const { optimizeDeps, resolve } = config; const projectOverrides: Vite.UserConfig & UserWorkspaceConfig = { + extends: false, test: { name: projectName, include, From 56d581c289dc5efcc6a88302cd11413022809ce6 Mon Sep 17 00:00:00 2001 From: Alan Agius <17563226+alan-agius4@users.noreply.github.com> Date: Mon, 7 Sep 2026 09:47:14 +0000 Subject: [PATCH 6/9] build: update @vitest/browser-webdriverio to 5.0.0-rc.1 Updates `@vitest/browser-webdriverio` to `^5.0.0-rc.1` in `latest-versions` and drops `{ force: true }` from package installation in Vitest E2E utilities. --- .../schematics/angular/utility/latest-versions/package.json | 2 +- tests/e2e/utils/vitest.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/schematics/angular/utility/latest-versions/package.json b/packages/schematics/angular/utility/latest-versions/package.json index 92b667724aaf..30a45ad40fe2 100644 --- a/packages/schematics/angular/utility/latest-versions/package.json +++ b/packages/schematics/angular/utility/latest-versions/package.json @@ -29,7 +29,7 @@ "@vitest/coverage-v8": "^5.0.0", "@vitest/coverage-istanbul": "^5.0.0", "@vitest/browser-playwright": "^5.0.0", - "@vitest/browser-webdriverio": "^4.0.8", + "@vitest/browser-webdriverio": "^5.0.0-rc.1", "@vitest/browser-preview": "^5.0.0", "playwright": "^1.48.0", "webdriverio": "^9.0.0", diff --git a/tests/e2e/utils/vitest.ts b/tests/e2e/utils/vitest.ts index 007c9287cece..01639c38996f 100644 --- a/tests/e2e/utils/vitest.ts +++ b/tests/e2e/utils/vitest.ts @@ -47,7 +47,7 @@ export async function applyVitestBuilder(options?: { } }); - await installWorkspacePackages({ force: true }); + await installWorkspacePackages(); await updateJsonFile('angular.json', (json) => { const projects = Object.values(json['projects']); From 4676a7cfc2b81545812648b246ac9da11dcf9a4c Mon Sep 17 00:00:00 2001 From: Alan Agius <17563226+alan-agius4@users.noreply.github.com> Date: Mon, 7 Sep 2026 10:04:24 +0000 Subject: [PATCH 7/9] test: add e2e test for Vitest browser configuration with Vitest v4 This commits adds a test to validate vitest version 4. --- .../vitest/browser-custom-config-vitest-v4.ts | 67 +++++++++++++++++++ tests/e2e/utils/vitest.ts | 7 +- 2 files changed, 72 insertions(+), 2 deletions(-) create mode 100644 tests/e2e/tests/vitest/browser-custom-config-vitest-v4.ts 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/utils/vitest.ts b/tests/e2e/utils/vitest.ts index 01639c38996f..f454a2784ee0 100644 --- a/tests/e2e/utils/vitest.ts +++ b/tests/e2e/utils/vitest.ts @@ -10,8 +10,9 @@ export async function applyVitestBuilder(options?: { coverageIstanbul?: boolean; playwright?: boolean; webdriver?: boolean; + skipInstall?: boolean; }): Promise { - const { coverageV8, coverageIstanbul, playwright, webdriver } = options ?? {}; + const { coverageV8, coverageIstanbul, playwright, webdriver, skipInstall } = options ?? {}; const schematicsAngular = createRequire(process.cwd() + '/').resolve( '@schematics/angular/package.json', @@ -47,7 +48,9 @@ export async function applyVitestBuilder(options?: { } }); - await installWorkspacePackages(); + if (!skipInstall) { + await installWorkspacePackages(); + } await updateJsonFile('angular.json', (json) => { const projects = Object.values(json['projects']); From 8cb0f7e45532ace045de0f19e393d8e208c1a1ec Mon Sep 17 00:00:00 2001 From: Alan Agius <17563226+alan-agius4@users.noreply.github.com> Date: Mon, 7 Sep 2026 11:56:58 +0000 Subject: [PATCH 8/9] refactor: remove Karma and Jasmine dependencies when initializing Vitest in e2e tests Reduce installations times --- tests/e2e/utils/vitest.ts | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/tests/e2e/utils/vitest.ts b/tests/e2e/utils/vitest.ts index f454a2784ee0..ebb9d9d12298 100644 --- a/tests/e2e/utils/vitest.ts +++ b/tests/e2e/utils/vitest.ts @@ -23,6 +23,19 @@ export async function applyVitestBuilder(options?: { 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']; From fbee73c1b3cc02245f3d7f3e1a3ebc381729e6ea Mon Sep 17 00:00:00 2001 From: Alan Agius <17563226+alan-agius4@users.noreply.github.com> Date: Tue, 8 Sep 2026 15:09:10 +0000 Subject: [PATCH 9/9] build: update @vitest/browser-webdriverio to version 5.0.0 Update `@vitest/browser-webdriverio` to the latest version. --- .../schematics/angular/utility/latest-versions/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/schematics/angular/utility/latest-versions/package.json b/packages/schematics/angular/utility/latest-versions/package.json index 30a45ad40fe2..111c8296c202 100644 --- a/packages/schematics/angular/utility/latest-versions/package.json +++ b/packages/schematics/angular/utility/latest-versions/package.json @@ -29,7 +29,7 @@ "@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-webdriverio": "^5.0.0", "@vitest/browser-preview": "^5.0.0", "playwright": "^1.48.0", "webdriverio": "^9.0.0",