From c3d0051d5c3a27a484b146f6540b6b1ad8af30e6 Mon Sep 17 00:00:00 2001 From: Maruthan G Date: Fri, 25 Sep 2026 09:46:41 +0000 Subject: [PATCH] fix(@schematics/angular): add browsers option to angular.json during vitest browser provider ng-add When adding a Vitest browser provider via ng-add, the schematic now automatically configures the 'browsers' option in angular.json with an appropriate default browser (chromium for Playwright/Preview, chrome for WebDriverIO) instead of only logging a manual instruction. Fixes #32401 --- .../angular/vitest-browser/index.ts | 16 ++++- .../angular/vitest-browser/index_spec.ts | 70 ++++++++++++++----- 2 files changed, 64 insertions(+), 22 deletions(-) diff --git a/packages/schematics/angular/vitest-browser/index.ts b/packages/schematics/angular/vitest-browser/index.ts index 78c3bdc6179d..927ac81aa4f1 100644 --- a/packages/schematics/angular/vitest-browser/index.ts +++ b/packages/schematics/angular/vitest-browser/index.ts @@ -22,7 +22,7 @@ import { } from '../utility/dependency'; import { JSONFile } from '../utility/json-file'; import { latestVersions } from '../utility/latest-versions'; -import { getWorkspace } from '../utility/workspace'; +import { getWorkspace, updateWorkspace } from '../utility/workspace'; import { Builders } from '../utility/workspace-models'; import { Schema as VitestBrowserOptions } from './schema'; @@ -89,8 +89,19 @@ export default function (options: VitestBrowserOptions): Rule { } }; + // Update angular.json to add the browsers option to the test target + const defaultBrowser = packageName === '@vitest/browser-webdriverio' ? 'chrome' : 'chromium'; + return chain([ updateTsConfigRule, + updateWorkspace((workspace) => { + const testTarget = workspace.projects.get(options.project)?.targets.get('test'); + + if (testTarget) { + testTarget.options ??= {}; + testTarget.options['browsers'] ??= [defaultBrowser]; + } + }), ...dependencies.map((name) => addDependency(name, latestVersions[name], { type: DependencyType.Dev, @@ -101,8 +112,7 @@ export default function (options: VitestBrowserOptions): Rule { (_, context) => { context.logger.info( 'Vitest browser testing support has been added. ' + - "To run tests in a browser, add a 'browsers' field to the 'test' target in 'angular.json', " + - "or use the '--browsers' command line option.", + `The test target has been configured with '${defaultBrowser}' as browser.`, ); }, ]); diff --git a/packages/schematics/angular/vitest-browser/index_spec.ts b/packages/schematics/angular/vitest-browser/index_spec.ts index 9027742f73a9..83ac0a9d55a6 100644 --- a/packages/schematics/angular/vitest-browser/index_spec.ts +++ b/packages/schematics/angular/vitest-browser/index_spec.ts @@ -35,37 +35,69 @@ describe('Vitest Browser Provider Schematic', () => { ); }); - it('should add dependencies and update tsconfig.spec.json', async () => { - const options = { - project: 'app', - package: '@vitest/browser-playwright', - skipInstall: true, - }; + [ + { pkg: '@vitest/browser-playwright', browser: 'chromium', extraDeps: ['playwright'] }, + { pkg: '@vitest/browser-webdriverio', browser: 'chrome', extraDeps: ['webdriverio'] }, + { pkg: '@vitest/browser-preview', browser: 'chromium', extraDeps: [] as string[] }, + ].forEach(({ pkg, browser, extraDeps }) => { + it(`should add ${browser} to browsers option in angular.json for ${pkg}`, async () => { + const options = { + project: 'app', + package: pkg, + skipInstall: true, + }; - const resultTree = await schematicRunner.runSchematic('vitest-browser', options, tree); + const resultTree = await schematicRunner.runSchematic('vitest-browser', options, tree); - const packageJson = parse(resultTree.readContent('/package.json')); - expect(packageJson.devDependencies['@vitest/browser-playwright']).toBeDefined(); - expect(packageJson.devDependencies['playwright']).toBeDefined(); + const angularJson = parse(resultTree.readContent('/angular.json')); + const project = angularJson.projects.app; + const targets = project.architect || project.targets; + expect(targets.test.options.browsers).toEqual([browser]); + }); - const tsConfig = parse(resultTree.readContent('/projects/app/tsconfig.spec.json')); - expect(tsConfig.compilerOptions.types).toContain('vitest/globals'); - expect(tsConfig.compilerOptions.types).toContain('@vitest/browser-playwright'); - expect(tsConfig.compilerOptions.types).not.toContain('jasmine'); + it(`should add dependencies and update tsconfig.spec.json for ${pkg}`, async () => { + const options = { + project: 'app', + package: pkg, + skipInstall: true, + }; + + const resultTree = await schematicRunner.runSchematic('vitest-browser', options, tree); + + const packageJson = parse(resultTree.readContent('/package.json')); + expect(packageJson.devDependencies[pkg]).toBeDefined(); + for (const dep of extraDeps) { + expect(packageJson.devDependencies[dep]).toBeDefined(); + } + + const tsConfig = parse(resultTree.readContent('/projects/app/tsconfig.spec.json')); + expect(tsConfig.compilerOptions.types).toContain('vitest/globals'); + expect(tsConfig.compilerOptions.types).toContain(pkg); + expect(tsConfig.compilerOptions.types).not.toContain('jasmine'); + }); }); - it('should add webdriverio dependency when @vitest/browser-webdriverio is used', async () => { + it('should not overwrite existing browsers option in angular.json', async () => { + // Set up existing browsers option + const angularJson = parse(tree.readContent('/angular.json')); + const project = angularJson.projects.app; + const targets = project.architect || project.targets; + targets.test.options ??= {}; + targets.test.options.browsers = ['firefox']; + tree.overwrite('/angular.json', JSON.stringify(angularJson)); + const options = { project: 'app', - package: '@vitest/browser-webdriverio', + package: '@vitest/browser-playwright', skipInstall: true, }; const resultTree = await schematicRunner.runSchematic('vitest-browser', options, tree); - const packageJson = parse(resultTree.readContent('/package.json')); - expect(packageJson.devDependencies['@vitest/browser-webdriverio']).toBeDefined(); - expect(packageJson.devDependencies['webdriverio']).toBeDefined(); + const updatedAngularJson = parse(resultTree.readContent('/angular.json')); + const updatedProject = updatedAngularJson.projects.app; + const updatedTargets = updatedProject.architect || updatedProject.targets; + expect(updatedTargets.test.options.browsers).toEqual(['firefox']); }); it('should update tsconfig.spec.json for a library project', async () => {