diff --git a/packages/vitest/src/node/cli/cac.ts b/packages/vitest/src/node/cli/cac.ts index e7f3aa938337..d0e4dafc1f70 100644 --- a/packages/vitest/src/node/cli/cac.ts +++ b/packages/vitest/src/node/cli/cac.ts @@ -283,10 +283,6 @@ function normalizeCliOptions(cliFilters: string[], argv: CliOptions): CliOptions argv.includeTaskLocation ??= true } - // running "vitest --browser.headless" - if (typeof argv.browser === 'object' && !('enabled' in argv.browser)) { - argv.browser.enabled = true - } if (typeof argv.typecheck?.only === 'boolean') { argv.typecheck.enabled ??= true } diff --git a/packages/vitest/src/node/cli/cli-config.ts b/packages/vitest/src/node/cli/cli-config.ts index fd967adc0596..334d7f81bc6e 100644 --- a/packages/vitest/src/node/cli/cli-config.ts +++ b/packages/vitest/src/node/cli/cli-config.ts @@ -361,7 +361,7 @@ export const cliOptionsConfig: VitestCLIOptions = { return { enabled: browser === 'yes' } } if (typeof browser === 'string') { - return { enabled: true, name: browser } + return { name: browser } } return browser }, diff --git a/packages/vitest/src/node/config/resolveConfig.ts b/packages/vitest/src/node/config/resolveConfig.ts index 39f66bdd5b01..048cddb2dbeb 100644 --- a/packages/vitest/src/node/config/resolveConfig.ts +++ b/packages/vitest/src/node/config/resolveConfig.ts @@ -1,6 +1,7 @@ import type { ResolvedConfig as ResolvedViteConfig } from 'vite' import type { Vitest } from '../core' import type { BenchmarkBuiltinReporters } from '../reporters' +import type { ResolvedBrowserOptions } from '../types/browser' import type { ApiConfig, ResolvedConfig, @@ -13,6 +14,7 @@ import { toArray } from '@vitest/utils' import { resolveModule } from 'local-pkg' import { normalize, relative, resolve } from 'pathe' import c from 'tinyrainbow' +import { mergeConfig } from 'vite' import { defaultBrowserPort, defaultInspectPort, @@ -199,8 +201,6 @@ export function resolveConfig( resolved.minWorkers = resolveInlineWorkerOption(resolved.minWorkers) } - resolved.browser ??= {} as any - // run benchmark sequentially by default resolved.fileParallelism ??= mode !== 'benchmark' @@ -232,10 +232,23 @@ export function resolveConfig( } } + // apply browser CLI options only if the config already has the browser config and not disabled manually + if ( + vitest._cliOptions.browser + && resolved.browser + // if enabled is set to `false`, but CLI overrides it, then always override it + && (resolved.browser.enabled !== false || vitest._cliOptions.browser.enabled) + ) { + resolved.browser = mergeConfig( + resolved.browser, + vitest._cliOptions.browser, + ) as ResolvedBrowserOptions + } + + resolved.browser ??= {} as any const browser = resolved.browser - // if browser was enabled via CLI and it's configured by the user, then validate the input - if (browser.enabled && viteConfig.test?.browser) { + if (browser.enabled) { if (!browser.name && !browser.instances) { throw new Error(`Vitest Browser Mode requires "browser.name" (deprecated) or "browser.instances" options, none were set.`) } @@ -800,7 +813,6 @@ export function resolveConfig( ) } - resolved.browser ??= {} as any resolved.browser.enabled ??= false resolved.browser.headless ??= isCI resolved.browser.isolate ??= true diff --git a/packages/vitest/src/node/core.ts b/packages/vitest/src/node/core.ts index 515e4e690302..96cc7f6f98d4 100644 --- a/packages/vitest/src/node/core.ts +++ b/packages/vitest/src/node/core.ts @@ -5,6 +5,7 @@ import type { ViteDevServer } from 'vite' import type { defineWorkspace } from 'vitest/config' import type { SerializedCoverageConfig } from '../runtime/config' import type { ArgumentsType, ProvidedContext, UserConsoleLog } from '../types/general' +import type { CliOptions } from './cli/cli-api' import type { ProcessPool, WorkspaceSpec } from './pool' import type { TestSpecification } from './spec' import type { ResolvedConfig, TestProjectConfiguration, UserConfig, VitestRunMode } from './types/config' @@ -97,7 +98,7 @@ export class Vitest { resolvedProjects: TestProject[] = [] /** @internal */ _browserLastPort = defaultBrowserPort /** @internal */ _browserSessions = new BrowserSessions() - /** @internal */ _options: UserConfig = {} + /** @internal */ _cliOptions: CliOptions = {} /** @internal */ reporters: Reporter[] = [] /** @internal */ vitenode: ViteNodeServer = undefined! /** @internal */ runner: ViteNodeRunner = undefined! @@ -118,8 +119,10 @@ export class Vitest { constructor( public readonly mode: VitestRunMode, + cliOptions: UserConfig, options: VitestOptions = {}, ) { + this._cliOptions = cliOptions this.logger = new Logger(this, options.stdout, options.stderr) this.packageInstaller = options.packageInstaller || new VitestPackageInstaller() this.specifications = new VitestSpecifications(this) @@ -192,13 +195,12 @@ export class Vitest { } /** @deprecated internal */ - setServer(options: UserConfig, server: ViteDevServer, cliOptions: UserConfig): Promise { - return this._setServer(options, server, cliOptions) + setServer(options: UserConfig, server: ViteDevServer): Promise { + return this._setServer(options, server) } /** @internal */ - async _setServer(options: UserConfig, server: ViteDevServer, cliOptions: UserConfig) { - this._options = options + async _setServer(options: UserConfig, server: ViteDevServer) { this.watcher.unregisterWatcher() clearTimeout(this._rerunTimer) this.restartsCount += 1 @@ -274,7 +276,7 @@ export class Vitest { } catch { } - const projects = await this.resolveWorkspace(cliOptions) + const projects = await this.resolveWorkspace(this._cliOptions) this.resolvedProjects = projects this.projects = projects @@ -287,7 +289,7 @@ export class Vitest { })) })) - if (options.browser?.enabled) { + if (this._cliOptions.browser?.enabled) { const browserProjects = this.projects.filter(p => p.config.browser.enabled) if (!browserProjects.length) { throw new Error(`Vitest received --browser flag, but no project had a browser configuration.`) @@ -327,7 +329,7 @@ export class Vitest { const currentNames = new Set(this.projects.map(p => p.name)) const workspace = await resolveWorkspace( this, - this._options, + this._cliOptions, undefined, Array.isArray(config) ? config : [config], currentNames, @@ -1308,7 +1310,7 @@ export class Vitest { * Check if the project with a given name should be included. */ matchesProjectFilter(name: string): boolean { - const projects = this._config?.project || this._options?.project + const projects = this._config?.project || this._cliOptions?.project // no filters applied, any project can be included if (!projects || !projects.length) { return true diff --git a/packages/vitest/src/node/create.ts b/packages/vitest/src/node/create.ts index 078362168b9a..26d54f82bac0 100644 --- a/packages/vitest/src/node/create.ts +++ b/packages/vitest/src/node/create.ts @@ -6,7 +6,7 @@ import type { CliOptions } from './cli/cli-api' import type { VitestOptions } from './core' import type { VitestRunMode } from './types/config' import { resolve } from 'node:path' -import { slash } from '@vitest/utils' +import { deepClone, slash } from '@vitest/utils' import { findUp } from 'find-up' import { mergeConfig } from 'vite' import { configFiles } from '../constants' @@ -20,7 +20,7 @@ export async function createVitest( viteOverrides: ViteUserConfig = {}, vitestOptions: VitestOptions = {}, ): Promise { - const ctx = new Vitest(mode, vitestOptions) + const ctx = new Vitest(mode, deepClone(options), vitestOptions) const root = slash(resolve(options.root || process.cwd())) const configPath @@ -32,12 +32,14 @@ export async function createVitest( options.config = configPath + const { browser: _removeBrowser, ...restOptions } = options + const config: ViteInlineConfig = { configFile: configPath, configLoader: options.configLoader, // this will make "mode": "test" | "benchmark" inside defineConfig mode: options.mode || mode, - plugins: await VitestPlugin(options, ctx), + plugins: await VitestPlugin(restOptions, ctx), } const server = await createViteServer( diff --git a/packages/vitest/src/node/plugins/index.ts b/packages/vitest/src/node/plugins/index.ts index 19ef092fc42d..5644ec41a8c4 100644 --- a/packages/vitest/src/node/plugins/index.ts +++ b/packages/vitest/src/node/plugins/index.ts @@ -1,6 +1,7 @@ import type { UserConfig as ViteConfig, Plugin as VitePlugin } from 'vite' import type { ResolvedConfig, UserConfig } from '../types/config' import { + deepClone, deepMerge, notNullish, toArray, @@ -27,13 +28,13 @@ import { VitestCoreResolver } from './vitestResolver' export async function VitestPlugin( options: UserConfig = {}, - ctx: Vitest = new Vitest('test'), + vitest: Vitest = new Vitest('test', deepClone(options)), ): Promise { const userConfig = deepMerge({}, options) as UserConfig async function UIPlugin() { - await ctx.packageInstaller.ensureInstalled('@vitest/ui', options.root || process.cwd(), ctx.version) - return (await import('@vitest/ui')).default(ctx) + await vitest.packageInstaller.ensureInstalled('@vitest/ui', options.root || process.cwd(), vitest.version) + return (await import('@vitest/ui')).default(vitest) } return [ @@ -143,13 +144,13 @@ export async function VitestPlugin( }, } - if (ctx.configOverride.project) { + if (vitest.configOverride.project) { // project filter was set by the user, so we need to filter the project - options.project = ctx.configOverride.project + options.project = vitest.configOverride.project } config.customLogger = createViteLogger( - ctx.logger, + vitest.logger, viteConfig.logLevel || 'warn', { allowClearScreen: false, @@ -207,7 +208,7 @@ export async function VitestPlugin( name: string, filename: string, ) => { - const root = ctx.config.root || options.root || process.cwd() + const root = vitest.config.root || options.root || process.cwd() return generateScopedClassName( classNameStrategy, name, @@ -258,7 +259,7 @@ export async function VitestPlugin( }) const originalName = options.name - if (options.browser?.enabled && options.browser?.instances) { + if (options.browser?.instances) { options.browser.instances.forEach((instance) => { instance.name ??= originalName ? `${originalName} (${instance.browser})` : instance.browser }) @@ -274,9 +275,9 @@ export async function VitestPlugin( console.log('[debug] watcher is ready') }) } - await ctx._setServer(options, server, userConfig) + await vitest._setServer(options, server) if (options.api && options.watch) { - (await import('../../api/setup')).setup(ctx) + (await import('../../api/setup')).setup(vitest) } // #415, in run mode we don't need the watcher, close it would improve the performance @@ -287,9 +288,9 @@ export async function VitestPlugin( }, }, SsrReplacerPlugin(), - ...CSSEnablerPlugin(ctx), - CoverageTransform(ctx), - VitestCoreResolver(ctx), + ...CSSEnablerPlugin(vitest), + CoverageTransform(vitest), + VitestCoreResolver(vitest), options.ui ? await UIPlugin() : null, ...MocksPlugins(), VitestOptimizer(), diff --git a/packages/vitest/src/node/plugins/publicConfig.ts b/packages/vitest/src/node/plugins/publicConfig.ts index f58038b691d7..927b50894e18 100644 --- a/packages/vitest/src/node/plugins/publicConfig.ts +++ b/packages/vitest/src/node/plugins/publicConfig.ts @@ -3,7 +3,7 @@ import type { UserConfig as ViteUserConfig, } from 'vite' import type { ResolvedConfig, UserConfig } from '../types/config' -import { slash } from '@vitest/utils' +import { deepClone, slash } from '@vitest/utils' import { findUp } from 'find-up' import { resolve } from 'pathe' import { mergeConfig, resolveConfig as resolveViteConfig } from 'vite' @@ -27,7 +27,7 @@ export async function resolveConfig( : await findUp(configFiles, { cwd: root } as any) options.config = configPath - const vitest = new Vitest('test') + const vitest = new Vitest('test', deepClone(options)) const config = await resolveViteConfig( mergeConfig( { diff --git a/packages/vitest/src/node/plugins/workspace.ts b/packages/vitest/src/node/plugins/workspace.ts index ed88068ed993..05bbe24e1821 100644 --- a/packages/vitest/src/node/plugins/workspace.ts +++ b/packages/vitest/src/node/plugins/workspace.ts @@ -4,7 +4,6 @@ import type { ResolvedConfig, TestProjectInlineConfiguration } from '../types/co import { existsSync, readFileSync } from 'node:fs' import { deepMerge } from '@vitest/utils' import { basename, dirname, relative, resolve } from 'pathe' -import { mergeConfig } from 'vite' import { configDefaults } from '../../defaults' import { generateScopedClassName } from '../../integrations/css/css-modules' import { VitestFilteredOutProjectError } from '../errors' @@ -112,32 +111,25 @@ export function WorkspaceVitestPlugin( }, } - // if this project defines a browser configuration, respect --browser flag - // otherwise if we always override the configuration, every project will run in browser mode - if (project.vitest._options.browser && viteConfig.test?.browser) { - viteConfig.test.browser = mergeConfig( - viteConfig.test.browser, - project.vitest._options.browser, - ) - } - - (config.test as ResolvedConfig).defines = defines + ;(config.test as ResolvedConfig).defines = defines + const isUserBrowserEnabled = viteConfig.test?.browser?.enabled + const isBrowserEnabled = isUserBrowserEnabled ?? (viteConfig.test?.browser && project.vitest._cliOptions.browser?.enabled) // keep project names to potentially filter it out const workspaceNames = [name] - if (viteConfig.test?.browser?.enabled) { - if (viteConfig.test.browser.name && !viteConfig.test.browser.instances?.length) { - const browser = viteConfig.test.browser.name - // vitest injects `instances` in this case later on - workspaceNames.push(name ? `${name} (${browser})` : browser) - } + const browser = viteConfig.test!.browser || {} + if (isBrowserEnabled && browser.name && !browser.instances?.length) { + // vitest injects `instances` in this case later on + workspaceNames.push(name ? `${name} (${browser.name})` : browser.name) + } - viteConfig.test.browser.instances?.forEach((instance) => { - // every instance is a potential project - instance.name ??= name ? `${name} (${instance.browser})` : instance.browser + viteConfig.test?.browser?.instances?.forEach((instance) => { + // every instance is a potential project + instance.name ??= name ? `${name} (${instance.browser})` : instance.browser + if (isBrowserEnabled) { workspaceNames.push(instance.name) - }) - } + } + }) const filters = project.vitest.config.project // if there is `--project=...` filter, check if any of the potential projects match diff --git a/test/cli/fixtures/public-api/vitest.config.ts b/test/cli/fixtures/public-api/vitest.config.ts index 56004c9f9e06..5dc5b97d2a1f 100644 --- a/test/cli/fixtures/public-api/vitest.config.ts +++ b/test/cli/fixtures/public-api/vitest.config.ts @@ -1 +1,11 @@ -export default {} \ No newline at end of file +import { defineConfig } from 'vitest/config' + +export default defineConfig({ + test: { + browser: { + provider: 'playwright', + instances: [{ browser: 'chromium' }], + headless: true, + }, + }, +}) diff --git a/test/cli/test/public-api.test.ts b/test/cli/test/public-api.test.ts index 8c0638f3b4f0..0d15054bf9be 100644 --- a/test/cli/test/public-api.test.ts +++ b/test/cli/test/public-api.test.ts @@ -11,9 +11,6 @@ it.each([ name: 'running in the browser', browser: { enabled: true, - provider: 'playwright', - instances: [{ browser: 'chromium' }], - headless: true, }, }, ] as UserConfig[])('passes down metadata when $name', { timeout: 60_000, retry: 1 }, async (config) => { diff --git a/test/config/fixtures/bail/vitest.config.ts b/test/config/fixtures/bail/vitest.config.ts index 0a7dfa7957b9..b5ead47cb18e 100644 --- a/test/config/fixtures/bail/vitest.config.ts +++ b/test/config/fixtures/bail/vitest.config.ts @@ -29,10 +29,6 @@ export default defineConfig({ }, browser: { headless: true, - provider: 'webdriverio', - instances: [ - { browser: 'chrome' }, - ], }, }, }) diff --git a/test/config/fixtures/browser-no-config/vitest.config.ts b/test/config/fixtures/browser-no-config/vitest.config.ts index 76c887590f00..35b54686abcf 100644 --- a/test/config/fixtures/browser-no-config/vitest.config.ts +++ b/test/config/fixtures/browser-no-config/vitest.config.ts @@ -3,7 +3,7 @@ import { defineConfig } from 'vitest/config'; export default defineConfig({ test: { browser: { - enabled: false, + headless: true, }, }, }) \ No newline at end of file diff --git a/test/config/test/bail.test.ts b/test/config/test/bail.test.ts index 79b8a671dce9..e9a370a614da 100644 --- a/test/config/test/bail.test.ts +++ b/test/config/test/bail.test.ts @@ -16,6 +16,7 @@ if (process.platform !== 'win32') { browser: { enabled: true, provider: 'playwright', + headless: true, fileParallelism: false, instances: [ { browser: 'chromium' }, @@ -26,6 +27,7 @@ if (process.platform !== 'win32') { browser: { enabled: true, provider: 'playwright', + headless: true, fileParallelism: true, instances: [ { browser: 'chromium' }, @@ -72,9 +74,12 @@ for (const config of configs) { const { exitCode, stdout, ctx } = await runVitest({ root: './fixtures/bail', bail: 1, - ...config, - env: { - THREADS: process.env.THREADS, + }, [], 'test', { + test: { + ...config, + env: { + THREADS: process.env.THREADS, + }, }, }) diff --git a/test/config/test/browser-configs.test.ts b/test/config/test/browser-configs.test.ts index a9113914ca77..d8e65916dbda 100644 --- a/test/config/test/browser-configs.test.ts +++ b/test/config/test/browser-configs.test.ts @@ -14,7 +14,7 @@ async function vitest(cliOptions: UserConfig, configValue: UserConfig = {}, vite } test('assigns names as browsers', async () => { - const { projects } = await vitest({ + const { projects } = await vitest({}, { browser: { enabled: true, headless: true, @@ -33,8 +33,7 @@ test('assigns names as browsers', async () => { }) test('filters projects', async () => { - const { projects } = await vitest({ - project: 'chromium', + const { projects } = await vitest({ project: 'chromium' }, { browser: { enabled: true, instances: [ @@ -50,8 +49,7 @@ test('filters projects', async () => { }) test('filters projects with a wildcard', async () => { - const { projects } = await vitest({ - project: 'chrom*', + const { projects } = await vitest({ project: 'chrom*' }, { browser: { enabled: true, instances: [ @@ -67,7 +65,7 @@ test('filters projects with a wildcard', async () => { }) test('assignes names as browsers in a custom project', async () => { - const { projects } = await vitest({ + const { projects } = await vitest({}, { workspace: [ { test: { @@ -95,7 +93,7 @@ test('assignes names as browsers in a custom project', async () => { }) test('inherits browser options', async () => { - const { projects } = await vitest({ + const { projects } = await vitest({}, { setupFiles: ['/test/setup.ts'], provide: { browser: true, @@ -183,30 +181,33 @@ test('inherits browser options', async () => { }) test('coverage provider v8 works correctly in browser mode if instances are filtered', async () => { - const { projects } = await vitest({ - project: 'chromium', - coverage: { - enabled: true, - provider: 'v8', + const { projects } = await vitest( + { + project: 'chromium', }, - browser: { - enabled: true, - provider: 'playwright', - instances: [ - { browser: 'chromium' }, - { browser: 'firefox' }, - { browser: 'webkit' }, - ], + { + coverage: { + enabled: true, + provider: 'v8', + }, + browser: { + enabled: true, + provider: 'playwright', + instances: [ + { browser: 'chromium' }, + { browser: 'firefox' }, + { browser: 'webkit' }, + ], + }, }, - }) + ) expect(projects.map(p => p.name)).toEqual([ 'chromium', ]) }) test('coverage provider v8 works correctly in workspaced browser mode if instances are filtered', async () => { - const { projects } = await vitest({ - project: 'browser (chromium)', + const { projects } = await vitest({ project: 'browser (chromium)' }, { workspace: [ { test: { @@ -234,8 +235,7 @@ test('coverage provider v8 works correctly in workspaced browser mode if instanc }) test('filter for the global browser project includes all browser instances', async () => { - const { projects } = await vitest({ - project: 'myproject', + const { projects } = await vitest({ project: 'myproject' }, { workspace: [ { test: { @@ -534,4 +534,146 @@ describe('[e2e] workspace configs are affected by the CLI options', () => { }, }) }) + + test('correctly resolves extended project', async () => { + const { stdout } = await getCliConfig({ + browser: { + provider: 'playwright', + headless: true, + instances: [ + { browser: 'chromium' }, + ], + }, + workspace: [ + { + extends: true, + test: { + name: 'node', + }, + }, + { + extends: true, + test: { + name: 'browser', + browser: { + enabled: true, + }, + }, + }, + ], + }, []) + + const config = JSON.parse(stdout) + + expect(config.workspace).toHaveLength(2) + expect(config.workspace[0]).toEqual({ + name: 'node', + headless: true, + browser: false, + ui: false, + parent: null, + }) + + expect(config.workspace[1]).toEqual({ + name: 'browser (chromium)', + headless: true, + browser: true, + ui: false, + parent: { + name: 'browser', + headless: true, + browser: true, + ui: false, + }, + }) + }) + + test('correctly overrides extended project', async () => { + const { stdout } = await getCliConfig({ + browser: { + provider: 'playwright', + headless: true, + instances: [ + { browser: 'chromium' }, + ], + }, + workspace: [ + { + extends: true, + test: { + name: 'node', + }, + }, + { + extends: true, + test: { + name: 'browser', + browser: { + enabled: true, + }, + }, + }, + ], + }, ['--browser.headless=false']) + + const config = JSON.parse(stdout) + + expect(config.workspace).toHaveLength(2) + expect(config.workspace[0]).toEqual({ + name: 'node', + headless: false, + browser: false, + ui: true, + parent: null, + }) + + expect(config.workspace[1]).toEqual({ + name: 'browser (chromium)', + headless: false, + browser: true, + ui: true, + parent: { + name: 'browser', + headless: false, + browser: true, + ui: true, + }, + }) + }) + + test('CLI options override the config if --browser.enabled is passed down manually', async () => { + const { stdout } = await getCliConfig({ + browser: { + enabled: false, + provider: 'playwright', + headless: true, + instances: [ + { browser: 'chromium' }, + ], + }, + }, ['--browser.headless=false', '--browser.enabled']) + + const config = JSON.parse(stdout) + expect(config).toEqual({ + browser: { + headless: false, + browser: true, + ui: true, + }, + workspace: [ + { + name: 'chromium', + headless: false, + browser: true, + ui: true, + parent: { + name: '', + headless: false, + browser: true, + ui: true, + }, + }, + ], + }) + }) }) diff --git a/test/config/test/failures.test.ts b/test/config/test/failures.test.ts index c0f561042ca1..c2dee1c84b1b 100644 --- a/test/config/test/failures.test.ts +++ b/test/config/test/failures.test.ts @@ -90,13 +90,15 @@ test('inspect and --inspect-brk cannot be used when not playwright + chromium', continue } - const { stderr } = await runVitest({ - [option]: true, - fileParallelism: false, - browser: { - enabled: true, - provider, - name, + const { stderr } = await runVitest({}, { + test: { + [option]: true, + fileParallelism: false, + browser: { + enabled: true, + provider, + name, + }, }, }) @@ -134,14 +136,16 @@ test('v8 coverage provider throws when not playwright + chromium (browser.name)' continue } - const { stderr } = await runVitest({ - coverage: { - enabled: true, - }, - browser: { - enabled: true, - provider, - name, + const { stderr } = await runVitest({}, { + test: { + coverage: { + enabled: true, + }, + browser: { + enabled: true, + provider, + name, + }, }, }) @@ -183,14 +187,16 @@ test('v8 coverage provider throws when not playwright + chromium (browser.instan continue } - const { stderr } = await runVitest({ - coverage: { - enabled: true, - }, - browser: { - enabled: true, - provider, - instances: [{ browser: name }], + const { stderr } = await runVitest({}, { + test: { + coverage: { + enabled: true, + }, + browser: { + enabled: true, + provider, + instances: [{ browser: name }], + }, }, }) @@ -231,19 +237,21 @@ Use either: }) test('v8 coverage provider throws when using chromium and other non-chromium browser', async () => { - const { stderr } = await runVitest({ - coverage: { - enabled: true, - }, - browser: { - enabled: true, - headless: true, - provider: 'playwright', - instances: [ - { browser: 'chromium' }, - { browser: 'firefox' }, - { browser: 'webkit' }, - ], + const { stderr } = await runVitest({}, { + test: { + coverage: { + enabled: true, + }, + browser: { + enabled: true, + headless: true, + provider: 'playwright', + instances: [ + { browser: 'chromium' }, + { browser: 'firefox' }, + { browser: 'webkit' }, + ], + }, }, }) @@ -480,50 +488,56 @@ test('browser.instances throws an error if no custom name is provided', async () }) test('browser.instances throws an error if no custom name is provided, but the config name is inherited', async () => { - const { stderr } = await runVitest({ - name: 'custom', - browser: { - enabled: true, - provider: 'playwright', - instances: [ - { browser: 'firefox' }, - { browser: 'firefox' }, - ], + const { stderr } = await runVitest({}, { + test: { + name: 'custom', + browser: { + enabled: true, + provider: 'playwright', + instances: [ + { browser: 'firefox' }, + { browser: 'firefox' }, + ], + }, }, }) expect(stderr).toMatch('Cannot define a nested project for a firefox browser. The project name "custom (firefox)" was already defined. If you have multiple instances for the same browser, make sure to define a custom "name". All projects in a workspace should have unique names. Make sure your configuration is correct.') }) test('throws an error if name conflicts with a workspace name', async () => { - const { stderr } = await runVitest({ - workspace: [ - { test: { name: '1 (firefox)' } }, - { - test: { - browser: { - enabled: true, - provider: 'playwright', - instances: [ - { browser: 'firefox' }, - ], + const { stderr } = await runVitest({}, { + test: { + workspace: [ + { test: { name: '1 (firefox)' } }, + { + test: { + browser: { + enabled: true, + provider: 'playwright', + instances: [ + { browser: 'firefox' }, + ], + }, }, }, - }, - ], + ], + }, }) expect(stderr).toMatch('Cannot define a nested project for a firefox browser. The project name "1 (firefox)" was already defined. If you have multiple instances for the same browser, make sure to define a custom "name". All projects in a workspace should have unique names. Make sure your configuration is correct.') }) test('throws an error if several browsers are headed in nonTTY mode', async () => { - const { stderr } = await runVitest({ - browser: { - enabled: true, - provider: 'playwright', - headless: false, - instances: [ - { browser: 'chromium' }, - { browser: 'firefox' }, - ], + const { stderr } = await runVitest({}, { + test: { + browser: { + enabled: true, + provider: 'playwright', + headless: false, + instances: [ + { browser: 'chromium' }, + { browser: 'firefox' }, + ], + }, }, }) expect(stderr).toContain('Found multiple projects that run browser tests in headed mode: "chromium", "firefox"') diff --git a/test/core/test/cli-test.test.ts b/test/core/test/cli-test.test.ts index 4638bc734396..6139e246dba5 100644 --- a/test/core/test/cli-test.test.ts +++ b/test/core/test/cli-test.test.ts @@ -269,7 +269,7 @@ test('browser by name', () => { const { options, args } = parseArguments('--browser=firefox', false) expect(args).toEqual([]) - expect(options).toEqual({ browser: { enabled: true, name: 'firefox' } }) + expect(options).toEqual({ browser: { name: 'firefox' } }) }) test('clearScreen', async () => { @@ -292,7 +292,11 @@ test('clearScreen', async () => { clearScreen: viteClearScreen, } const vitestConfig = getCLIOptions(vitestClearScreen) - const config = resolveConfig({ logger: undefined, mode: 'test' } as any, vitestConfig, viteConfig) + const config = resolveConfig({ + logger: undefined, + mode: 'test', + _cliOptions: {}, + } as any, vitestConfig, viteConfig) return config.clearScreen }) expect(results).toMatchInlineSnapshot(` @@ -373,7 +377,7 @@ test('public parseCLI works correctly', () => { filter: [], options: { 'coverage': { enabled: true }, - 'browser': { enabled: true, name: 'chrome' }, + 'browser': { name: 'chrome' }, '--': [], 'color': true, }, diff --git a/test/coverage-test/utils.ts b/test/coverage-test/utils.ts index ced512c1a1aa..4439e6e6227d 100644 --- a/test/coverage-test/utils.ts +++ b/test/coverage-test/utils.ts @@ -35,23 +35,26 @@ export async function runVitest(config: UserConfig, options = { throwOnError: tr config: 'fixtures/configs/vitest.config.ts', pool: 'threads', ...config, - env: { - COVERAGE_TEST: 'true', - ...config.env, - }, - coverage: { - enabled: true, - reporter: [], - ...config.coverage, - provider, - customProviderModule: provider === 'custom' ? 'fixtures/custom-provider' : undefined, - }, - browser: { - enabled: process.env.COVERAGE_BROWSER === 'true', - headless: true, - instances: [{ browser: 'chromium' }], - provider: 'playwright', - ...config.browser, + browser: config.browser, + }, [], 'test', { + test: { + env: { + COVERAGE_TEST: 'true', + ...config.env, + }, + coverage: { + enabled: true, + reporter: [], + ...config.coverage, + provider: provider === 'v8-ast-aware' ? 'v8' : provider, + customProviderModule: provider === 'custom' ? 'fixtures/custom-provider' : undefined, + }, + browser: { + enabled: process.env.COVERAGE_BROWSER === 'true', + headless: true, + instances: [{ browser: 'chromium' }], + provider: 'playwright', + }, }, }) diff --git a/test/test-utils/index.ts b/test/test-utils/index.ts index 7a59306ca56d..3904cc9fca9f 100644 --- a/test/test-utils/index.ts +++ b/test/test-utils/index.ts @@ -27,7 +27,7 @@ export interface VitestRunnerCLIOptions { } export async function runVitest( - config: UserConfig, + cliOptions: UserConfig, cliFilters: string[] = [], mode: VitestRunMode = 'test', viteOverrides: ViteUserConfig = {}, @@ -72,7 +72,7 @@ export async function runVitest( let ctx: Vitest | undefined let thrown = false try { - const { reporters, ...rest } = config + const { reporters, ...rest } = cliOptions ctx = await startVitest(mode, cliFilters, { watch: false,