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..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 () => {