diff --git a/packages/vitest/src/node/config/resolveConfig.ts b/packages/vitest/src/node/config/resolveConfig.ts index 18a050ebe..d549b041c 100644 --- a/packages/vitest/src/node/config/resolveConfig.ts +++ b/packages/vitest/src/node/config/resolveConfig.ts @@ -1056,7 +1056,7 @@ export async function resolveConfig( configLoader: options.configLoader, mode: options.mode || 'test', plugins: [ - CliOverride(cliOptionsCopy), + CliOverride(cliOptionsCopy, true), ...VitestConfigServer(pluginsHarness), ...VitestConfig(pluginsHarness), ...VitestCorePlugin(pluginsHarness, options), diff --git a/packages/vitest/src/node/plugins/cliOverride.ts b/packages/vitest/src/node/plugins/cliOverride.ts index 9fc05b5b3..1d45311db 100644 --- a/packages/vitest/src/node/plugins/cliOverride.ts +++ b/packages/vitest/src/node/plugins/cliOverride.ts @@ -4,7 +4,7 @@ import type { UserConfig } from '../types/config' import { deepMerge } from '@vitest/utils/helpers' import { mergeConfig } from 'vite' -export function CliOverride(cliOptions: UserConfig): Plugin { +export function CliOverride(cliOptions: UserConfig, isRootConfig = false): Plugin { return { // The CLI plugin overwrites config values with CLI options, making them // available in the next plugin. We have to do this via plugins because of watch mode. @@ -20,10 +20,10 @@ export function CliOverride(cliOptions: UserConfig): Plugin { // By default, Vite extends arrays, for example, but CLI options should have the priority config.test = deepMerge({}, config.test, options) - // apply browser CLI options only if the config already has the browser config and not disabled manually - if (config.test.browser && browser && (config.test.browser.enabled !== false || browser.enabled)) { + // Projects must opt into browser mode, but browser options can initialize the root config. + if (browser && (config.test.browser || isRootConfig) && (config.test.browser?.enabled !== false || browser.enabled)) { config.test.browser = mergeConfig( - config.test.browser, + config.test.browser || {}, browser, ) as ResolvedBrowserOptions } diff --git a/test/e2e/test/config/browser-configs.test.ts b/test/e2e/test/config/browser-configs.test.ts index 12511d2ec..b41d43e7d 100644 --- a/test/e2e/test/config/browser-configs.test.ts +++ b/test/e2e/test/config/browser-configs.test.ts @@ -132,6 +132,21 @@ test('assigns names as browsers', async () => { ]) }) +test('applies programmatic browser options without existing browser config', async () => { + const v = await vitest({ + $cliConfig: { + browser: { + enabled: true, + headless: true, + provider: preview(), + instances: [{ browser: 'chromium' }], + }, + }, + }) + + expect(v.projects.map(project => project.name)).toEqual(['chromium']) +}) + test('filters projects', async () => { const projects = await config({ project: 'chromium',