···4343- Components testing ([Vue](https://github.com/vitest-tests/browser-examples/tree/main/examples/vue), [React](https://github.com/vitest-tests/browser-examples/tree/main/examples/react), [Svelte](https://github.com/vitest-tests/browser-examples/tree/main/examples/svelte), [Lit](./examples/lit), [Marko](https://github.com/marko-js/examples/tree/master/examples/library-ts))
4444- Workers multi-threading via [Tinypool](https://github.com/tinylibs/tinypool) (a lightweight fork of [Piscina](https://github.com/piscinajs/piscina))
4545- Benchmarking support with [Tinybench](https://github.com/tinylibs/tinybench)
4646-- [Workspace](https://vitest.dev/guide/workspace) support
4646+- [Projects](https://vitest.dev/guide/projects) support
4747- [expect-type](https://github.com/mmkal/expect-type) for type-level testing
4848- ESM first, top level await
4949- Out-of-box TypeScript / JSX support
···3131})
3232```
33333434-If you need to run tests in different pools, use the [workspace](/guide/workspace) feature:
3434+If you need to run tests in different pools, use the [`projects`](/guide/projects) feature:
35353636```ts [vitest.config.ts]
3737export default defineConfig({
3838 test: {
3939- workspace: [
3939+ projects: [
4040 {
4141 extends: true,
4242 test: {
···4747 },
4848})
4949```
5050-5151-::: info
5252-The `workspace` field was introduced in Vitest 3. To define a workspace in [Vitest 2](https://v2.vitest.dev/), create a separate `vitest.workspace.ts` file.
5353-:::
54505551## API
5652···69657066The function is called only once (unless the server config was updated), and it's generally a good idea to initialize everything you need for tests inside that function and reuse it when `runTests` is called.
71677272-Vitest calls `runTest` when new tests are scheduled to run. It will not call it if `files` is empty. The first argument is an array of [TestSpecifications](/advanced/api/test-specification). Files are sorted using [`sequencer`](/config/#sequence-sequencer) before `runTests` is called. It's possible (but unlikely) to have the same file twice, but it will always have a different project - this is implemented via [`vitest.workspace.ts`](/guide/workspace) configuration.
6868+Vitest calls `runTest` when new tests are scheduled to run. It will not call it if `files` is empty. The first argument is an array of [TestSpecifications](/advanced/api/test-specification). Files are sorted using [`sequencer`](/config/#sequence-sequencer) before `runTests` is called. It's possible (but unlikely) to have the same file twice, but it will always have a different project - this is implemented via [`projects`](/guide/projects) configuration.
73697470Vitest will wait until `runTests` is executed before finishing a run (i.e., it will emit [`onFinished`](/advanced/reporters) only after `runTests` is resolved).
7571
+1-1
docs/advanced/runner.md
···164164 */
165165 filepath: string
166166 /**
167167- * The name of the workspace project the file belongs to.
167167+ * The name of the test project the file belongs to.
168168 */
169169 projectName: string | undefined
170170 /**
+1-1
docs/blog/vitest-3.md
···72727373## Inline Workspace
74747575-Rejoice! No more separate files to define your [workspace](/guide/workspace) - specify an array of projects using the `workspace` field in your `vitest.config` file:
7575+Rejoice! No more separate files to define your [workspace](/guide/projects) - specify an array of projects using the `workspace` field in your `vitest.config` file:
76767777```jsx
7878import { defineConfig } from 'vitest/config'
+19-8
docs/config/index.md
···106106107107Since Vitest uses Vite config, you can also use any configuration option from [Vite](https://vitejs.dev/config/). For example, `define` to define global variables, or `resolve.alias` to define aliases - these options should be defined on the top level, _not_ within a `test` property.
108108109109-Configuration options that are not supported inside a [workspace](/guide/workspace) project config have <NonProjectOption /> sign next to them. This means they can only be set in the root Vitest config.
109109+Configuration options that are not supported inside a [project](/guide/projects) config have <NonProjectOption /> sign next to them. This means they can only be set in the root Vitest config.
110110:::
111111112112### include
···588588- **Default:** `[]`
589589590590::: danger DEPRECATED
591591-This API was deprecated in Vitest 3. Use [workspace](/guide/workspace) to define different configurations instead.
591591+This API was deprecated in Vitest 3. Use [projects](/guide/projects) to define different configurations instead.
592592593593```ts
594594export default defineConfig({
···596596 environmentMatchGlobs: [ // [!code --]
597597 ['./*.jsdom.test.ts', 'jsdom'], // [!code --]
598598 ], // [!code --]
599599- workspace: [ // [!code ++]
599599+ projects: [ // [!code ++]
600600 { // [!code ++]
601601 extends: true, // [!code ++]
602602 test: { // [!code ++]
···635635- **Default:** `[]`
636636637637::: danger DEPRECATED
638638-This API was deprecated in Vitest 3. Use [workspace](/guide/workspace) to define different configurations instead:
638638+This API was deprecated in Vitest 3. Use [projects](/guide/projects) to define different configurations instead:
639639640640```ts
641641export default defineConfig({
···643643 poolMatchGlobs: [ // [!code --]
644644 ['./*.threads.test.ts', 'threads'], // [!code --]
645645 ], // [!code --]
646646- workspace: [ // [!code ++]
646646+ projects: [ // [!code ++]
647647 { // [!code ++]
648648 test: { // [!code ++]
649649 extends: true, // [!code ++]
···724724```
725725726726::: warning
727727-Returned files should be either absolute or relative to the root. Note that this is a global option, and it cannot be used inside of [project](/guide/workspace) configs.
727727+Returned files should be either absolute or relative to the root. Note that this is a global option, and it cannot be used inside of [project](/guide/projects) configs.
728728:::
729729730730### root
···2436243624372437### workspace<NonProjectOption /> {#workspace}
2438243824392439-- **Type:** `string | TestProjectConfiguration`
24392439+::: danger DEPRECATED
24402440+This options is deprecated and will be removed in the next major. Please, use [`projects`](#projects) instead.
24412441+:::
24422442+24432443+- **Type:** `string | TestProjectConfiguration[]`
24402444- **CLI:** `--workspace=./file.js`
24412445- **Default:** `vitest.{workspace,projects}.{js,ts,json}` close to the config file or root
2442244624432443-Path to a [workspace](/guide/workspace) config file relative to [root](#root).
24472447+Path to a [workspace](/guide/projects) config file relative to [root](#root).
2444244824452449Since Vitest 3, you can also define the workspace array in the root config. If the `workspace` is defined in the config manually, Vitest will ignore the `vitest.workspace` file in the root.
24502450+24512451+### projects<NonProjectOption /> {#projects}
24522452+24532453+- **Type:** `TestProjectConfiguration[]`
24542454+- **Default:** `[]`
24552455+24562456+An array of [projects](/guide/projects).
2446245724472458### isolate
24482459
+2-2
docs/guide/cli-generated.md
···291291- **CLI:** `--workspace <path>`
292292- **Config:** [workspace](/config/#workspace)
293293294294-Path to a workspace configuration file
294294+[deprecated] Path to a workspace configuration file
295295296296### isolate
297297···360360- **CLI:** `--browser.provider <name>`
361361- **Config:** [browser.provider](/guide/browser/config#browser-provider)
362362363363-Provider used to run browser tests. Some browsers are only available for specific providers. Can be "webdriverio", "playwright", "preview", or the path to a custom provider. Visit [`browser.provider`](https://vitest.dev/config/#browser-provider) for more information (default: `"preview"`)
363363+Provider used to run browser tests. Some browsers are only available for specific providers. Can be "webdriverio", "playwright", "preview", or the path to a custom provider. Visit [`browser.provider`](https://vitest.dev/guide/browser/config.html#browser-provider) for more information (default: `"preview"`)
364364365365### browser.providerOptions
366366
+1-1
docs/guide/environment.md
···2222::: warning
2323"Environments" exist only when running tests in Node.js.
24242525-`browser` is not considered an environment in Vitest. If you wish to run part of your tests using [Browser Mode](/guide/browser/), you can create a [workspace project](/guide/browser/#workspace-config).
2525+`browser` is not considered an environment in Vitest. If you wish to run part of your tests using [Browser Mode](/guide/browser/), you can create a [test project](/guide/browser/#projects-config).
2626:::
27272828## Environments for Specific Files
+5-5
docs/guide/index.md
···175175However, we recommend using the same file for both Vite and Vitest, instead of creating two separate files.
176176:::
177177178178-## Workspaces Support
178178+## Projects Support
179179180180-Run different project configurations inside the same project with [Vitest Workspaces](/guide/workspace). You can define a list of files and folders that define your workspace in `vitest.config` file.
180180+Run different project configurations inside the same project with [Test Projects](/guide/projects). You can define a list of files and folders that define your projects in `vitest.config` file.
181181182182```ts [vitest.config.ts]
183183import { defineConfig } from 'vitest/config'
184184185185export default defineConfig({
186186 test: {
187187- workspace: [
188188- // you can use a list of glob patterns to define your workspaces
187187+ projects: [
188188+ // you can use a list of glob patterns to define your projects
189189 // Vitest expects a list of config files
190190 // or directories where there is a config file
191191 'packages/*',
···261261| `sveltekit` | [GitHub](https://github.com/vitest-dev/vitest/tree/main/examples/sveltekit) | [Play Online](https://stackblitz.com/fork/github/vitest-dev/vitest/tree/main/examples/sveltekit?initialPath=__vitest__/) |
262262| `profiling` | [GitHub](https://github.com/vitest-dev/vitest/tree/main/examples/profiling) | Not Available |
263263| `typecheck` | [GitHub](https://github.com/vitest-dev/vitest/tree/main/examples/typecheck) | [Play Online](https://stackblitz.com/fork/github/vitest-dev/vitest/tree/main/examples/typecheck?initialPath=__vitest__/) |
264264-| `workspace` | [GitHub](https://github.com/vitest-dev/vitest/tree/main/examples/workspace) | [Play Online](https://stackblitz.com/fork/github/vitest-dev/vitest/tree/main/examples/workspace?initialPath=__vitest__/) |
264264+| `projects` | [GitHub](https://github.com/vitest-dev/vitest/tree/main/examples/projects) | [Play Online](https://stackblitz.com/fork/github/vitest-dev/vitest/tree/main/examples/projects?initialPath=__vitest__/) |
265265266266## Projects using Vitest
267267
+242
docs/guide/projects.md
···11+---
22+title: Test Projects | Guide
33+---
44+55+# Test Projects
66+77+::: tip Sample Project
88+99+[GitHub](https://github.com/vitest-dev/vitest/tree/main/examples/projects) - [Play Online](https://stackblitz.com/fork/github/vitest-dev/vitest/tree/main/examples/projects?initialPath=__vitest__/)
1010+1111+:::
1212+1313+::: warning
1414+This feature is also known as a `workspace`. The `workspace` is deprecated since 3.2 and replaced with the `projects` configuration. They are functionally the same.
1515+:::
1616+1717+Vitest provides a way to define multiple project configurations within a single Vitest process. This feature is particularly useful for monorepo setups but can also be used to run tests with different configurations, such as `resolve.alias`, `plugins`, or `test.browser` and more.
1818+1919+## Defining Projects
2020+2121+You can define projects in your root [config](/config/):
2222+2323+```ts [vitest.config.ts]
2424+import { defineConfig } from 'vitest/config'
2525+2626+export default defineConfig({
2727+ test: {
2828+ projects: ['packages/*'],
2929+ },
3030+})
3131+```
3232+3333+Project configurations are inlined configs, files, or glob patterns referencing your projects. For example, if you have a folder named `packages` that contains your projects, you can define an array in your root Vitest config:
3434+3535+```ts [vitest.config.ts]
3636+import { defineConfig } from 'vitest/config'
3737+3838+export default defineConfig({
3939+ test: {
4040+ projects: ['packages/*'],
4141+ },
4242+})
4343+```
4444+4545+Vitest will treat every folder in `packages` as a separate project even if it doesn't have a config file inside. If this glob pattern matches _any file_, it will be considered a Vitest config even if it doesn't have a `vitest` in its name or has an obscure file extension.
4646+4747+::: warning
4848+Vitest does not treat the root `vitest.config` file as a project unless it is explicitly specified in the configuration. Consequently, the root configuration will only influence global options such as `reporters` and `coverage`. Note that Vitest will always run certain plugin hooks, like `apply`, `config`, `configResolved` or `configureServer`, specified in the root config file. Vitest also uses the same plugins to execute global setups and custom coverage provider.
4949+:::
5050+5151+You can also reference projects with their config files:
5252+5353+```ts [vitest.config.ts]
5454+import { defineConfig } from 'vitest/config'
5555+5656+export default defineConfig({
5757+ test: {
5858+ projects: ['packages/*/vitest.config.{e2e,unit}.ts'],
5959+ },
6060+})
6161+```
6262+6363+This pattern will only include projects with a `vitest.config` file that contains `e2e` or `unit` before the extension.
6464+6565+You can also define projects using inline configuration. The configuration supports both syntaxes simultaneously.
6666+6767+```ts [vitest.config.ts]
6868+import { defineConfig } from 'vitest/config'
6969+7070+export default defineConfig({
7171+ test: {
7272+ projects: [
7373+ // matches every folder and file inside the `packages` folder
7474+ 'packages/*',
7575+ {
7676+ // add "extends: true" to inherit the options from the root config
7777+ extends: true,
7878+ test: {
7979+ include: ['tests/**/*.{browser}.test.{ts,js}'],
8080+ // it is recommended to define a name when using inline configs
8181+ name: 'happy-dom',
8282+ environment: 'happy-dom',
8383+ }
8484+ },
8585+ {
8686+ test: {
8787+ include: ['tests/**/*.{node}.test.{ts,js}'],
8888+ // color of the name label can be changed
8989+ name: { label: 'node', color: 'green' },
9090+ environment: 'node',
9191+ }
9292+ }
9393+ ]
9494+ }
9595+})
9696+```
9797+9898+::: warning
9999+All projects must have unique names; otherwise, Vitest will throw an error. If a name is not provided in the inline configuration, Vitest will assign a number. For project configurations defined with glob syntax, Vitest will default to using the "name" property in the nearest `package.json` file or, if none exists, the folder name.
100100+:::
101101+102102+Projects do not support all configuration properties. For better type safety, use the `defineProject` method instead of `defineConfig` within project configuration files:
103103+104104+```ts twoslash [packages/a/vitest.config.ts]
105105+// @errors: 2769
106106+import { defineProject } from 'vitest/config'
107107+108108+export default defineProject({
109109+ test: {
110110+ environment: 'jsdom',
111111+ // "reporters" is not supported in a project config,
112112+ // so it will show an error
113113+ reporters: ['json']
114114+ }
115115+})
116116+```
117117+118118+## Running tests
119119+120120+To run tests, define a script in your root `package.json`:
121121+122122+```json [package.json]
123123+{
124124+ "scripts": {
125125+ "test": "vitest"
126126+ }
127127+}
128128+```
129129+130130+Now tests can be run using your package manager:
131131+132132+::: code-group
133133+```bash [npm]
134134+npm run test
135135+```
136136+```bash [yarn]
137137+yarn test
138138+```
139139+```bash [pnpm]
140140+pnpm run test
141141+```
142142+```bash [bun]
143143+bun run test
144144+```
145145+:::
146146+147147+If you need to run tests only inside a single project, use the `--project` CLI option:
148148+149149+::: code-group
150150+```bash [npm]
151151+npm run test --project e2e
152152+```
153153+```bash [yarn]
154154+yarn test --project e2e
155155+```
156156+```bash [pnpm]
157157+pnpm run test --project e2e
158158+```
159159+```bash [bun]
160160+bun run test --project e2e
161161+```
162162+:::
163163+164164+::: tip
165165+CLI option `--project` can be used multiple times to filter out several projects:
166166+167167+::: code-group
168168+```bash [npm]
169169+npm run test --project e2e --project unit
170170+```
171171+```bash [yarn]
172172+yarn test --project e2e --project unit
173173+```
174174+```bash [pnpm]
175175+pnpm run test --project e2e --project unit
176176+```
177177+```bash [bun]
178178+bun run test --project e2e --project unit
179179+```
180180+:::
181181+182182+## Configuration
183183+184184+None of the configuration options are inherited from the root-level config file. You can create a shared config file and merge it with the project config yourself:
185185+186186+```ts [packages/a/vitest.config.ts]
187187+import { defineProject, mergeConfig } from 'vitest/config'
188188+import configShared from '../vitest.shared.js'
189189+190190+export default mergeConfig(
191191+ configShared,
192192+ defineProject({
193193+ test: {
194194+ environment: 'jsdom',
195195+ }
196196+ })
197197+)
198198+```
199199+200200+Additionally, you can use the `extends` option to inherit from your root-level configuration. All options will be merged.
201201+202202+```ts [vitest.config.ts]
203203+import { defineConfig } from 'vitest/config'
204204+import react from '@vitejs/plugin-react'
205205+206206+export default defineConfig({
207207+ plugins: [react()],
208208+ test: {
209209+ pool: 'threads',
210210+ projects: [
211211+ {
212212+ // will inherit options from this config like plugins and pool
213213+ extends: true,
214214+ test: {
215215+ name: 'unit',
216216+ include: ['**/*.unit.test.ts'],
217217+ },
218218+ },
219219+ {
220220+ // won't inherit any options from this config
221221+ // this is the default behaviour
222222+ extends: false,
223223+ test: {
224224+ name: 'integration',
225225+ include: ['**/*.integration.test.ts'],
226226+ },
227227+ },
228228+ ],
229229+ },
230230+})
231231+```
232232+233233+::: danger Unsupported Options
234234+Some of the configuration options are not allowed in a project config. Most notably:
235235+236236+- `coverage`: coverage is done for the whole process
237237+- `reporters`: only root-level reporters can be supported
238238+- `resolveSnapshotPath`: only root-level resolver is respected
239239+- all other options that don't affect test runners
240240+241241+All configuration options that are not supported inside a project configuration are marked with a <NonProjectOption /> sign in the ["Config"](/config/) guide. They have to be defined once in the root config file.
242242+:::
+27-23
docs/guide/test-context.md
···232232233233#### Default fixture
234234235235-Since Vitest 3, you can provide different values in different [projects](/guide/workspace). To enable this feature, pass down `{ injected: true }` to the options. If the key is not specified in the [project configuration](/config/#provide), then the default value will be used.
235235+Since Vitest 3, you can provide different values in different [projects](/guide/projects). To enable this feature, pass down `{ injected: true }` to the options. If the key is not specified in the [project configuration](/config/#provide), then the default value will be used.
236236237237:::code-group
238238```ts [fixtures.test.ts]
···253253 // url is "/empty" in "project-empty"
254254})
255255```
256256-```ts [vitest.workspace.ts]
257257-import { defineWorkspace } from 'vitest/config'
256256+```ts [vitest.config.ts]
257257+import { defineConfig } from 'vitest/config'
258258259259-export default defineWorkspace([
260260- {
261261- test: {
262262- name: 'project-new',
263263- },
264264- },
265265- {
266266- test: {
267267- name: 'project-full',
268268- provide: {
269269- url: '/full',
259259+export default defineConfig({
260260+ test: {
261261+ projects: [
262262+ {
263263+ test: {
264264+ name: 'project-new',
265265+ },
270266 },
271271- },
272272- },
273273- {
274274- test: {
275275- name: 'project-empty',
276276- provide: {
277277- url: '/empty',
267267+ {
268268+ test: {
269269+ name: 'project-full',
270270+ provide: {
271271+ url: '/full',
272272+ },
273273+ },
278274 },
279279- },
275275+ {
276276+ test: {
277277+ name: 'project-empty',
278278+ provide: {
279279+ url: '/empty',
280280+ },
281281+ },
282282+ },
283283+ ],
280284 },
281281-])
285285+})
282286```
283287:::
284288
-316
docs/guide/workspace.md
···11----
22-title: Workspace | Guide
33----
44-55-# Workspace
66-77-::: tip Sample Project
88-99-[GitHub](https://github.com/vitest-dev/vitest/tree/main/examples/workspace) - [Play Online](https://stackblitz.com/fork/github/vitest-dev/vitest/tree/main/examples/workspace?initialPath=__vitest__/)
1010-1111-:::
1212-1313-Vitest provides a way to define multiple project configurations within a single Vitest process. This feature is particularly useful for monorepo setups but can also be used to run tests with different configurations, such as `resolve.alias`, `plugins`, or `test.browser` and more.
1414-1515-## Defining a Workspace
1616-1717-Since Vitest 3, you can define a workspace in your root [config](/config/). In this case, Vitest will ignore the `vitest.workspace` file in the root, if one exists.
1818-1919-```ts [vitest.config.ts]
2020-import { defineConfig } from 'vitest/config'
2121-2222-export default defineConfig({
2323- test: {
2424- workspace: ['packages/*'],
2525- },
2626-})
2727-```
2828-2929-If you are using an older version, a workspace must include `vitest.workspace` or `vitest.projects` file in its root directory (located in the same folder as your root configuration file or working directory if it doesn't exist). Note that `projects` is just an alias and does not change the behavior or semantics of this feature. Vitest supports `ts`, `js`, and `json` extensions for this file.
3030-3131-::: tip NAMING
3232-Please note that this feature is named `workspace`, not `workspaces` (without an "s" at the end).
3333-:::
3434-3535-A workspace is a list of inlined configs, files, or glob patterns referencing your projects. For example, if you have a folder named `packages` that contains your projects, you can either create a workspace file or define an array in the root config:
3636-3737-:::code-group
3838-```ts [vitest.config.ts <Version>3.0.0</Version>]
3939-import { defineConfig } from 'vitest/config'
4040-4141-export default defineConfig({
4242- test: {
4343- workspace: ['packages/*'],
4444- },
4545-})
4646-```
4747-```ts [vitest.workspace.ts]
4848-export default [
4949- 'packages/*'
5050-]
5151-```
5252-:::
5353-5454-Vitest will treat every folder in `packages` as a separate project even if it doesn't have a config file inside. If this glob pattern matches any file it will be considered a Vitest config even if it doesn't have a `vitest` in its name.
5555-5656-::: warning
5757-Vitest does not treat the root `vitest.config` file as a workspace project unless it is explicitly specified in the workspace configuration. Consequently, the root configuration will only influence global options such as `reporters` and `coverage`. Note that Vitest will always run certain plugin hooks, like `apply`, `config`, `configResolved` or `configureServer`, specified in the root config file. Vitest also uses the same plugins to execute global setups, workspace files and custom coverage provider.
5858-:::
5959-6060-You can also reference projects with their config files:
6161-6262-:::code-group
6363-```ts [vitest.config.ts <Version>3.0.0</Version>]
6464-import { defineConfig } from 'vitest/config'
6565-6666-export default defineConfig({
6767- test: {
6868- workspace: ['packages/*/vitest.config.{e2e,unit}.ts'],
6969- },
7070-})
7171-```
7272-```ts [vitest.workspace.ts]
7373-export default [
7474- 'packages/*/vitest.config.{e2e,unit}.ts'
7575-]
7676-```
7777-:::
7878-7979-This pattern will only include projects with a `vitest.config` file that contains `e2e` or `unit` before the extension.
8080-8181-You can also define projects using inline configuration. The workspace configuration supports both syntaxes simultaneously.
8282-8383-:::code-group
8484-```ts [vitest.config.ts <Version>3.0.0</Version>]
8585-import { defineConfig } from 'vitest/config'
8686-8787-export default defineConfig({
8888- test: {
8989- workspace: [
9090- // matches every folder and file inside the `packages` folder
9191- 'packages/*',
9292- {
9393- // add "extends: true" to inherit the options from the root config
9494- extends: true,
9595- test: {
9696- include: ['tests/**/*.{browser}.test.{ts,js}'],
9797- // it is recommended to define a name when using inline configs
9898- name: 'happy-dom',
9999- environment: 'happy-dom',
100100- }
101101- },
102102- {
103103- test: {
104104- include: ['tests/**/*.{node}.test.{ts,js}'],
105105- // color of the name label can be changed
106106- name: { label: 'node', color: 'green' },
107107- environment: 'node',
108108- }
109109- }
110110- ]
111111- }
112112-})
113113-```
114114-```ts [vitest.workspace.ts]
115115-import { defineWorkspace } from 'vitest/config'
116116-117117-// defineWorkspace provides a nice type hinting DX
118118-export default defineWorkspace([
119119- // matches every folder and file inside the `packages` folder
120120- 'packages/*',
121121- {
122122- // add "extends" to merge two configs together
123123- extends: './vite.config.js',
124124- test: {
125125- include: ['tests/**/*.{browser}.test.{ts,js}'],
126126- // it is recommended to define a name when using inline configs
127127- name: 'happy-dom',
128128- environment: 'happy-dom',
129129- }
130130- },
131131- {
132132- test: {
133133- include: ['tests/**/*.{node}.test.{ts,js}'],
134134- name: 'node',
135135- environment: 'node',
136136- }
137137- }
138138-])
139139-```
140140-:::
141141-142142-::: warning
143143-All projects must have unique names; otherwise, Vitest will throw an error. If a name is not provided in the inline configuration, Vitest will assign a number. For project configurations defined with glob syntax, Vitest will default to using the "name" property in the nearest `package.json` file or, if none exists, the folder name.
144144-:::
145145-146146-If you do not use inline configurations, you can create a small JSON file in your root directory or just specify it in the root config:
147147-148148-```json [vitest.workspace.json]
149149-[
150150- "packages/*"
151151-]
152152-```
153153-154154-Workspace projects do not support all configuration properties. For better type safety, use the `defineProject` method instead of `defineConfig` within project configuration files:
155155-156156-```ts twoslash [packages/a/vitest.config.ts]
157157-// @errors: 2769
158158-import { defineProject } from 'vitest/config'
159159-160160-export default defineProject({
161161- test: {
162162- environment: 'jsdom',
163163- // "reporters" is not supported in a project config,
164164- // so it will show an error
165165- reporters: ['json']
166166- }
167167-})
168168-```
169169-170170-## Running tests
171171-172172-To run tests inside the workspace, define a script in your root `package.json`:
173173-174174-```json [package.json]
175175-{
176176- "scripts": {
177177- "test": "vitest"
178178- }
179179-}
180180-```
181181-182182-Now tests can be run using your package manager:
183183-184184-::: code-group
185185-```bash [npm]
186186-npm run test
187187-```
188188-```bash [yarn]
189189-yarn test
190190-```
191191-```bash [pnpm]
192192-pnpm run test
193193-```
194194-```bash [bun]
195195-bun run test
196196-```
197197-:::
198198-199199-If you need to run tests only inside a single project, use the `--project` CLI option:
200200-201201-::: code-group
202202-```bash [npm]
203203-npm run test --project e2e
204204-```
205205-```bash [yarn]
206206-yarn test --project e2e
207207-```
208208-```bash [pnpm]
209209-pnpm run test --project e2e
210210-```
211211-```bash [bun]
212212-bun run test --project e2e
213213-```
214214-:::
215215-216216-::: tip
217217-CLI option `--project` can be used multiple times to filter out several projects:
218218-219219-::: code-group
220220-```bash [npm]
221221-npm run test --project e2e --project unit
222222-```
223223-```bash [yarn]
224224-yarn test --project e2e --project unit
225225-```
226226-```bash [pnpm]
227227-pnpm run test --project e2e --project unit
228228-```
229229-```bash [bun]
230230-bun run test --project e2e --project unit
231231-```
232232-:::
233233-234234-## Configuration
235235-236236-None of the configuration options are inherited from the root-level config file, even if the workspace is defined inside that config and not in a separate `vitest.workspace` file. You can create a shared config file and merge it with the project config yourself:
237237-238238-```ts [packages/a/vitest.config.ts]
239239-import { defineProject, mergeConfig } from 'vitest/config'
240240-import configShared from '../vitest.shared.js'
241241-242242-export default mergeConfig(
243243- configShared,
244244- defineProject({
245245- test: {
246246- environment: 'jsdom',
247247- }
248248- })
249249-)
250250-```
251251-252252-Additionally, at the `defineWorkspace` level, you can use the `extends` option to inherit from your root-level configuration. All options will be merged.
253253-254254-::: code-group
255255-```ts [vitest.config.ts <Version>3.0.0</Version>]
256256-import { defineConfig } from 'vitest/config'
257257-import react from '@vitejs/plugin-react'
258258-259259-export default defineConfig({
260260- plugins: [react()],
261261- test: {
262262- pool: 'threads',
263263- workspace: [
264264- {
265265- // will inherit options from this config like plugins and pool
266266- extends: true,
267267- test: {
268268- name: 'unit',
269269- include: ['**/*.unit.test.ts'],
270270- },
271271- },
272272- {
273273- // won't inherit any options from this config
274274- // this is the default behaviour
275275- extends: false,
276276- test: {
277277- name: 'integration',
278278- include: ['**/*.integration.test.ts'],
279279- },
280280- },
281281- ],
282282- },
283283-})
284284-```
285285-```ts [vitest.workspace.ts]
286286-import { defineWorkspace } from 'vitest/config'
287287-288288-export default defineWorkspace([
289289- {
290290- extends: './vitest.config.ts',
291291- test: {
292292- name: 'unit',
293293- include: ['**/*.unit.test.ts'],
294294- },
295295- },
296296- {
297297- extends: './vitest.config.ts',
298298- test: {
299299- name: 'integration',
300300- include: ['**/*.integration.test.ts'],
301301- },
302302- },
303303-])
304304-```
305305-:::
306306-307307-::: danger Unsupported Options
308308-Some of the configuration options are not allowed in a project config. Most notably:
309309-310310-- `coverage`: coverage is done for the whole workspace
311311-- `reporters`: only root-level reporters can be supported
312312-- `resolveSnapshotPath`: only root-level resolver is respected
313313-- all other options that don't affect test runners
314314-315315-All configuration options that are not supported inside a project configuration are marked with a <NonProjectOption /> sign in the ["Config"](/config/) guide. They have to be defined once in the root config file.
316316-:::
···1313 <ListItem>Workers multi-threading via <a target="_blank" href="https://github.com/tinylibs/tinypool" rel="noopener noreferrer">Tinypool</a></ListItem>
1414 <ListItem>Benchmarking support with <a target="_blank" href="https://github.com/tinylibs/tinybench" rel="noopener noreferrer">Tinybench</a></ListItem>
1515 <ListItem>Filtering, timeouts, concurrent for suite and tests</ListItem>
1616- <ListItem><a href="/guide/workspace">Workspace</a> support</ListItem>
1616+ <ListItem><a href="/guide/projects">Projects</a> support</ListItem>
1717 <ListItem>
1818 <a href="/guide/snapshot">
1919 Jest-compatible Snapshot
+1-1
docs/advanced/api/index.md
···119119:::
120120121121::: warning
122122-The `resolveConfig` doesn't resolve the `workspace`. To resolve workspace configs, Vitest needs an established Vite server.
122122+The `resolveConfig` doesn't resolve `projects`. To resolve projects configs, Vitest needs an established Vite server.
123123124124Also note that `viteConfig.test` will not be fully resolved. If you need Vitest config, use `vitestConfig` instead.
125125:::
+2-2
docs/advanced/api/plugin.md
···5353```
5454:::
55555656-Unlike [`reporter.onInit`](/advanced/api/reporters#oninit), this hooks runs early in Vitest lifecycle allowing you to make changes to configuration like `coverage` and `reporters`. A more notable change is that you can manipulate the global config from a [workspace project](/guide/workspace) if your plugin is defined in the project and not in the global config.
5656+Unlike [`reporter.onInit`](/advanced/api/reporters#oninit), this hooks runs early in Vitest lifecycle allowing you to make changes to configuration like `coverage` and `reporters`. A more notable change is that you can manipulate the global config from a [test project](/guide/projects) if your plugin is defined in the project and not in the global config.
57575858## Context
5959···107107```
108108109109::: warning Projects are Filtered
110110-Vitest filters projects during the config resolution, so if the user defined a filter, injected project might not be resolved unless it [matches the filter](./vitest#matchesprojectfilter). You can update the filter via the `vitest.config.project` option to always include your workspace project:
110110+Vitest filters projects during the config resolution, so if the user defined a filter, injected project might not be resolved unless it [matches the filter](./vitest#matchesprojectfilter). You can update the filter via the `vitest.config.project` option to always include your test project:
111111112112```ts
113113vitest.config.project.push('my-project-name')
+25-21
docs/advanced/api/test-project.md
···4455# TestProject <Version>3.0.0</Version> {#testproject}
6677-- **Alias**: `WorkspaceProject` before 3.0.0
88-97::: warning
1010-This guide describes the advanced Node.js API. If you just want to create a workspace, follow the ["Workspace"](/guide/workspace) guide.
88+This guide describes the advanced Node.js API. If you just want to define projects, follow the ["Test Projects"](/guide/projects) guide.
119:::
12101311## name
···2624 'custom'
2725]
2826```
2929-```ts [vitest.workspace.js]
3030-export default [
3131- './packages/server', // has package.json with "@pkg/server"
3232- './utils', // doesn't have a package.json file
3333- {
3434- // doesn't customize the name
3535- test: {
3636- pool: 'threads',
3737- },
2727+```ts [vitest.config.js]
2828+import { defineConfig } from 'vitest/config'
2929+3030+export default defineConfig({
3131+ test: {
3232+ projects: [
3333+ './packages/server', // has package.json with "@pkg/server"
3434+ './utils', // doesn't have a package.json file
3535+ {
3636+ // doesn't customize the name
3737+ test: {
3838+ pool: 'threads',
3939+ },
4040+ },
4141+ {
4242+ // customized the name
4343+ test: {
4444+ name: 'custom',
4545+ },
4646+ },
4747+ ],
3848 },
3939- {
4040- // customized the name
4141- test: {
4242- name: 'custom',
4343- },
4444- },
4545-]
4949+})
4650```
4751:::
48524953::: info
5050-If the [root project](/advanced/api/vitest#getroottestproject) is not part of a user workspace, its `name` will not be resolved.
5454+If the [root project](/advanced/api/vitest#getroottestproject) is not part of user projects, its `name` will not be resolved.
5155:::
52565357## vitest
···279283:::
280284281285::: info
282282-Internally, Vitest uses this method to import global setups, custom coverage providers, workspace file, and custom reporters, meaning all of them share the same module graph as long as they belong to the same Vite server.
286286+Internally, Vitest uses this method to import global setups, custom coverage providers and custom reporters, meaning all of them share the same module graph as long as they belong to the same Vite server.
283287:::
284288285289## onTestsRerun
+5-5
docs/advanced/api/vitest.md
···64646565## config
66666767-The root (or global) config. If workspace feature is enabled, projects will reference this as `globalConfig`.
6767+The root (or global) config. If projects are defined, they will reference this as `globalConfig`.
68686969::: warning
7070This is Vitest config, it doesn't extend _Vite_ config. It only has resolved values from the `test` property.
···101101102102## projects
103103104104-An array of [test projects](/advanced/api/test-project) that belong to the user's workspace. If the user did not specify a custom workspace, the workspace will only have a [root project](#getrootproject).
104104+An array of [test projects](/advanced/api/test-project) that belong to user's projects. If the user did not specify a them, this array will only contain a [root project](#getrootproject).
105105106106-Vitest will ensure that there is always at least one project in the workspace. If the user specifies a non-existent `--project` name, Vitest will throw an error.
106106+Vitest will ensure that there is always at least one project in this array. If the user specifies a non-existent `--project` name, Vitest will throw an error before this array is defined.
107107108108## getRootProject
109109···111111function getRootProject(): TestProject
112112```
113113114114-This returns the root test project. The root project generally doesn't run any tests and is not included in `vitest.projects` unless the user explicitly includes the root config in their workspace, or the workspace is not defined at all.
114114+This returns the root test project. The root project generally doesn't run any tests and is not included in `vitest.projects` unless the user explicitly includes the root config in their configuration, or projects are not defined at all.
115115116116The primary goal of the root project is to setup the global config. In fact, `rootProject.config` references `rootProject.globalConfig` and `vitest.config` directly:
117117···433433:::
434434435435::: info
436436-Internally, Vitest uses this method to import global setups, custom coverage providers, workspace file, and custom reporters, meaning all of them share the same module graph as long as they belong to the same Vite server.
436436+Internally, Vitest uses this method to import global setups, custom coverage providers, and custom reporters, meaning all of them share the same module graph as long as they belong to the same Vite server.
437437:::
438438439439## close
+1-1
docs/guide/browser/commands.md
···11111212### Files Handling
13131414-You can use the `readFile`, `writeFile`, and `removeFile` APIs to handle files in your browser tests. Since Vitest 3.2, all paths are resolved relative to the [project](/guide/workspace) root (which is `process.cwd()`, unless overriden manually). Previously, paths were resolved relative to the test file.
1414+You can use the `readFile`, `writeFile`, and `removeFile` APIs to handle files in your browser tests. Since Vitest 3.2, all paths are resolved relative to the [project](/guide/projects) root (which is `process.cwd()`, unless overriden manually). Previously, paths were resolved relative to the test file.
15151616By default, Vitest uses `utf-8` encoding but you can override it with options.
1717
+38-34
docs/guide/browser/index.md
···88This page provides information about the experimental browser mode feature in the Vitest API, which allows you to run your tests in the browser natively, providing access to browser globals like window and document. This feature is currently under development, and APIs may change in the future.
991010::: tip
1111-If you are looking for documentation for `expect`, `vi` or any general API like workspaces or type testing, refer to the ["Getting Started" guide](/guide/).
1111+If you are looking for documentation for `expect`, `vi` or any general API like test projects or type testing, refer to the ["Getting Started" guide](/guide/).
1212:::
13131414<img alt="Vitest UI" img-light src="/ui-browser-1-light.png">
···209209```
210210:::
211211212212-If you need to run some tests using Node-based runner, you can define a [workspace](/guide/workspace) file with separate configurations for different testing strategies:
212212+If you need to run some tests using Node-based runner, you can define a [`projects`](/guide/projects) option with separate configurations for different testing strategies:
213213214214-{#workspace-config}
214214+{#projects-config}
215215216216-```ts [vitest.workspace.ts]
217217-import { defineWorkspace } from 'vitest/config'
216216+```ts [vitest.config.ts]
217217+import { defineConfig } from 'vitest/config'
218218219219-export default defineWorkspace([
220220- {
221221- test: {
222222- // an example of file based convention,
223223- // you don't have to follow it
224224- include: [
225225- 'tests/unit/**/*.{test,spec}.ts',
226226- 'tests/**/*.unit.{test,spec}.ts',
227227- ],
228228- name: 'unit',
229229- environment: 'node',
230230- },
231231- },
232232- {
233233- test: {
234234- // an example of file based convention,
235235- // you don't have to follow it
236236- include: [
237237- 'tests/browser/**/*.{test,spec}.ts',
238238- 'tests/**/*.browser.{test,spec}.ts',
239239- ],
240240- name: 'browser',
241241- browser: {
242242- enabled: true,
243243- instances: [
244244- { browser: 'chromium' },
245245- ],
219219+export default defineConfig({
220220+ test: {
221221+ projects: [
222222+ {
223223+ test: {
224224+ // an example of file based convention,
225225+ // you don't have to follow it
226226+ include: [
227227+ 'tests/unit/**/*.{test,spec}.ts',
228228+ 'tests/**/*.unit.{test,spec}.ts',
229229+ ],
230230+ name: 'unit',
231231+ environment: 'node',
232232+ },
246233 },
247247- },
234234+ {
235235+ test: {
236236+ // an example of file based convention,
237237+ // you don't have to follow it
238238+ include: [
239239+ 'tests/browser/**/*.{test,spec}.ts',
240240+ 'tests/**/*.browser.{test,spec}.ts',
241241+ ],
242242+ name: 'browser',
243243+ browser: {
244244+ enabled: true,
245245+ instances: [
246246+ { browser: 'chromium' },
247247+ ],
248248+ },
249249+ },
250250+ },
251251+ ],
248252 },
249249-])
253253+})
250254```
251255252256## Browser Option Types
+1-1
docs/guide/browser/multiple-setups.md
···2233Since Vitest 3, you can specify several different browser setups using the new [`browser.instances`](/guide/browser/config#browser-instances) option.
4455-The main advantage of using the `browser.instances` over the [workspace](/guide/workspace) is improved caching. Every project will use the same Vite server meaning the file transform and [dependency pre-bundling](https://vite.dev/guide/dep-pre-bundling.html) has to happen only once.
55+The main advantage of using the `browser.instances` over the [test projects](/guide/projects) is improved caching. Every project will use the same Vite server meaning the file transform and [dependency pre-bundling](https://vite.dev/guide/dep-pre-bundling.html) has to happen only once.
6677## Several Browsers
88
+4-4
test/browser/test/commands.test.ts
···1313 catch (err) {
1414 expect(err.message).toMatch(`ENOENT: no such file or directory, open`)
1515 if (server.platform === 'win32') {
1616- expect(err.message).toMatch('test\\browser\\test\\test.txt')
1616+ expect(err.message).toMatch('test\\browser\\test.txt')
1717 }
1818 else {
1919- expect(err.message).toMatch('test/browser/test/test.txt')
1919+ expect(err.message).toMatch('test/browser/test.txt')
2020 }
2121 }
2222···3434 catch (err) {
3535 expect(err.message).toMatch(`ENOENT: no such file or directory, open`)
3636 if (server.platform === 'win32') {
3737- expect(err.message).toMatch('test\\browser\\test\\test.txt')
3737+ expect(err.message).toMatch('test\\browser\\test.txt')
3838 }
3939 else {
4040- expect(err.message).toMatch('test/browser/test/test.txt')
4040+ expect(err.message).toMatch('test/browser/test.txt')
4141 }
4242 }
4343})
···30303131test('can change the project and the global configurations', async () => {
3232 const v = await vitest({}, {
3333- workspace: [
3333+ projects: [
3434 {
3535 plugins: [
3636 {
···5959 const { projects } = await vitest({
6060 project: 'project-2',
6161 }, {
6262- workspace: [
6262+ projects: [
6363 {
6464 test: {
6565 name: 'project-1',
···113113 let newWorkspace: TestProject[] = []
114114 const { projects } = await vitest({
115115 project: 'project-1',
116116- workspace: [
116116+ projects: [
117117 {
118118 test: {
119119 name: 'project-1',
···143143 let newWorkspace: TestProject[] = []
144144 const { projects } = await vitest({
145145 project: 'project-1',
146146- workspace: [
146146+ projects: [
147147 {
148148 test: {
149149 name: 'project-1',
···174174175175test('adding a plugin with existing name throws and error', async () => {
176176 await expect(() => vitest({
177177- workspace: [
177177+ projects: [
178178 {
179179 test: {
180180 name: 'project-1',
···194194 },
195195 ],
196196 }),
197197- ).rejects.toThrowError('Project name "project-1" is not unique. All projects in a workspace should have unique names. Make sure your configuration is correct.')
197197+ ).rejects.toThrowError('Project name "project-1" is not unique. All projects should have unique names. Make sure your configuration is correct.')
198198199199 await expect(() => vitest({
200200- workspace: [
200200+ projects: [
201201 {
202202 plugins: [
203203 {
···219219 },
220220 ],
221221 }),
222222- ).rejects.toThrowError('Project name "project-1" is not unique. All projects in a workspace should have unique names. Make sure your configuration is correct.')
222222+ ).rejects.toThrowError('Project name "project-1" is not unique. All projects should have unique names. Make sure your configuration is correct.')
223223224224 await expect(() => vitest({
225225- workspace: [
225225+ projects: [
226226 {
227227 plugins: [
228228 {
···246246 },
247247 ],
248248 }),
249249- ).rejects.toThrowError('Project name "project-1" is not unique. All projects in a workspace should have unique names. Make sure your configuration is correct.')
249249+ ).rejects.toThrowError('Project name "project-1" is not unique. All projects should have unique names. Make sure your configuration is correct.')
250250})
+4-4
test/config/test/failures.test.ts
···476476 },
477477 },
478478 })
479479- expect(stderr).toMatch('Cannot define a nested project for a firefox browser. The project name "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.')
479479+ expect(stderr).toMatch('Cannot define a nested project for a firefox browser. The project name "firefox" was already defined. If you have multiple instances for the same browser, make sure to define a custom "name". All projects should have unique names. Make sure your configuration is correct.')
480480})
481481482482test('browser.instances throws an error if no custom name is provided, but the config name is inherited', async () => {
···491491 ],
492492 },
493493 })
494494- 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.')
494494+ 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 should have unique names. Make sure your configuration is correct.')
495495})
496496497497test('throws an error if name conflicts with a workspace name', async () => {
498498 const { stderr } = await runVitest({
499499- workspace: [
499499+ projects: [
500500 { test: { name: '1 (firefox)' } },
501501 {
502502 test: {
···511511 },
512512 ],
513513 })
514514- 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.')
514514+ 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 should have unique names. Make sure your configuration is correct.')
515515})
516516517517test('throws an error if several browsers are headed in nonTTY mode', async () => {
+150
test/config/test/projects.test.ts
···11+import { resolve } from 'pathe'
22+import { expect, it } from 'vitest'
33+import { runVitest } from '../../test-utils'
44+55+it('correctly runs workspace tests when workspace config path is specified', async () => {
66+ const { stderr, stdout } = await runVitest({
77+ root: 'fixtures/workspace',
88+ workspace: 'nested/e2e.projects.js',
99+ })
1010+ expect(stderr).toBe('')
1111+ expect(stdout).toContain('1 + 1 = 2')
1212+ expect(stdout).not.toContain('2 + 2 = 4')
1313+})
1414+1515+it('runs the workspace if there are several vitest config files', async () => {
1616+ const { stderr, stdout } = await runVitest({
1717+ root: 'fixtures/workspace/several-configs',
1818+ })
1919+ expect(stderr).toBe('')
2020+ expect(stdout).toContain('workspace/several-configs')
2121+ expect(stdout).toContain('| 1_test')
2222+ expect(stdout).toContain('| 2_test')
2323+ expect(stdout).toContain('1 + 1 = 2')
2424+ expect(stdout).toContain('2 + 2 = 4')
2525+})
2626+2727+it('correctly resolves workspace projects with a several folder globs', async () => {
2828+ const { stderr, stdout } = await runVitest({
2929+ root: 'fixtures/workspace/several-folders',
3030+ })
3131+ expect(stderr).toBe('')
3232+ expect(stdout).toContain('test - a')
3333+ expect(stdout).toContain('test - b')
3434+})
3535+3636+it('supports glob negation pattern', async () => {
3737+ const { stderr, stdout } = await runVitest({
3838+ root: 'fixtures/workspace/negated',
3939+ })
4040+ expect(stderr).toBe('')
4141+ expect(stdout).toContain('test - a')
4242+ expect(stdout).toContain('test - c')
4343+ expect(stdout).not.toContain('test - b')
4444+})
4545+4646+it('fails if project names are identical with a nice error message', async () => {
4747+ const { stderr } = await runVitest({
4848+ root: 'fixtures/workspace/invalid-duplicate-configs',
4949+ }, [], 'test', {}, { fails: true })
5050+ expect(stderr).toContain(
5151+ `Project name "test" from "vitest2.config.js" is not unique. The project is already defined by "vitest1.config.js".
5252+5353+Your config matched these files:
5454+ - vitest1.config.js
5555+ - vitest2.config.js
5656+5757+All projects should have unique names. Make sure your configuration is correct.`,
5858+ )
5959+})
6060+6161+it('fails if project names are identical inside the inline config', async () => {
6262+ const { stderr } = await runVitest({
6363+ root: 'fixtures/workspace/invalid-duplicate-inline',
6464+ }, [], 'test', {}, { fails: true })
6565+ expect(stderr).toContain(
6666+ 'Project name "test" is not unique. All projects should have unique names. Make sure your configuration is correct.',
6767+ )
6868+})
6969+7070+it('fails if referenced file doesnt exist', async () => {
7171+ const { stderr } = await runVitest({
7272+ root: 'fixtures/workspace/invalid-non-existing-config',
7373+ }, [], 'test', {}, { fails: true })
7474+ expect(stderr).toContain(
7575+ `Projects definition references a non-existing file or a directory: ${resolve('fixtures/workspace/invalid-non-existing-config/vitest.config.js')}`,
7676+ )
7777+})
7878+7979+it('vite import analysis is applied when loading workspace config', async () => {
8080+ const { stderr, stdout } = await runVitest({
8181+ root: 'fixtures/workspace/config-import-analysis',
8282+ })
8383+ expect(stderr).toBe('')
8484+ expect(stdout).toContain('test - a')
8585+})
8686+8787+it('can define inline workspace config programmatically', async () => {
8888+ const { stderr, stdout } = await runVitest({
8989+ root: 'fixtures/workspace/api',
9090+ env: {
9191+ TEST_ROOT: '1',
9292+ },
9393+ projects: [
9494+ {
9595+ extends: true,
9696+ test: {
9797+ name: 'project-1',
9898+ },
9999+ },
100100+ {
101101+ test: {
102102+ name: 'project-2',
103103+ env: {
104104+ TEST_ROOT: '2',
105105+ },
106106+ },
107107+ },
108108+ {
109109+ extends: './vite.custom.config.js',
110110+ test: {
111111+ name: 'project-3',
112112+ },
113113+ },
114114+ ],
115115+ })
116116+ expect(stderr).toBe('')
117117+ expect(stdout).toContain('project-1')
118118+ expect(stdout).toContain('project-2')
119119+ expect(stdout).toContain('project-3')
120120+ expect(stdout).toContain('3 passed')
121121+})
122122+123123+it('correctly inherits the root config', async () => {
124124+ const { stderr, stdout } = await runVitest({
125125+ root: 'fixtures/workspace/config-extends',
126126+ })
127127+ expect(stderr).toBe('')
128128+ expect(stdout).toContain('repro.test.js > importing a virtual module')
129129+})
130130+131131+it('fails if workspace is empty', async () => {
132132+ const { stderr } = await runVitest({
133133+ projects: [],
134134+ })
135135+ expect(stderr).toContain('No projects were found. Make sure your configuration is correct. The projects definition: [].')
136136+})
137137+138138+it('fails if workspace is filtered by the project', async () => {
139139+ const { stderr } = await runVitest({
140140+ project: 'non-existing',
141141+ root: 'fixtures/workspace/config-empty',
142142+ config: './vitest.config.js',
143143+ projects: [
144144+ './vitest.config.js',
145145+ ],
146146+ })
147147+ expect(stderr).toContain(`No projects were found. Make sure your configuration is correct. The filter matched no projects: non-existing. The projects definition: [
148148+ "./vitest.config.js"
149149+].`)
150150+})
-157
test/config/test/workspace.test.ts
···11-import { resolve } from 'pathe'
22-import { expect, it } from 'vitest'
33-import { runVitest } from '../../test-utils'
44-55-it('correctly runs workspace tests when workspace config path is specified', async () => {
66- const { stderr, stdout } = await runVitest({
77- root: 'fixtures/workspace',
88- workspace: 'nested/e2e.projects.js',
99- })
1010- expect(stderr).toBe('')
1111- expect(stdout).toContain('1 + 1 = 2')
1212- expect(stdout).not.toContain('2 + 2 = 4')
1313-})
1414-1515-it('runs the workspace if there are several vitest config files', async () => {
1616- const { stderr, stdout } = await runVitest({
1717- root: 'fixtures/workspace/several-configs',
1818- workspace: './fixtures/workspace/several-configs/vitest.workspace.ts',
1919- })
2020- expect(stderr).toBe('')
2121- expect(stdout).toContain('workspace/several-configs')
2222- expect(stdout).toContain('| 1_test')
2323- expect(stdout).toContain('| 2_test')
2424- expect(stdout).toContain('1 + 1 = 2')
2525- expect(stdout).toContain('2 + 2 = 4')
2626-})
2727-2828-it('correctly resolves workspace projects with a several folder globs', async () => {
2929- const { stderr, stdout } = await runVitest({
3030- root: 'fixtures/workspace/several-folders',
3131- workspace: './fixtures/workspace/several-folders/vitest.workspace.ts',
3232- })
3333- expect(stderr).toBe('')
3434- expect(stdout).toContain('test - a')
3535- expect(stdout).toContain('test - b')
3636-})
3737-3838-it('supports glob negation pattern', async () => {
3939- const { stderr, stdout } = await runVitest({
4040- root: 'fixtures/workspace/negated',
4141- workspace: './fixtures/workspace/negated/vitest.workspace.ts',
4242- })
4343- expect(stderr).toBe('')
4444- expect(stdout).toContain('test - a')
4545- expect(stdout).toContain('test - c')
4646- expect(stdout).not.toContain('test - b')
4747-})
4848-4949-it('fails if project names are identical with a nice error message', async () => {
5050- const { stderr } = await runVitest({
5151- root: 'fixtures/workspace/invalid-duplicate-configs',
5252- workspace: './fixtures/workspace/invalid-duplicate-configs/vitest.workspace.ts',
5353- }, [], 'test', {}, { fails: true })
5454- expect(stderr).toContain(
5555- `Project name "test" from "vitest2.config.js" is not unique. The project is already defined by "vitest1.config.js".
5656-5757-Your config matched these files:
5858- - vitest1.config.js
5959- - vitest2.config.js
6060-6161-All projects in a workspace should have unique names. Make sure your configuration is correct.`,
6262- )
6363-})
6464-6565-it('fails if project names are identical inside the inline config', async () => {
6666- const { stderr } = await runVitest({
6767- root: 'fixtures/workspace/invalid-duplicate-inline',
6868- workspace: './fixtures/workspace/invalid-duplicate-inline/vitest.workspace.ts',
6969- }, [], 'test', {}, { fails: true })
7070- expect(stderr).toContain(
7171- 'Project name "test" is not unique. All projects in a workspace should have unique names. Make sure your configuration is correct.',
7272- )
7373-})
7474-7575-it('fails if referenced file doesnt exist', async () => {
7676- const { stderr } = await runVitest({
7777- root: 'fixtures/workspace/invalid-non-existing-config',
7878- workspace: './fixtures/workspace/invalid-non-existing-config/vitest.workspace.ts',
7979- }, [], 'test', {}, { fails: true })
8080- expect(stderr).toContain(
8181- `Workspace config file "vitest.workspace.ts" references a non-existing file or a directory: ${resolve('fixtures/workspace/invalid-non-existing-config/vitest.config.js')}`,
8282- )
8383-})
8484-8585-it('vite import analysis is applied when loading workspace config', async () => {
8686- const { stderr, stdout } = await runVitest({
8787- root: 'fixtures/workspace/config-import-analysis',
8888- workspace: './fixtures/workspace/config-import-analysis/vitest.workspace.ts',
8989- })
9090- expect(stderr).toBe('')
9191- expect(stdout).toContain('test - a')
9292-})
9393-9494-it('can define inline workspace config programmatically', async () => {
9595- const { stderr, stdout } = await runVitest({
9696- root: 'fixtures/workspace/api',
9797- env: {
9898- TEST_ROOT: '1',
9999- },
100100- workspace: [
101101- {
102102- extends: true,
103103- test: {
104104- name: 'project-1',
105105- },
106106- },
107107- {
108108- test: {
109109- name: 'project-2',
110110- env: {
111111- TEST_ROOT: '2',
112112- },
113113- },
114114- },
115115- {
116116- extends: './vite.custom.config.js',
117117- test: {
118118- name: 'project-3',
119119- },
120120- },
121121- ],
122122- })
123123- expect(stderr).toBe('')
124124- expect(stdout).toContain('project-1')
125125- expect(stdout).toContain('project-2')
126126- expect(stdout).toContain('project-3')
127127- expect(stdout).toContain('3 passed')
128128-})
129129-130130-it('correctly inherits the root config', async () => {
131131- const { stderr, stdout } = await runVitest({
132132- root: 'fixtures/workspace/config-extends',
133133- })
134134- expect(stderr).toBe('')
135135- expect(stdout).toContain('repro.test.js > importing a virtual module')
136136-})
137137-138138-it('fails if workspace is empty', async () => {
139139- const { stderr } = await runVitest({
140140- workspace: [],
141141- })
142142- expect(stderr).toContain('No projects were found. Make sure your configuration is correct. The workspace: [].')
143143-})
144144-145145-it('fails if workspace is filtered by the project', async () => {
146146- const { stderr } = await runVitest({
147147- project: 'non-existing',
148148- root: 'fixtures/workspace/config-empty',
149149- config: './vitest.config.js',
150150- workspace: [
151151- './vitest.config.js',
152152- ],
153153- })
154154- expect(stderr).toContain(`No projects were found. Make sure your configuration is correct. The filter matched no projects: non-existing. The workspace: [
155155- "./vitest.config.js"
156156-].`)
157157-})
···55 {
66 name: 'throw-error',
77 config() {
88- throw new Error('This file should not initiate a workspace project.')
88+ throw new Error('This file should not initiate a test project.')
99 },
1010 },
1111 ],
···7070 for (const [glob, pool] of project.config.poolMatchGlobs) {
7171 if ((pool as Pool) === 'browser') {
7272 throw new Error(
7373- 'Since Vitest 0.31.0 "browser" pool is not supported in "poolMatchGlobs". You can create a workspace to run some of your tests in browser in parallel. Read more: https://vitest.dev/guide/workspace',
7373+ 'Since Vitest 0.31.0 "browser" pool is not supported in "poolMatchGlobs". You can create a project to run some of your tests in browser in parallel. Read more: https://vitest.dev/guide/projects',
7474 )
7575 }
7676 if (mm.isMatch(file, glob, { cwd: project.config.root })) {
+3
packages/vitest/src/public/config.ts
···6666 return config
6767}
68686969+/**
7070+ * @deprecated use the `projects` field in the root config instead
7171+ */
6972export function defineWorkspace(config: TestProjectConfiguration[]): TestProjectConfiguration[] {
7073 return config
7174}