From d7a11537cccd57aa980dec7b887af6623f11d6cd Mon Sep 17 00:00:00 2001 From: maruthan Date: Fri, 27 Mar 2026 15:21:38 +0530 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 | 30 +++++++++-- .../angular/vitest-browser/index_spec.ts | 53 +++++++++++++++++++ 2 files changed, 80 insertions(+), 3 deletions(-) diff --git a/packages/schematics/angular/vitest-browser/index.ts b/packages/schematics/angular/vitest-browser/index.ts index 78c3bdc6179d..8bd36ead6635 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,33 @@ export default function (options: VitestBrowserOptions): Rule { } }; + // Determine the default browser based on the provider package + let defaultBrowser: string; + if (packageName === '@vitest/browser-webdriverio') { + defaultBrowser = 'chrome'; + } else { + // Playwright and preview both use 'chromium' as the default + defaultBrowser = 'chromium'; + } + + // Update angular.json to add the browsers option to the test target + const updateAngularJsonRule = updateWorkspace((workspace) => { + const project = workspace.projects.get(options.project); + if (project) { + const testTarget = project.targets.get('test'); + if (testTarget) { + testTarget.options ??= {}; + const existingBrowsers = testTarget.options['browsers'] as string[] | undefined; + if (!existingBrowsers?.length) { + testTarget.options['browsers'] = [defaultBrowser]; + } + } + } + }); + return chain([ updateTsConfigRule, + updateAngularJsonRule, ...dependencies.map((name) => addDependency(name, latestVersions[name], { type: DependencyType.Dev, @@ -101,8 +126,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 the default browser.`, ); }, ]); diff --git a/packages/schematics/angular/vitest-browser/index_spec.ts b/packages/schematics/angular/vitest-browser/index_spec.ts index 9027742f73a9..55338552ee5a 100644 --- a/packages/schematics/angular/vitest-browser/index_spec.ts +++ b/packages/schematics/angular/vitest-browser/index_spec.ts @@ -54,6 +54,59 @@ describe('Vitest Browser Provider Schematic', () => { expect(tsConfig.compilerOptions.types).not.toContain('jasmine'); }); + it('should add browsers option to angular.json for playwright', async () => { + const options = { + project: 'app', + package: '@vitest/browser-playwright', + skipInstall: true, + }; + + const resultTree = await schematicRunner.runSchematic('vitest-browser', options, tree); + + const angularJson = parse(resultTree.readContent('/angular.json')); + const project = angularJson.projects.app; + const targets = project.architect || project.targets; + expect(targets.test.options.browsers).toEqual(['chromium']); + }); + + it('should add browsers option to angular.json for webdriverio', async () => { + const options = { + project: 'app', + package: '@vitest/browser-webdriverio', + skipInstall: true, + }; + + const resultTree = await schematicRunner.runSchematic('vitest-browser', options, tree); + + const angularJson = parse(resultTree.readContent('/angular.json')); + const project = angularJson.projects.app; + const targets = project.architect || project.targets; + expect(targets.test.options.browsers).toEqual(['chrome']); + }); + + 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-playwright', + skipInstall: true, + }; + + const resultTree = await schematicRunner.runSchematic('vitest-browser', options, tree); + + 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 add webdriverio dependency when @vitest/browser-webdriverio is used', async () => { const options = { project: 'app',