···234234235235 const browser = resolved.browser
236236237237- if (browser.enabled) {
237237+ // if browser was enabled via CLI and it's configured by the user, then validate the input
238238+ if (browser.enabled && viteConfig.test?.browser) {
238239 if (!browser.name && !browser.instances) {
239239- // CLI can enable `--browser.*` flag to change config of workspace projects
240240- // the same flag will be applied to the root config that doesn't have to have "name" or "instances"
241241- // in this case we just disable the browser mode
242242- browser.enabled = false
240240+ throw new Error(`Vitest Browser Mode requires "browser.name" (deprecated) or "browser.instances" options, none were set.`)
243241 }
244244- else {
245245- const instances = browser.instances
246246- if (browser.name && browser.instances) {
247247- // --browser=chromium filters configs to a single one
248248- browser.instances = browser.instances.filter(instance => instance.browser === browser.name)
249249- }
250242251251- if (browser.instances && !browser.instances.length) {
252252- throw new Error([
253253- `"browser.instances" was set in the config, but the array is empty. Define at least one browser config.`,
254254- browser.name && instances?.length ? ` The "browser.name" was set to "${browser.name}" which filtered all configs (${instances.map(c => c.browser).join(', ')}). Did you mean to use another name?` : '',
255255- ].join(''))
256256- }
243243+ const instances = browser.instances
244244+ if (browser.name && browser.instances) {
245245+ // --browser=chromium filters configs to a single one
246246+ browser.instances = browser.instances.filter(instance => instance.browser === browser.name)
247247+ }
248248+249249+ if (browser.instances && !browser.instances.length) {
250250+ throw new Error([
251251+ `"browser.instances" was set in the config, but the array is empty. Define at least one browser config.`,
252252+ browser.name && instances?.length ? ` The "browser.name" was set to "${browser.name}" which filtered all configs (${instances.map(c => c.browser).join(', ')}). Did you mean to use another name?` : '',
253253+ ].join(''))
257254 }
258255 }
259256
+40-30
packages/vitest/src/node/plugins/workspace.ts
···44import { existsSync, readFileSync } from 'node:fs'
55import { deepMerge } from '@vitest/utils'
66import { basename, dirname, relative, resolve } from 'pathe'
77+import { mergeConfig } from 'vite'
78import { configDefaults } from '../../defaults'
89import { generateScopedClassName } from '../../integrations/css/css-modules'
910import { VitestFilteredOutProjectError } from '../errors'
···6364 }
6465 }
65666666- // keep project names to potentially filter it out
6767- const workspaceNames = [name]
6868- if (viteConfig.test?.browser?.enabled) {
6969- if (viteConfig.test.browser.name) {
7070- const browser = viteConfig.test.browser.name
7171- // vitest injects `instances` in this case later on
7272- workspaceNames.push(name ? `${name} (${browser})` : browser)
7373- }
7474-7575- viteConfig.test.browser.instances?.forEach((instance) => {
7676- // every instance is a potential project
7777- instance.name ??= name ? `${name} (${instance.browser})` : instance.browser
7878- workspaceNames.push(instance.name)
7979- })
8080- }
8181-8282- const filters = project.vitest.config.project
8383- // if there is `--project=...` filter, check if any of the potential projects match
8484- // if projects don't match, we ignore the test project altogether
8585- // if some of them match, they will later be filtered again by `resolveWorkspace`
8686- if (filters.length) {
8787- const hasProject = workspaceNames.some((name) => {
8888- return project.vitest.matchesProjectFilter(name)
8989- })
9090- if (!hasProject) {
9191- throw new VitestFilteredOutProjectError()
9292- }
9393- }
9494-9567 const resolveOptions = getDefaultResolveOptions()
9668 const config: ViteConfig = {
9769 root,
···138110 test: {
139111 name,
140112 },
141141- };
113113+ }
114114+115115+ // if this project defines a browser configuration, respect --browser flag
116116+ // otherwise if we always override the configuration, every project will run in browser mode
117117+ if (project.vitest._options.browser && viteConfig.test?.browser) {
118118+ viteConfig.test.browser = mergeConfig(
119119+ viteConfig.test.browser,
120120+ project.vitest._options.browser,
121121+ )
122122+ }
142123143124 (config.test as ResolvedConfig).defines = defines
125125+126126+ // keep project names to potentially filter it out
127127+ const workspaceNames = [name]
128128+ if (viteConfig.test?.browser?.enabled) {
129129+ if (viteConfig.test.browser.name && !viteConfig.test.browser.instances?.length) {
130130+ const browser = viteConfig.test.browser.name
131131+ // vitest injects `instances` in this case later on
132132+ workspaceNames.push(name ? `${name} (${browser})` : browser)
133133+ }
134134+135135+ viteConfig.test.browser.instances?.forEach((instance) => {
136136+ // every instance is a potential project
137137+ instance.name ??= name ? `${name} (${instance.browser})` : instance.browser
138138+ workspaceNames.push(instance.name)
139139+ })
140140+ }
141141+142142+ const filters = project.vitest.config.project
143143+ // if there is `--project=...` filter, check if any of the potential projects match
144144+ // if projects don't match, we ignore the test project altogether
145145+ // if some of them match, they will later be filtered again by `resolveWorkspace`
146146+ if (filters.length) {
147147+ const hasProject = workspaceNames.some((name) => {
148148+ return project.vitest.matchesProjectFilter(name)
149149+ })
150150+ if (!hasProject) {
151151+ throw new VitestFilteredOutProjectError()
152152+ }
153153+ }
144154145155 const classNameStrategy
146156 = (typeof testConfig.css !== 'boolean'