mirror of
https://github.com/vitest-dev/vitest.git
synced 2026-02-01 17:36:51 +00:00
feat: deprecate workspace in favor of projects (#7923)
Co-authored-by: Ari Perkkiö <ari.perkkio@gmail.com>
This commit is contained in:
parent
5f50495843
commit
41beb261e6
@ -43,7 +43,7 @@ Next generation testing framework powered by Vite.
|
||||
- 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))
|
||||
- Workers multi-threading via [Tinypool](https://github.com/tinylibs/tinypool) (a lightweight fork of [Piscina](https://github.com/piscinajs/piscina))
|
||||
- Benchmarking support with [Tinybench](https://github.com/tinylibs/tinybench)
|
||||
- [Workspace](https://vitest.dev/guide/workspace) support
|
||||
- [Projects](https://vitest.dev/guide/projects) support
|
||||
- [expect-type](https://github.com/mmkal/expect-type) for type-level testing
|
||||
- ESM first, top level await
|
||||
- Out-of-box TypeScript / JSX support
|
||||
|
||||
@ -13,7 +13,7 @@
|
||||
<ListItem>Workers multi-threading via <a target="_blank" href="https://github.com/tinylibs/tinypool" rel="noopener noreferrer">Tinypool</a></ListItem>
|
||||
<ListItem>Benchmarking support with <a target="_blank" href="https://github.com/tinylibs/tinybench" rel="noopener noreferrer">Tinybench</a></ListItem>
|
||||
<ListItem>Filtering, timeouts, concurrent for suite and tests</ListItem>
|
||||
<ListItem><a href="/guide/workspace">Workspace</a> support</ListItem>
|
||||
<ListItem><a href="/guide/projects">Projects</a> support</ListItem>
|
||||
<ListItem>
|
||||
<a href="/guide/snapshot">
|
||||
Jest-compatible Snapshot
|
||||
|
||||
@ -477,8 +477,8 @@ function guide(): DefaultTheme.SidebarItem[] {
|
||||
link: '/guide/filtering',
|
||||
},
|
||||
{
|
||||
text: 'Workspace',
|
||||
link: '/guide/workspace',
|
||||
text: 'Test Projects',
|
||||
link: '/guide/projects',
|
||||
},
|
||||
{
|
||||
text: 'Reporters',
|
||||
|
||||
@ -119,7 +119,7 @@ If you pass down the config to the `startVitest` or `createVitest` APIs, Vitest
|
||||
:::
|
||||
|
||||
::: warning
|
||||
The `resolveConfig` doesn't resolve the `workspace`. To resolve workspace configs, Vitest needs an established Vite server.
|
||||
The `resolveConfig` doesn't resolve `projects`. To resolve projects configs, Vitest needs an established Vite server.
|
||||
|
||||
Also note that `viteConfig.test` will not be fully resolved. If you need Vitest config, use `vitestConfig` instead.
|
||||
:::
|
||||
|
||||
@ -53,7 +53,7 @@ Vitest re-exports all Vite type-only imports via a `Vite` namespace, which you c
|
||||
```
|
||||
:::
|
||||
|
||||
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.
|
||||
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.
|
||||
|
||||
## Context
|
||||
|
||||
@ -107,7 +107,7 @@ const newProjects = await injectTestProjects({
|
||||
```
|
||||
|
||||
::: warning Projects are Filtered
|
||||
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:
|
||||
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:
|
||||
|
||||
```ts
|
||||
vitest.config.project.push('my-project-name')
|
||||
|
||||
@ -4,10 +4,8 @@ title: TestProject
|
||||
|
||||
# TestProject <Version>3.0.0</Version> {#testproject}
|
||||
|
||||
- **Alias**: `WorkspaceProject` before 3.0.0
|
||||
|
||||
::: warning
|
||||
This guide describes the advanced Node.js API. If you just want to create a workspace, follow the ["Workspace"](/guide/workspace) guide.
|
||||
This guide describes the advanced Node.js API. If you just want to define projects, follow the ["Test Projects"](/guide/projects) guide.
|
||||
:::
|
||||
|
||||
## name
|
||||
@ -26,28 +24,34 @@ vitest.projects.map(p => p.name) === [
|
||||
'custom'
|
||||
]
|
||||
```
|
||||
```ts [vitest.workspace.js]
|
||||
export default [
|
||||
'./packages/server', // has package.json with "@pkg/server"
|
||||
'./utils', // doesn't have a package.json file
|
||||
{
|
||||
// doesn't customize the name
|
||||
test: {
|
||||
pool: 'threads',
|
||||
},
|
||||
```ts [vitest.config.js]
|
||||
import { defineConfig } from 'vitest/config'
|
||||
|
||||
export default defineConfig({
|
||||
test: {
|
||||
projects: [
|
||||
'./packages/server', // has package.json with "@pkg/server"
|
||||
'./utils', // doesn't have a package.json file
|
||||
{
|
||||
// doesn't customize the name
|
||||
test: {
|
||||
pool: 'threads',
|
||||
},
|
||||
},
|
||||
{
|
||||
// customized the name
|
||||
test: {
|
||||
name: 'custom',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
// customized the name
|
||||
test: {
|
||||
name: 'custom',
|
||||
},
|
||||
},
|
||||
]
|
||||
})
|
||||
```
|
||||
:::
|
||||
|
||||
::: info
|
||||
If the [root project](/advanced/api/vitest#getroottestproject) is not part of a user workspace, its `name` will not be resolved.
|
||||
If the [root project](/advanced/api/vitest#getroottestproject) is not part of user projects, its `name` will not be resolved.
|
||||
:::
|
||||
|
||||
## vitest
|
||||
@ -279,7 +283,7 @@ dynamicExample !== staticExample // ✅
|
||||
:::
|
||||
|
||||
::: info
|
||||
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.
|
||||
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.
|
||||
:::
|
||||
|
||||
## onTestsRerun
|
||||
|
||||
@ -64,7 +64,7 @@ Benchmark mode calls `bench` functions and throws an error, when it encounters `
|
||||
|
||||
## config
|
||||
|
||||
The root (or global) config. If workspace feature is enabled, projects will reference this as `globalConfig`.
|
||||
The root (or global) config. If projects are defined, they will reference this as `globalConfig`.
|
||||
|
||||
::: warning
|
||||
This is Vitest config, it doesn't extend _Vite_ config. It only has resolved values from the `test` property.
|
||||
@ -101,9 +101,9 @@ Cache manager that stores information about latest test results and test file st
|
||||
|
||||
## projects
|
||||
|
||||
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).
|
||||
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).
|
||||
|
||||
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.
|
||||
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.
|
||||
|
||||
## getRootProject
|
||||
|
||||
@ -111,7 +111,7 @@ Vitest will ensure that there is always at least one project in the workspace. I
|
||||
function getRootProject(): TestProject
|
||||
```
|
||||
|
||||
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.
|
||||
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.
|
||||
|
||||
The primary goal of the root project is to setup the global config. In fact, `rootProject.config` references `rootProject.globalConfig` and `vitest.config` directly:
|
||||
|
||||
@ -433,7 +433,7 @@ dynamicExample !== staticExample // ✅
|
||||
:::
|
||||
|
||||
::: info
|
||||
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.
|
||||
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.
|
||||
:::
|
||||
|
||||
## close
|
||||
|
||||
@ -31,12 +31,12 @@ export default defineConfig({
|
||||
})
|
||||
```
|
||||
|
||||
If you need to run tests in different pools, use the [workspace](/guide/workspace) feature:
|
||||
If you need to run tests in different pools, use the [`projects`](/guide/projects) feature:
|
||||
|
||||
```ts [vitest.config.ts]
|
||||
export default defineConfig({
|
||||
test: {
|
||||
workspace: [
|
||||
projects: [
|
||||
{
|
||||
extends: true,
|
||||
test: {
|
||||
@ -48,10 +48,6 @@ export default defineConfig({
|
||||
})
|
||||
```
|
||||
|
||||
::: info
|
||||
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.
|
||||
:::
|
||||
|
||||
## API
|
||||
|
||||
The file specified in `pool` option should export a function (can be async) that accepts `Vitest` interface as its first option. This function needs to return an object matching `ProcessPool` interface:
|
||||
@ -69,7 +65,7 @@ export interface ProcessPool {
|
||||
|
||||
The 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.
|
||||
|
||||
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.
|
||||
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.
|
||||
|
||||
Vitest will wait until `runTests` is executed before finishing a run (i.e., it will emit [`onFinished`](/advanced/reporters) only after `runTests` is resolved).
|
||||
|
||||
|
||||
@ -164,7 +164,7 @@ interface File extends Suite {
|
||||
*/
|
||||
filepath: string
|
||||
/**
|
||||
* The name of the workspace project the file belongs to.
|
||||
* The name of the test project the file belongs to.
|
||||
*/
|
||||
projectName: string | undefined
|
||||
/**
|
||||
|
||||
@ -72,7 +72,7 @@ You can follow the design process in [#7069](https://github.com/vitest-dev/vites
|
||||
|
||||
## Inline Workspace
|
||||
|
||||
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:
|
||||
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:
|
||||
|
||||
```jsx
|
||||
import { defineConfig } from 'vitest/config'
|
||||
|
||||
@ -106,7 +106,7 @@ export default defineConfig({
|
||||
|
||||
Since 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.
|
||||
|
||||
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.
|
||||
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.
|
||||
:::
|
||||
|
||||
### include
|
||||
@ -588,7 +588,7 @@ These options are passed down to `setup` method of current [`environment`](#envi
|
||||
- **Default:** `[]`
|
||||
|
||||
::: danger DEPRECATED
|
||||
This API was deprecated in Vitest 3. Use [workspace](/guide/workspace) to define different configurations instead.
|
||||
This API was deprecated in Vitest 3. Use [projects](/guide/projects) to define different configurations instead.
|
||||
|
||||
```ts
|
||||
export default defineConfig({
|
||||
@ -596,7 +596,7 @@ export default defineConfig({
|
||||
environmentMatchGlobs: [ // [!code --]
|
||||
['./*.jsdom.test.ts', 'jsdom'], // [!code --]
|
||||
], // [!code --]
|
||||
workspace: [ // [!code ++]
|
||||
projects: [ // [!code ++]
|
||||
{ // [!code ++]
|
||||
extends: true, // [!code ++]
|
||||
test: { // [!code ++]
|
||||
@ -635,7 +635,7 @@ export default defineConfig({
|
||||
- **Default:** `[]`
|
||||
|
||||
::: danger DEPRECATED
|
||||
This API was deprecated in Vitest 3. Use [workspace](/guide/workspace) to define different configurations instead:
|
||||
This API was deprecated in Vitest 3. Use [projects](/guide/projects) to define different configurations instead:
|
||||
|
||||
```ts
|
||||
export default defineConfig({
|
||||
@ -643,7 +643,7 @@ export default defineConfig({
|
||||
poolMatchGlobs: [ // [!code --]
|
||||
['./*.threads.test.ts', 'threads'], // [!code --]
|
||||
], // [!code --]
|
||||
workspace: [ // [!code ++]
|
||||
projects: [ // [!code ++]
|
||||
{ // [!code ++]
|
||||
test: { // [!code ++]
|
||||
extends: true, // [!code ++]
|
||||
@ -724,7 +724,7 @@ export default defineConfig({
|
||||
```
|
||||
|
||||
::: warning
|
||||
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.
|
||||
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.
|
||||
:::
|
||||
|
||||
### root
|
||||
@ -2436,14 +2436,25 @@ Tells fake timers to clear "native" (i.e. not fake) timers by delegating to thei
|
||||
|
||||
### workspace<NonProjectOption /> {#workspace}
|
||||
|
||||
- **Type:** `string | TestProjectConfiguration`
|
||||
::: danger DEPRECATED
|
||||
This options is deprecated and will be removed in the next major. Please, use [`projects`](#projects) instead.
|
||||
:::
|
||||
|
||||
- **Type:** `string | TestProjectConfiguration[]`
|
||||
- **CLI:** `--workspace=./file.js`
|
||||
- **Default:** `vitest.{workspace,projects}.{js,ts,json}` close to the config file or root
|
||||
|
||||
Path to a [workspace](/guide/workspace) config file relative to [root](#root).
|
||||
Path to a [workspace](/guide/projects) config file relative to [root](#root).
|
||||
|
||||
Since 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.
|
||||
|
||||
### projects<NonProjectOption /> {#projects}
|
||||
|
||||
- **Type:** `TestProjectConfiguration[]`
|
||||
- **Default:** `[]`
|
||||
|
||||
An array of [projects](/guide/projects).
|
||||
|
||||
### isolate
|
||||
|
||||
- **Type:** `boolean`
|
||||
|
||||
@ -11,7 +11,7 @@ Command is a function that invokes another function on the server and passes dow
|
||||
|
||||
### Files Handling
|
||||
|
||||
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.
|
||||
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.
|
||||
|
||||
By default, Vitest uses `utf-8` encoding but you can override it with options.
|
||||
|
||||
|
||||
@ -8,7 +8,7 @@ outline: deep
|
||||
This 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.
|
||||
|
||||
::: tip
|
||||
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/).
|
||||
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/).
|
||||
:::
|
||||
|
||||
<img alt="Vitest UI" img-light src="/ui-browser-1-light.png">
|
||||
@ -209,44 +209,48 @@ export default defineConfig({
|
||||
```
|
||||
:::
|
||||
|
||||
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:
|
||||
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:
|
||||
|
||||
{#workspace-config}
|
||||
{#projects-config}
|
||||
|
||||
```ts [vitest.workspace.ts]
|
||||
import { defineWorkspace } from 'vitest/config'
|
||||
```ts [vitest.config.ts]
|
||||
import { defineConfig } from 'vitest/config'
|
||||
|
||||
export default defineWorkspace([
|
||||
{
|
||||
test: {
|
||||
// an example of file based convention,
|
||||
// you don't have to follow it
|
||||
include: [
|
||||
'tests/unit/**/*.{test,spec}.ts',
|
||||
'tests/**/*.unit.{test,spec}.ts',
|
||||
],
|
||||
name: 'unit',
|
||||
environment: 'node',
|
||||
},
|
||||
},
|
||||
{
|
||||
test: {
|
||||
// an example of file based convention,
|
||||
// you don't have to follow it
|
||||
include: [
|
||||
'tests/browser/**/*.{test,spec}.ts',
|
||||
'tests/**/*.browser.{test,spec}.ts',
|
||||
],
|
||||
name: 'browser',
|
||||
browser: {
|
||||
enabled: true,
|
||||
instances: [
|
||||
{ browser: 'chromium' },
|
||||
],
|
||||
export default defineConfig({
|
||||
test: {
|
||||
projects: [
|
||||
{
|
||||
test: {
|
||||
// an example of file based convention,
|
||||
// you don't have to follow it
|
||||
include: [
|
||||
'tests/unit/**/*.{test,spec}.ts',
|
||||
'tests/**/*.unit.{test,spec}.ts',
|
||||
],
|
||||
name: 'unit',
|
||||
environment: 'node',
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
test: {
|
||||
// an example of file based convention,
|
||||
// you don't have to follow it
|
||||
include: [
|
||||
'tests/browser/**/*.{test,spec}.ts',
|
||||
'tests/**/*.browser.{test,spec}.ts',
|
||||
],
|
||||
name: 'browser',
|
||||
browser: {
|
||||
enabled: true,
|
||||
instances: [
|
||||
{ browser: 'chromium' },
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
])
|
||||
})
|
||||
```
|
||||
|
||||
## Browser Option Types
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
|
||||
Since Vitest 3, you can specify several different browser setups using the new [`browser.instances`](/guide/browser/config#browser-instances) option.
|
||||
|
||||
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.
|
||||
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.
|
||||
|
||||
## Several Browsers
|
||||
|
||||
|
||||
@ -291,7 +291,7 @@ Override Vite mode (default: `test` or `benchmark`)
|
||||
- **CLI:** `--workspace <path>`
|
||||
- **Config:** [workspace](/config/#workspace)
|
||||
|
||||
Path to a workspace configuration file
|
||||
[deprecated] Path to a workspace configuration file
|
||||
|
||||
### isolate
|
||||
|
||||
@ -360,7 +360,7 @@ Set to true to exit if port is already in use, instead of automatically trying t
|
||||
- **CLI:** `--browser.provider <name>`
|
||||
- **Config:** [browser.provider](/guide/browser/config#browser-provider)
|
||||
|
||||
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"`)
|
||||
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"`)
|
||||
|
||||
### browser.providerOptions
|
||||
|
||||
|
||||
@ -22,7 +22,7 @@ The `require` of CSS and assets inside the external dependencies are resolved au
|
||||
::: warning
|
||||
"Environments" exist only when running tests in Node.js.
|
||||
|
||||
`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).
|
||||
`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).
|
||||
:::
|
||||
|
||||
## Environments for Specific Files
|
||||
|
||||
@ -175,17 +175,17 @@ export default defineConfig({
|
||||
However, we recommend using the same file for both Vite and Vitest, instead of creating two separate files.
|
||||
:::
|
||||
|
||||
## Workspaces Support
|
||||
## Projects Support
|
||||
|
||||
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.
|
||||
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.
|
||||
|
||||
```ts [vitest.config.ts]
|
||||
import { defineConfig } from 'vitest/config'
|
||||
|
||||
export default defineConfig({
|
||||
test: {
|
||||
workspace: [
|
||||
// you can use a list of glob patterns to define your workspaces
|
||||
projects: [
|
||||
// you can use a list of glob patterns to define your projects
|
||||
// Vitest expects a list of config files
|
||||
// or directories where there is a config file
|
||||
'packages/*',
|
||||
@ -261,7 +261,7 @@ Learn more about [IDE Integrations](/guide/ide)
|
||||
| `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__/) |
|
||||
| `profiling` | [GitHub](https://github.com/vitest-dev/vitest/tree/main/examples/profiling) | Not Available |
|
||||
| `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__/) |
|
||||
| `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__/) |
|
||||
| `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__/) |
|
||||
|
||||
## Projects using Vitest
|
||||
|
||||
|
||||
@ -1,92 +1,75 @@
|
||||
---
|
||||
title: Workspace | Guide
|
||||
title: Test Projects | Guide
|
||||
---
|
||||
|
||||
# Workspace
|
||||
# Test Projects
|
||||
|
||||
::: tip Sample Project
|
||||
|
||||
[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__/)
|
||||
[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__/)
|
||||
|
||||
:::
|
||||
|
||||
::: warning
|
||||
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.
|
||||
:::
|
||||
|
||||
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.
|
||||
|
||||
## Defining a Workspace
|
||||
## Defining Projects
|
||||
|
||||
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.
|
||||
You can define projects in your root [config](/config/):
|
||||
|
||||
```ts [vitest.config.ts]
|
||||
import { defineConfig } from 'vitest/config'
|
||||
|
||||
export default defineConfig({
|
||||
test: {
|
||||
workspace: ['packages/*'],
|
||||
projects: ['packages/*'],
|
||||
},
|
||||
})
|
||||
```
|
||||
|
||||
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.
|
||||
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:
|
||||
|
||||
::: tip NAMING
|
||||
Please note that this feature is named `workspace`, not `workspaces` (without an "s" at the end).
|
||||
:::
|
||||
|
||||
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:
|
||||
|
||||
:::code-group
|
||||
```ts [vitest.config.ts <Version>3.0.0</Version>]
|
||||
```ts [vitest.config.ts]
|
||||
import { defineConfig } from 'vitest/config'
|
||||
|
||||
export default defineConfig({
|
||||
test: {
|
||||
workspace: ['packages/*'],
|
||||
projects: ['packages/*'],
|
||||
},
|
||||
})
|
||||
```
|
||||
```ts [vitest.workspace.ts]
|
||||
export default [
|
||||
'packages/*'
|
||||
]
|
||||
```
|
||||
:::
|
||||
|
||||
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.
|
||||
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.
|
||||
|
||||
::: warning
|
||||
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.
|
||||
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.
|
||||
:::
|
||||
|
||||
You can also reference projects with their config files:
|
||||
|
||||
:::code-group
|
||||
```ts [vitest.config.ts <Version>3.0.0</Version>]
|
||||
```ts [vitest.config.ts]
|
||||
import { defineConfig } from 'vitest/config'
|
||||
|
||||
export default defineConfig({
|
||||
test: {
|
||||
workspace: ['packages/*/vitest.config.{e2e,unit}.ts'],
|
||||
projects: ['packages/*/vitest.config.{e2e,unit}.ts'],
|
||||
},
|
||||
})
|
||||
```
|
||||
```ts [vitest.workspace.ts]
|
||||
export default [
|
||||
'packages/*/vitest.config.{e2e,unit}.ts'
|
||||
]
|
||||
```
|
||||
:::
|
||||
|
||||
This pattern will only include projects with a `vitest.config` file that contains `e2e` or `unit` before the extension.
|
||||
|
||||
You can also define projects using inline configuration. The workspace configuration supports both syntaxes simultaneously.
|
||||
You can also define projects using inline configuration. The configuration supports both syntaxes simultaneously.
|
||||
|
||||
:::code-group
|
||||
```ts [vitest.config.ts <Version>3.0.0</Version>]
|
||||
```ts [vitest.config.ts]
|
||||
import { defineConfig } from 'vitest/config'
|
||||
|
||||
export default defineConfig({
|
||||
test: {
|
||||
workspace: [
|
||||
projects: [
|
||||
// matches every folder and file inside the `packages` folder
|
||||
'packages/*',
|
||||
{
|
||||
@ -111,47 +94,12 @@ export default defineConfig({
|
||||
}
|
||||
})
|
||||
```
|
||||
```ts [vitest.workspace.ts]
|
||||
import { defineWorkspace } from 'vitest/config'
|
||||
|
||||
// defineWorkspace provides a nice type hinting DX
|
||||
export default defineWorkspace([
|
||||
// matches every folder and file inside the `packages` folder
|
||||
'packages/*',
|
||||
{
|
||||
// add "extends" to merge two configs together
|
||||
extends: './vite.config.js',
|
||||
test: {
|
||||
include: ['tests/**/*.{browser}.test.{ts,js}'],
|
||||
// it is recommended to define a name when using inline configs
|
||||
name: 'happy-dom',
|
||||
environment: 'happy-dom',
|
||||
}
|
||||
},
|
||||
{
|
||||
test: {
|
||||
include: ['tests/**/*.{node}.test.{ts,js}'],
|
||||
name: 'node',
|
||||
environment: 'node',
|
||||
}
|
||||
}
|
||||
])
|
||||
```
|
||||
:::
|
||||
|
||||
::: warning
|
||||
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.
|
||||
:::
|
||||
|
||||
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:
|
||||
|
||||
```json [vitest.workspace.json]
|
||||
[
|
||||
"packages/*"
|
||||
]
|
||||
```
|
||||
|
||||
Workspace projects do not support all configuration properties. For better type safety, use the `defineProject` method instead of `defineConfig` within project configuration files:
|
||||
Projects do not support all configuration properties. For better type safety, use the `defineProject` method instead of `defineConfig` within project configuration files:
|
||||
|
||||
```ts twoslash [packages/a/vitest.config.ts]
|
||||
// @errors: 2769
|
||||
@ -169,7 +117,7 @@ export default defineProject({
|
||||
|
||||
## Running tests
|
||||
|
||||
To run tests inside the workspace, define a script in your root `package.json`:
|
||||
To run tests, define a script in your root `package.json`:
|
||||
|
||||
```json [package.json]
|
||||
{
|
||||
@ -233,7 +181,7 @@ bun run test --project e2e --project unit
|
||||
|
||||
## Configuration
|
||||
|
||||
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:
|
||||
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:
|
||||
|
||||
```ts [packages/a/vitest.config.ts]
|
||||
import { defineProject, mergeConfig } from 'vitest/config'
|
||||
@ -249,10 +197,9 @@ export default mergeConfig(
|
||||
)
|
||||
```
|
||||
|
||||
Additionally, at the `defineWorkspace` level, you can use the `extends` option to inherit from your root-level configuration. All options will be merged.
|
||||
Additionally, you can use the `extends` option to inherit from your root-level configuration. All options will be merged.
|
||||
|
||||
::: code-group
|
||||
```ts [vitest.config.ts <Version>3.0.0</Version>]
|
||||
```ts [vitest.config.ts]
|
||||
import { defineConfig } from 'vitest/config'
|
||||
import react from '@vitejs/plugin-react'
|
||||
|
||||
@ -260,7 +207,7 @@ export default defineConfig({
|
||||
plugins: [react()],
|
||||
test: {
|
||||
pool: 'threads',
|
||||
workspace: [
|
||||
projects: [
|
||||
{
|
||||
// will inherit options from this config like plugins and pool
|
||||
extends: true,
|
||||
@ -282,32 +229,11 @@ export default defineConfig({
|
||||
},
|
||||
})
|
||||
```
|
||||
```ts [vitest.workspace.ts]
|
||||
import { defineWorkspace } from 'vitest/config'
|
||||
|
||||
export default defineWorkspace([
|
||||
{
|
||||
extends: './vitest.config.ts',
|
||||
test: {
|
||||
name: 'unit',
|
||||
include: ['**/*.unit.test.ts'],
|
||||
},
|
||||
},
|
||||
{
|
||||
extends: './vitest.config.ts',
|
||||
test: {
|
||||
name: 'integration',
|
||||
include: ['**/*.integration.test.ts'],
|
||||
},
|
||||
},
|
||||
])
|
||||
```
|
||||
:::
|
||||
|
||||
::: danger Unsupported Options
|
||||
Some of the configuration options are not allowed in a project config. Most notably:
|
||||
|
||||
- `coverage`: coverage is done for the whole workspace
|
||||
- `coverage`: coverage is done for the whole process
|
||||
- `reporters`: only root-level reporters can be supported
|
||||
- `resolveSnapshotPath`: only root-level resolver is respected
|
||||
- all other options that don't affect test runners
|
||||
@ -232,7 +232,7 @@ test('works correctly')
|
||||
|
||||
#### Default fixture
|
||||
|
||||
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.
|
||||
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.
|
||||
|
||||
:::code-group
|
||||
```ts [fixtures.test.ts]
|
||||
@ -253,32 +253,36 @@ test('works correctly', ({ url }) => {
|
||||
// url is "/empty" in "project-empty"
|
||||
})
|
||||
```
|
||||
```ts [vitest.workspace.ts]
|
||||
import { defineWorkspace } from 'vitest/config'
|
||||
```ts [vitest.config.ts]
|
||||
import { defineConfig } from 'vitest/config'
|
||||
|
||||
export default defineWorkspace([
|
||||
{
|
||||
test: {
|
||||
name: 'project-new',
|
||||
},
|
||||
},
|
||||
{
|
||||
test: {
|
||||
name: 'project-full',
|
||||
provide: {
|
||||
url: '/full',
|
||||
export default defineConfig({
|
||||
test: {
|
||||
projects: [
|
||||
{
|
||||
test: {
|
||||
name: 'project-new',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
test: {
|
||||
name: 'project-empty',
|
||||
provide: {
|
||||
url: '/empty',
|
||||
{
|
||||
test: {
|
||||
name: 'project-full',
|
||||
provide: {
|
||||
url: '/full',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
test: {
|
||||
name: 'project-empty',
|
||||
provide: {
|
||||
url: '/empty',
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
])
|
||||
})
|
||||
```
|
||||
:::
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
{
|
||||
"name": "@vitest/example-workspace",
|
||||
"name": "@vitest/example-projects",
|
||||
"type": "module",
|
||||
"private": true,
|
||||
"license": "MIT",
|
||||
@ -2,7 +2,7 @@ import { render, screen } from '@testing-library/react'
|
||||
import { userEvent } from '@testing-library/user-event'
|
||||
import React from 'react'
|
||||
import { expect, test } from 'vitest'
|
||||
import Link from '../components/Link.jsx'
|
||||
import Link from '../components/Link.js'
|
||||
|
||||
test('Link changes the state when hovered', async () => {
|
||||
render(
|
||||
@ -1,6 +1,6 @@
|
||||
import type { FastifyInstance } from 'fastify'
|
||||
import Fastify from 'fastify'
|
||||
import { usersData } from '../mockData'
|
||||
import { usersData } from '../mockData.js'
|
||||
|
||||
const app: FastifyInstance = Fastify({
|
||||
logger: process.env.NODE_ENV === 'development',
|
||||
@ -1,4 +1,4 @@
|
||||
import app from './app'
|
||||
import app from './app.js'
|
||||
|
||||
async function start() {
|
||||
try {
|
||||
@ -1,8 +1,8 @@
|
||||
import supertest from 'supertest'
|
||||
import { afterAll, expect, test } from 'vitest'
|
||||
|
||||
import { usersData } from '../mockData'
|
||||
import app from '../src/app'
|
||||
import { usersData } from '../mockData.js'
|
||||
import app from '../src/app.js'
|
||||
|
||||
test('with HTTP injection', async () => {
|
||||
const response = await app.inject({
|
||||
7
examples/projects/vitest.config.ts
Normal file
7
examples/projects/vitest.config.ts
Normal file
@ -0,0 +1,7 @@
|
||||
import { defineConfig } from 'vitest/config'
|
||||
|
||||
export default defineConfig({
|
||||
test: {
|
||||
projects: ['packages/*'],
|
||||
},
|
||||
})
|
||||
@ -1,5 +0,0 @@
|
||||
import { defineWorkspace } from 'vitest/config'
|
||||
|
||||
export default defineWorkspace([
|
||||
'packages/*',
|
||||
])
|
||||
10
netlify.toml
10
netlify.toml
@ -25,6 +25,16 @@ from = "/config/file"
|
||||
to = "/config/"
|
||||
status = 301
|
||||
|
||||
[[redirects]]
|
||||
from = "/guide/workspace"
|
||||
to = "/guide/projects"
|
||||
status = 301
|
||||
|
||||
[[redirects]]
|
||||
from = "/guide/workspace.html"
|
||||
to = "/guide/projects"
|
||||
status = 301
|
||||
|
||||
[[headers]]
|
||||
for = "/manifest.webmanifest"
|
||||
|
||||
|
||||
@ -332,7 +332,7 @@ export const cliOptionsConfig: VitestCLIOptions = {
|
||||
argument: '<name>',
|
||||
},
|
||||
workspace: {
|
||||
description: 'Path to a workspace configuration file',
|
||||
description: '[deprecated] Path to a workspace configuration file',
|
||||
argument: '<path>',
|
||||
normalize: true,
|
||||
},
|
||||
@ -863,6 +863,7 @@ export const cliOptionsConfig: VitestCLIOptions = {
|
||||
json: null,
|
||||
provide: null,
|
||||
filesOnly: null,
|
||||
projects: null,
|
||||
watchTriggerPatterns: null,
|
||||
}
|
||||
|
||||
|
||||
@ -15,7 +15,7 @@ import { promises as fs } from 'node:fs'
|
||||
import { getTasks, hasFailed } from '@vitest/runner/utils'
|
||||
import { SnapshotManager } from '@vitest/snapshot/manager'
|
||||
import { noop, toArray } from '@vitest/utils'
|
||||
import { dirname, join, normalize, relative } from 'pathe'
|
||||
import { dirname, join, normalize, relative, resolve } from 'pathe'
|
||||
import { ViteNodeRunner } from 'vite-node/client'
|
||||
import { ViteNodeServer } from 'vite-node/server'
|
||||
import { version } from '../../package.json' with { type: 'json' }
|
||||
@ -33,6 +33,7 @@ import { Logger } from './logger'
|
||||
import { VitestPackageInstaller } from './packageInstaller'
|
||||
import { createPool } from './pool'
|
||||
import { TestProject } from './project'
|
||||
import { getDefaultTestProject, resolveBrowserProjects, resolveProjects } from './projects/resolveProjects'
|
||||
import { BlobReporter, readBlobs } from './reporters/blob'
|
||||
import { HangingProcessReporter } from './reporters/hanging-process'
|
||||
import { createBenchmarkReporters, createReporters } from './reporters/utils'
|
||||
@ -40,7 +41,6 @@ import { VitestSpecifications } from './specifications'
|
||||
import { StateManager } from './state'
|
||||
import { TestRun } from './test-run'
|
||||
import { VitestWatcher } from './watcher'
|
||||
import { getDefaultTestProject, resolveBrowserWorkspace, resolveWorkspace } from './workspace/resolveWorkspace'
|
||||
|
||||
const WATCHER_DEBOUNCE = 100
|
||||
|
||||
@ -274,7 +274,7 @@ export class Vitest {
|
||||
}
|
||||
catch { }
|
||||
|
||||
const projects = await this.resolveWorkspace(cliOptions)
|
||||
const projects = await this.resolveProjects(cliOptions)
|
||||
this.resolvedProjects = projects
|
||||
this.projects = projects
|
||||
|
||||
@ -325,15 +325,15 @@ export class Vitest {
|
||||
*/
|
||||
private injectTestProject = async (config: TestProjectConfiguration | TestProjectConfiguration[]): Promise<TestProject[]> => {
|
||||
const currentNames = new Set(this.projects.map(p => p.name))
|
||||
const workspace = await resolveWorkspace(
|
||||
const projects = await resolveProjects(
|
||||
this,
|
||||
this._options,
|
||||
undefined,
|
||||
Array.isArray(config) ? config : [config],
|
||||
currentNames,
|
||||
)
|
||||
this.projects.push(...workspace)
|
||||
return workspace
|
||||
this.projects.push(...projects)
|
||||
return projects
|
||||
}
|
||||
|
||||
/**
|
||||
@ -423,11 +423,30 @@ export class Vitest {
|
||||
return join(configDir, workspaceConfigName)
|
||||
}
|
||||
|
||||
private async resolveWorkspace(cliOptions: UserConfig): Promise<TestProject[]> {
|
||||
private async resolveProjects(cliOptions: UserConfig): Promise<TestProject[]> {
|
||||
const names = new Set<string>()
|
||||
|
||||
if (this.config.projects) {
|
||||
if (typeof this.config.workspace !== 'undefined') {
|
||||
this.logger.warn(
|
||||
'Both `config.projects` and `config.workspace` are defined. Ignoring the `workspace` option.',
|
||||
)
|
||||
}
|
||||
|
||||
return resolveProjects(
|
||||
this,
|
||||
cliOptions,
|
||||
undefined,
|
||||
this.config.projects,
|
||||
names,
|
||||
)
|
||||
}
|
||||
|
||||
if (Array.isArray(this.config.workspace)) {
|
||||
return resolveWorkspace(
|
||||
this.logger.deprecate(
|
||||
'The `workspace` option is deprecated and will be removed in the next major. To hide this warning, rename `workspace` option to `projects`.',
|
||||
)
|
||||
return resolveProjects(
|
||||
this,
|
||||
cliOptions,
|
||||
undefined,
|
||||
@ -448,9 +467,17 @@ export class Vitest {
|
||||
if (!project) {
|
||||
return []
|
||||
}
|
||||
return resolveBrowserWorkspace(this, new Set([project.name]), [project])
|
||||
return resolveBrowserProjects(this, new Set([project.name]), [project])
|
||||
}
|
||||
|
||||
const configFile = this.vite.config.configFile
|
||||
? resolve(this.vite.config.root, this.vite.config.configFile)
|
||||
: 'the root config file'
|
||||
|
||||
this.logger.deprecate(
|
||||
`The workspace file is deprecated and will be removed in the next major. Please, use the \`projects\` field in ${configFile} instead.`,
|
||||
)
|
||||
|
||||
const workspaceModule = await this.import<{
|
||||
default: ReturnType<typeof defineWorkspace>
|
||||
}>(workspaceConfigPath)
|
||||
@ -459,7 +486,7 @@ export class Vitest {
|
||||
throw new TypeError(`Workspace config file "${workspaceConfigPath}" must export a default array of project paths.`)
|
||||
}
|
||||
|
||||
return resolveWorkspace(
|
||||
return resolveProjects(
|
||||
this,
|
||||
cliOptions,
|
||||
workspaceConfigPath,
|
||||
|
||||
@ -110,6 +110,10 @@ export class Logger {
|
||||
printError(err, this.ctx, this, options)
|
||||
}
|
||||
|
||||
deprecate(message: string): void {
|
||||
this.log(c.bold(c.bgYellow(' DEPRECATED ')), c.yellow(message))
|
||||
}
|
||||
|
||||
clearHighlightCache(filename?: string): void {
|
||||
if (filename) {
|
||||
this._highlights.delete(filename)
|
||||
|
||||
@ -70,7 +70,7 @@ export function getFilePoolName(project: TestProject, file: string): Pool {
|
||||
for (const [glob, pool] of project.config.poolMatchGlobs) {
|
||||
if ((pool as Pool) === 'browser') {
|
||||
throw new Error(
|
||||
'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',
|
||||
'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',
|
||||
)
|
||||
}
|
||||
if (mm.isMatch(file, glob, { cwd: project.config.root })) {
|
||||
|
||||
@ -14,17 +14,17 @@ import { VitestFilteredOutProjectError } from '../errors'
|
||||
import { initializeProject, TestProject } from '../project'
|
||||
import { withLabel } from '../reporters/renderers/utils'
|
||||
|
||||
export async function resolveWorkspace(
|
||||
export async function resolveProjects(
|
||||
vitest: Vitest,
|
||||
cliOptions: UserConfig,
|
||||
workspaceConfigPath: string | undefined,
|
||||
workspaceDefinition: TestProjectConfiguration[],
|
||||
projectsDefinition: TestProjectConfiguration[],
|
||||
names: Set<string>,
|
||||
): Promise<TestProject[]> {
|
||||
const { configFiles, projectConfigs, nonConfigDirectories } = await resolveTestProjectConfigs(
|
||||
vitest,
|
||||
workspaceConfigPath,
|
||||
workspaceDefinition,
|
||||
projectsDefinition,
|
||||
)
|
||||
|
||||
// cli options that affect the project config,
|
||||
@ -109,7 +109,7 @@ export async function resolveWorkspace(
|
||||
[
|
||||
'No projects were found. Make sure your configuration is correct. ',
|
||||
vitest.config.project.length ? `The filter matched no projects: ${vitest.config.project.join(', ')}. ` : '',
|
||||
`The workspace: ${JSON.stringify(workspaceDefinition, null, 4)}.`,
|
||||
`The projects definition: ${JSON.stringify(projectsDefinition, null, 4)}.`,
|
||||
].join(''),
|
||||
)
|
||||
}
|
||||
@ -135,7 +135,7 @@ export async function resolveWorkspace(
|
||||
if (errors.length) {
|
||||
throw new AggregateError(
|
||||
errors,
|
||||
'Failed to initialize projects. There were errors during workspace setup. See below for more details.',
|
||||
'Failed to initialize projects. There were errors during projects setup. See below for more details.',
|
||||
)
|
||||
}
|
||||
|
||||
@ -157,16 +157,16 @@ export async function resolveWorkspace(
|
||||
' is not unique.',
|
||||
duplicate?.vite.config.configFile ? ` The project is already defined by "${relative(vitest.config.root, duplicate.vite.config.configFile)}".` : '',
|
||||
filesError,
|
||||
'All projects in a workspace should have unique names. Make sure your configuration is correct.',
|
||||
'All projects should have unique names. Make sure your configuration is correct.',
|
||||
].join(''))
|
||||
}
|
||||
names.add(name)
|
||||
}
|
||||
|
||||
return resolveBrowserWorkspace(vitest, names, resolvedProjects)
|
||||
return resolveBrowserProjects(vitest, names, resolvedProjects)
|
||||
}
|
||||
|
||||
export async function resolveBrowserWorkspace(
|
||||
export async function resolveBrowserProjects(
|
||||
vitest: Vitest,
|
||||
names: Set<string>,
|
||||
resolvedProjects: TestProject[],
|
||||
@ -184,7 +184,7 @@ export async function resolveBrowserWorkspace(
|
||||
browser,
|
||||
name: project.name ? `${project.name} (${browser})` : browser,
|
||||
})
|
||||
console.warn(
|
||||
vitest.logger.warn(
|
||||
withLabel(
|
||||
'yellow',
|
||||
'Vitest',
|
||||
@ -237,7 +237,7 @@ export async function resolveBrowserWorkspace(
|
||||
[
|
||||
`Cannot define a nested project for a ${browser} browser. The project name "${name}" 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.',
|
||||
'All projects should have unique names. Make sure your configuration is correct.',
|
||||
].join(''),
|
||||
)
|
||||
}
|
||||
@ -322,21 +322,21 @@ function cloneConfig(project: TestProject, { browser, ...config }: BrowserInstan
|
||||
async function resolveTestProjectConfigs(
|
||||
vitest: Vitest,
|
||||
workspaceConfigPath: string | undefined,
|
||||
workspaceDefinition: TestProjectConfiguration[],
|
||||
projectsDefinition: TestProjectConfiguration[],
|
||||
) {
|
||||
// project configurations that were specified directly
|
||||
const projectsOptions: (UserWorkspaceConfig & { extends?: true | string })[] = []
|
||||
|
||||
// custom config files that were specified directly or resolved from a directory
|
||||
const workspaceConfigFiles: string[] = []
|
||||
const projectsConfigFiles: string[] = []
|
||||
|
||||
// custom glob matches that should be resolved as directories or config files
|
||||
const workspaceGlobMatches: string[] = []
|
||||
const projectsGlobMatches: string[] = []
|
||||
|
||||
// directories that don't have a config file inside, but should be treated as projects
|
||||
const nonConfigProjectDirectories: string[] = []
|
||||
|
||||
for (const definition of workspaceDefinition) {
|
||||
for (const definition of projectsDefinition) {
|
||||
if (typeof definition === 'string') {
|
||||
const stringOption = definition.replace('<rootDir>', vitest.config.root)
|
||||
// if the string doesn't contain a glob, we can resolve it directly
|
||||
@ -345,23 +345,23 @@ async function resolveTestProjectConfigs(
|
||||
const file = resolve(vitest.config.root, stringOption)
|
||||
|
||||
if (!existsSync(file)) {
|
||||
const relativeWorkSpaceConfigPath = workspaceConfigPath
|
||||
const relativeWorkspaceConfigPath = workspaceConfigPath
|
||||
? relative(vitest.config.root, workspaceConfigPath)
|
||||
: undefined
|
||||
const note = workspaceConfigPath ? `Workspace config file "${relativeWorkSpaceConfigPath}"` : 'Inline workspace'
|
||||
const note = workspaceConfigPath ? `Workspace config file "${relativeWorkspaceConfigPath}"` : 'Projects definition'
|
||||
throw new Error(`${note} references a non-existing file or a directory: ${file}`)
|
||||
}
|
||||
|
||||
const stats = await fs.stat(file)
|
||||
// user can specify a config file directly
|
||||
if (stats.isFile()) {
|
||||
workspaceConfigFiles.push(file)
|
||||
projectsConfigFiles.push(file)
|
||||
}
|
||||
// user can specify a directory that should be used as a project
|
||||
else if (stats.isDirectory()) {
|
||||
const configFile = await resolveDirectoryConfig(file)
|
||||
if (configFile) {
|
||||
workspaceConfigFiles.push(configFile)
|
||||
projectsConfigFiles.push(configFile)
|
||||
}
|
||||
else {
|
||||
const directory = file[file.length - 1] === '/' ? file : `${file}/`
|
||||
@ -376,7 +376,7 @@ async function resolveTestProjectConfigs(
|
||||
// if the string is a glob pattern, resolve it later
|
||||
// ['./packages/*']
|
||||
else {
|
||||
workspaceGlobMatches.push(stringOption)
|
||||
projectsGlobMatches.push(stringOption)
|
||||
}
|
||||
}
|
||||
// if the config is inlined, we can resolve it immediately
|
||||
@ -394,7 +394,7 @@ async function resolveTestProjectConfigs(
|
||||
}
|
||||
}
|
||||
|
||||
if (workspaceGlobMatches.length) {
|
||||
if (projectsGlobMatches.length) {
|
||||
const globOptions: GlobOptions = {
|
||||
absolute: true,
|
||||
dot: true,
|
||||
@ -410,27 +410,27 @@ async function resolveTestProjectConfigs(
|
||||
],
|
||||
}
|
||||
|
||||
const workspacesFs = await glob(workspaceGlobMatches, globOptions)
|
||||
const projectsFs = await glob(projectsGlobMatches, globOptions)
|
||||
|
||||
await Promise.all(workspacesFs.map(async (path) => {
|
||||
await Promise.all(projectsFs.map(async (path) => {
|
||||
// directories are allowed with a glob like `packages/*`
|
||||
// in this case every directory is treated as a project
|
||||
if (path.endsWith('/')) {
|
||||
const configFile = await resolveDirectoryConfig(path)
|
||||
if (configFile) {
|
||||
workspaceConfigFiles.push(configFile)
|
||||
projectsConfigFiles.push(configFile)
|
||||
}
|
||||
else {
|
||||
nonConfigProjectDirectories.push(path)
|
||||
}
|
||||
}
|
||||
else {
|
||||
workspaceConfigFiles.push(path)
|
||||
projectsConfigFiles.push(path)
|
||||
}
|
||||
}))
|
||||
}
|
||||
|
||||
const projectConfigFiles = Array.from(new Set(workspaceConfigFiles))
|
||||
const projectConfigFiles = Array.from(new Set(projectsConfigFiles))
|
||||
|
||||
return {
|
||||
projectConfigs: projectsOptions,
|
||||
@ -1,6 +1,5 @@
|
||||
import type { File } from '@vitest/runner'
|
||||
import type { Vitest } from '../core'
|
||||
import c from 'tinyrainbow'
|
||||
import { BaseReporter } from './base'
|
||||
|
||||
export class BasicReporter extends BaseReporter {
|
||||
@ -12,11 +11,11 @@ export class BasicReporter extends BaseReporter {
|
||||
onInit(ctx: Vitest): void {
|
||||
super.onInit(ctx)
|
||||
|
||||
ctx.logger.log(c.bold(c.bgYellow(' DEPRECATED ')), c.yellow(
|
||||
ctx.logger.deprecate(
|
||||
`'basic' reporter is deprecated and will be removed in Vitest v3.\n`
|
||||
+ `Remove 'basic' from 'reporters' option. To match 'basic' reporter 100%, use configuration:\n${
|
||||
JSON.stringify({ test: { reporters: [['default', { summary: false }]] } }, null, 2)}`,
|
||||
))
|
||||
)
|
||||
}
|
||||
|
||||
reportSummary(files: File[], errors: unknown[]): void {
|
||||
|
||||
@ -320,7 +320,7 @@ export interface InlineConfig {
|
||||
*
|
||||
* Format: [glob, environment-name]
|
||||
*
|
||||
* @deprecated use [`workspace`](https://vitest.dev/config/#environmentmatchglobs) instead
|
||||
* @deprecated use [`projects`](https://vitest.dev/config/#projects) instead
|
||||
* @default []
|
||||
* @example [
|
||||
* // all tests in tests/dom will run in jsdom
|
||||
@ -377,7 +377,7 @@ export interface InlineConfig {
|
||||
*
|
||||
* Format: [glob, pool-name]
|
||||
*
|
||||
* @deprecated use [`workspace`](https://vitest.dev/config/#poolmatchglobs) instead
|
||||
* @deprecated use [`projects`](https://vitest.dev/config/#projects) instead
|
||||
* @default []
|
||||
* @example [
|
||||
* // all tests in "forks" directory will run using "poolOptions.forks" API
|
||||
@ -388,8 +388,14 @@ export interface InlineConfig {
|
||||
*/
|
||||
poolMatchGlobs?: [string, Exclude<Pool, 'browser'>][]
|
||||
|
||||
/**
|
||||
* Options for projects
|
||||
*/
|
||||
projects?: TestProjectConfiguration[]
|
||||
|
||||
/**
|
||||
* Path to a workspace configuration file
|
||||
* @deprecated use `projects` instead
|
||||
*/
|
||||
workspace?: string | TestProjectConfiguration[]
|
||||
|
||||
|
||||
@ -66,6 +66,9 @@ export function defineProject(config: UserProjectConfigExport): UserProjectConfi
|
||||
return config
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated use the `projects` field in the root config instead
|
||||
*/
|
||||
export function defineWorkspace(config: TestProjectConfiguration[]): TestProjectConfiguration[] {
|
||||
return config
|
||||
}
|
||||
|
||||
76
pnpm-lock.yaml
generated
76
pnpm-lock.yaml
generated
@ -382,25 +382,7 @@ importers:
|
||||
specifier: workspace:*
|
||||
version: link:../../packages/vitest
|
||||
|
||||
examples/typecheck:
|
||||
devDependencies:
|
||||
'@types/node':
|
||||
specifier: ^20.17.30
|
||||
version: 20.17.30
|
||||
'@vitest/ui':
|
||||
specifier: workspace:*
|
||||
version: link:../../packages/ui
|
||||
typescript:
|
||||
specifier: ^5.8.3
|
||||
version: 5.8.3
|
||||
vite:
|
||||
specifier: ^6.2.0
|
||||
version: 6.2.0(@types/node@20.17.30)(jiti@2.4.2)(terser@5.36.0)(tsx@4.19.3)(yaml@2.7.0)
|
||||
vitest:
|
||||
specifier: workspace:*
|
||||
version: link:../../packages/vitest
|
||||
|
||||
examples/workspace:
|
||||
examples/projects:
|
||||
devDependencies:
|
||||
'@testing-library/jest-dom':
|
||||
specifier: ^6.6.3
|
||||
@ -442,6 +424,24 @@ importers:
|
||||
specifier: workspace:*
|
||||
version: link:../../packages/vitest
|
||||
|
||||
examples/typecheck:
|
||||
devDependencies:
|
||||
'@types/node':
|
||||
specifier: ^20.17.30
|
||||
version: 20.17.30
|
||||
'@vitest/ui':
|
||||
specifier: workspace:*
|
||||
version: link:../../packages/ui
|
||||
typescript:
|
||||
specifier: ^5.8.3
|
||||
version: 5.8.3
|
||||
vite:
|
||||
specifier: ^6.2.0
|
||||
version: 6.2.0(@types/node@20.17.30)(jiti@2.4.2)(terser@5.36.0)(tsx@4.19.3)(yaml@2.7.0)
|
||||
vitest:
|
||||
specifier: workspace:*
|
||||
version: link:../../packages/vitest
|
||||
|
||||
packages/browser:
|
||||
dependencies:
|
||||
'@testing-library/dom':
|
||||
@ -5476,9 +5476,6 @@ packages:
|
||||
resolution: {integrity: sha512-Fv96DCsdOgB6mdGl67MT5JaTNKRzrzill5OH5s8bjYJXVlcXyPYGyPsUkWyGV5p1TXI5esYIYMMeDJL0hEIwaA==}
|
||||
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
|
||||
|
||||
decimal.js@10.4.3:
|
||||
resolution: {integrity: sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA==}
|
||||
|
||||
decimal.js@10.5.0:
|
||||
resolution: {integrity: sha512-8vDa8Qxvr/+d94hSh5P3IJwI5t8/c0KsMp+g8bNw9cY2icONa5aPfvKeieW1WlG0WQYwwhJ7mjui2xtiePQSXw==}
|
||||
|
||||
@ -8768,10 +8765,6 @@ packages:
|
||||
tr46@1.0.1:
|
||||
resolution: {integrity: sha512-dTpowEjclQ7Kgx5SdBkqRzVhERQXov8/l9Ft9dVM9fmg0W0KQSVaXX9T4i6twCPNtYiZM53lpSSUAwJbFPOHxA==}
|
||||
|
||||
tr46@5.0.0:
|
||||
resolution: {integrity: sha512-tk2G5R2KRwBd+ZN0zaEXpmzdKyOYksXwywulIX95MBODjSzMIuQnQ3m8JxgbhnL1LeVo7lqQKsYa1O3Htl7K5g==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
tr46@5.1.0:
|
||||
resolution: {integrity: sha512-IUWnUK7ADYR5Sl1fZlO1INDUhVhatWl7BtJWsIhwJ0UAK7ilzzIa8uIqOO/aYVWHZPJkKbEL+362wrzoeRF7bw==}
|
||||
engines: {node: '>=18'}
|
||||
@ -9342,10 +9335,6 @@ packages:
|
||||
resolution: {integrity: sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
whatwg-url@14.1.0:
|
||||
resolution: {integrity: sha512-jlf/foYIKywAt3x/XWKZ/3rz8OSJPiWktjmk891alJUEjiVxKX9LEO92qH3hv4aJ0mN3MWPvGMCy8jQi95xK4w==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
whatwg-url@14.2.0:
|
||||
resolution: {integrity: sha512-De72GdQZzNTUBBChsXueQUnPKDkg/5A5zp7pFDuQAj5UFoENpiACU0wlCvzpAGnTkj++ihpKwKyYewn/XNUbKw==}
|
||||
engines: {node: '>=18'}
|
||||
@ -11891,24 +11880,24 @@ snapshots:
|
||||
|
||||
'@types/babel__core@7.20.5':
|
||||
dependencies:
|
||||
'@babel/parser': 7.26.2
|
||||
'@babel/types': 7.26.0
|
||||
'@babel/parser': 7.27.0
|
||||
'@babel/types': 7.27.0
|
||||
'@types/babel__generator': 7.6.6
|
||||
'@types/babel__template': 7.4.3
|
||||
'@types/babel__traverse': 7.20.3
|
||||
|
||||
'@types/babel__generator@7.6.6':
|
||||
dependencies:
|
||||
'@babel/types': 7.26.0
|
||||
'@babel/types': 7.27.0
|
||||
|
||||
'@types/babel__template@7.4.3':
|
||||
dependencies:
|
||||
'@babel/parser': 7.26.2
|
||||
'@babel/types': 7.26.0
|
||||
'@babel/parser': 7.27.0
|
||||
'@babel/types': 7.27.0
|
||||
|
||||
'@types/babel__traverse@7.20.3':
|
||||
dependencies:
|
||||
'@babel/types': 7.26.0
|
||||
'@babel/types': 7.27.0
|
||||
|
||||
'@types/braces@3.0.1': {}
|
||||
|
||||
@ -13652,8 +13641,6 @@ snapshots:
|
||||
|
||||
decamelize@6.0.0: {}
|
||||
|
||||
decimal.js@10.4.3: {}
|
||||
|
||||
decimal.js@10.5.0: {}
|
||||
|
||||
decode-bmp@0.2.1:
|
||||
@ -15435,7 +15422,7 @@ snapshots:
|
||||
dependencies:
|
||||
cssstyle: 4.2.1
|
||||
data-urls: 5.0.0
|
||||
decimal.js: 10.4.3
|
||||
decimal.js: 10.5.0
|
||||
form-data: 4.0.1
|
||||
html-encoding-sniffer: 4.0.0
|
||||
http-proxy-agent: 7.0.2
|
||||
@ -15451,7 +15438,7 @@ snapshots:
|
||||
webidl-conversions: 7.0.0
|
||||
whatwg-encoding: 3.1.1
|
||||
whatwg-mimetype: 4.0.0
|
||||
whatwg-url: 14.1.0
|
||||
whatwg-url: 14.2.0
|
||||
ws: 8.18.1
|
||||
xml-name-validator: 5.0.0
|
||||
transitivePeerDependencies:
|
||||
@ -17679,10 +17666,6 @@ snapshots:
|
||||
dependencies:
|
||||
punycode: 2.3.1
|
||||
|
||||
tr46@5.0.0:
|
||||
dependencies:
|
||||
punycode: 2.3.1
|
||||
|
||||
tr46@5.1.0:
|
||||
dependencies:
|
||||
punycode: 2.3.1
|
||||
@ -18389,11 +18372,6 @@ snapshots:
|
||||
|
||||
whatwg-mimetype@4.0.0: {}
|
||||
|
||||
whatwg-url@14.1.0:
|
||||
dependencies:
|
||||
tr46: 5.0.0
|
||||
webidl-conversions: 7.0.0
|
||||
|
||||
whatwg-url@14.2.0:
|
||||
dependencies:
|
||||
tr46: 5.1.0
|
||||
|
||||
@ -5,7 +5,7 @@ export default defineConfig({
|
||||
test: {
|
||||
watch: false,
|
||||
|
||||
workspace: [
|
||||
projects: [
|
||||
{
|
||||
test: {
|
||||
name: "Browser in workspace",
|
||||
|
||||
@ -13,10 +13,10 @@ it('can manipulate files', async () => {
|
||||
catch (err) {
|
||||
expect(err.message).toMatch(`ENOENT: no such file or directory, open`)
|
||||
if (server.platform === 'win32') {
|
||||
expect(err.message).toMatch('test\\browser\\test\\test.txt')
|
||||
expect(err.message).toMatch('test\\browser\\test.txt')
|
||||
}
|
||||
else {
|
||||
expect(err.message).toMatch('test/browser/test/test.txt')
|
||||
expect(err.message).toMatch('test/browser/test.txt')
|
||||
}
|
||||
}
|
||||
|
||||
@ -34,10 +34,10 @@ it('can manipulate files', async () => {
|
||||
catch (err) {
|
||||
expect(err.message).toMatch(`ENOENT: no such file or directory, open`)
|
||||
if (server.platform === 'win32') {
|
||||
expect(err.message).toMatch('test\\browser\\test\\test.txt')
|
||||
expect(err.message).toMatch('test\\browser\\test.txt')
|
||||
}
|
||||
else {
|
||||
expect(err.message).toMatch('test/browser/test/test.txt')
|
||||
expect(err.message).toMatch('test/browser/test.txt')
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
37
test/cli/fixtures/browser-multiple/vitest.config.ts
Normal file
37
test/cli/fixtures/browser-multiple/vitest.config.ts
Normal file
@ -0,0 +1,37 @@
|
||||
import { resolve } from 'pathe';
|
||||
import { defineConfig, defineWorkspace } from 'vitest/config';
|
||||
|
||||
export default defineConfig({
|
||||
test: {
|
||||
projects: [
|
||||
{
|
||||
cacheDir: resolve(import.meta.dirname, 'basic-1'),
|
||||
test: {
|
||||
name: 'basic-1',
|
||||
dir: import.meta.dirname,
|
||||
include: ['./basic.test.js'],
|
||||
browser: {
|
||||
enabled: true,
|
||||
instances: [{ browser: 'chromium' }],
|
||||
provider: 'playwright',
|
||||
headless: true,
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
cacheDir: resolve(import.meta.dirname, 'basic-2'),
|
||||
test: {
|
||||
name: 'basic-2',
|
||||
dir: import.meta.dirname,
|
||||
include: ['./basic.test.js'],
|
||||
browser: {
|
||||
enabled: true,
|
||||
instances: [{ browser: 'chromium' }],
|
||||
provider: 'playwright',
|
||||
headless: true,
|
||||
}
|
||||
}
|
||||
},
|
||||
],
|
||||
},
|
||||
})
|
||||
@ -1,33 +0,0 @@
|
||||
import { resolve } from 'pathe';
|
||||
import { defineWorkspace } from 'vitest/config';
|
||||
|
||||
export default defineWorkspace([
|
||||
{
|
||||
cacheDir: resolve(import.meta.dirname, 'basic-1'),
|
||||
test: {
|
||||
name: 'basic-1',
|
||||
dir: import.meta.dirname,
|
||||
include: ['./basic.test.js'],
|
||||
browser: {
|
||||
enabled: true,
|
||||
instances: [{ browser: 'chromium' }],
|
||||
provider: 'playwright',
|
||||
headless: true,
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
cacheDir: resolve(import.meta.dirname, 'basic-2'),
|
||||
test: {
|
||||
name: 'basic-2',
|
||||
dir: import.meta.dirname,
|
||||
include: ['./basic.test.js'],
|
||||
browser: {
|
||||
enabled: true,
|
||||
instances: [{ browser: 'chromium' }],
|
||||
provider: 'playwright',
|
||||
headless: true,
|
||||
}
|
||||
}
|
||||
},
|
||||
])
|
||||
@ -3,7 +3,7 @@ import "@vitest/test-dep-linked/ts";
|
||||
|
||||
export default defineConfig({
|
||||
test: {
|
||||
workspace: [
|
||||
projects: [
|
||||
"browser/vitest.config.ts",
|
||||
"node/vitest.config.ts",
|
||||
],
|
||||
|
||||
@ -8,7 +8,7 @@ export default defineConfig({
|
||||
array: [1, 2, 3],
|
||||
},
|
||||
},
|
||||
workspace: [
|
||||
projects: [
|
||||
{
|
||||
extends: true,
|
||||
test: {
|
||||
|
||||
@ -1 +1,9 @@
|
||||
export default {}
|
||||
import { defineConfig } from 'vitest/config'
|
||||
|
||||
export default defineConfig({
|
||||
test: {
|
||||
projects: [
|
||||
"packages/*/vitest.config.mjs",
|
||||
]
|
||||
},
|
||||
})
|
||||
|
||||
@ -1,3 +0,0 @@
|
||||
export default [
|
||||
"packages/*/vitest.config.mjs",
|
||||
];
|
||||
@ -6,14 +6,12 @@ import { runVitest } from '../../test-utils'
|
||||
|
||||
it('automatically assigns the port', async () => {
|
||||
const root = resolve(import.meta.dirname, '../fixtures/browser-multiple')
|
||||
const workspace = resolve(import.meta.dirname, '../fixtures/browser-multiple/vitest.workspace.ts')
|
||||
const spy = vi.spyOn(console, 'log')
|
||||
onTestFinished(() => spy.mockRestore())
|
||||
let ctx: Vitest
|
||||
let urls: (string | undefined)[] = []
|
||||
const { stderr } = await runVitest({
|
||||
root,
|
||||
workspace,
|
||||
dir: root,
|
||||
watch: false,
|
||||
reporters: [
|
||||
|
||||
@ -1,5 +1,25 @@
|
||||
import { defineConfig } from 'vitest/config'
|
||||
import { resolve } from 'node:path'
|
||||
import { fileURLToPath } from 'node:url'
|
||||
|
||||
const __filename = fileURLToPath(import.meta.url)
|
||||
const __dirname = resolve(__filename, '..')
|
||||
|
||||
export default defineConfig({
|
||||
test: {},
|
||||
test: {
|
||||
projects: [
|
||||
{
|
||||
test: {
|
||||
name: 'Project #1',
|
||||
root: resolve(__dirname, './project'),
|
||||
},
|
||||
},
|
||||
{
|
||||
test: {
|
||||
name: 'Project #2',
|
||||
root: resolve(__dirname, './project'),
|
||||
},
|
||||
},
|
||||
]
|
||||
},
|
||||
})
|
||||
|
||||
@ -1,21 +0,0 @@
|
||||
import { resolve } from 'node:path'
|
||||
import { fileURLToPath } from 'node:url'
|
||||
import { defineWorkspace } from 'vitest/config'
|
||||
|
||||
const __filename = fileURLToPath(import.meta.url)
|
||||
const __dirname = resolve(__filename, '..')
|
||||
|
||||
export default defineWorkspace([
|
||||
{
|
||||
test: {
|
||||
name: 'Project #1',
|
||||
root: resolve(__dirname, './project'),
|
||||
},
|
||||
},
|
||||
{
|
||||
test: {
|
||||
name: 'Project #2',
|
||||
root: resolve(__dirname, './project'),
|
||||
},
|
||||
},
|
||||
])
|
||||
@ -2,7 +2,7 @@ import { defineConfig } from 'vitest/config';
|
||||
|
||||
export default defineConfig({
|
||||
test: {
|
||||
workspace: [
|
||||
projects: [
|
||||
{
|
||||
test: {
|
||||
name: 'unit',
|
||||
|
||||
@ -1,3 +1,9 @@
|
||||
import { defineConfig } from "vitest/config";
|
||||
|
||||
export default defineConfig({})
|
||||
export default defineConfig({
|
||||
test: {
|
||||
projects: [
|
||||
'packages/*'
|
||||
]
|
||||
}
|
||||
})
|
||||
|
||||
@ -1,3 +0,0 @@
|
||||
export default [
|
||||
'packages/*'
|
||||
]
|
||||
@ -11,5 +11,21 @@ export default defineConfig({
|
||||
basename(path) + extension
|
||||
);
|
||||
},
|
||||
projects: [
|
||||
{
|
||||
extends: './vitest.config.ts',
|
||||
test: {
|
||||
name: 'project1',
|
||||
root: import.meta.dirname,
|
||||
}
|
||||
},
|
||||
{
|
||||
extends: './vitest.config.ts',
|
||||
test: {
|
||||
name: 'project2',
|
||||
root: import.meta.dirname,
|
||||
}
|
||||
}
|
||||
],
|
||||
},
|
||||
});
|
||||
|
||||
@ -1,18 +0,0 @@
|
||||
import { defineWorkspace } from 'vitest/config'
|
||||
|
||||
export default defineWorkspace([
|
||||
{
|
||||
extends: './vitest.config.ts',
|
||||
test: {
|
||||
name: 'project1',
|
||||
root: import.meta.dirname,
|
||||
}
|
||||
},
|
||||
{
|
||||
extends: './vitest.config.ts',
|
||||
test: {
|
||||
name: 'project2',
|
||||
root: import.meta.dirname,
|
||||
}
|
||||
}
|
||||
])
|
||||
7
test/config/fixtures/workspace-flags/vitest.config.js
Normal file
7
test/config/fixtures/workspace-flags/vitest.config.js
Normal file
@ -0,0 +1,7 @@
|
||||
import { defineConfig } from 'vitest/config'
|
||||
|
||||
export default defineConfig({
|
||||
test: {
|
||||
projects: ['projects'],
|
||||
},
|
||||
})
|
||||
@ -1 +0,0 @@
|
||||
export default ['projects']
|
||||
@ -17,7 +17,7 @@ export default defineConfig({
|
||||
},
|
||||
],
|
||||
test: {
|
||||
workspace: [
|
||||
projects: [
|
||||
{
|
||||
extends: true,
|
||||
test: {
|
||||
|
||||
@ -0,0 +1,11 @@
|
||||
import { defineConfig } from 'vitest/config'
|
||||
import depAsJs from "./dep.js"
|
||||
|
||||
export default defineConfig({
|
||||
test: {
|
||||
projects: [
|
||||
"./packages/*",
|
||||
...depAsJs,
|
||||
],
|
||||
}
|
||||
})
|
||||
@ -1,6 +0,0 @@
|
||||
import depAsJs from "./dep.js"
|
||||
|
||||
export default [
|
||||
"./packages/*",
|
||||
...depAsJs,
|
||||
]
|
||||
@ -0,0 +1,10 @@
|
||||
import { defineConfig } from 'vitest/config'
|
||||
|
||||
export default defineConfig({
|
||||
test: {
|
||||
projects: [
|
||||
'./vitest1.config.js',
|
||||
'./vitest2.config.js',
|
||||
],
|
||||
}
|
||||
})
|
||||
@ -1,6 +0,0 @@
|
||||
import { defineWorkspace } from 'vitest/config'
|
||||
|
||||
export default defineWorkspace([
|
||||
'./vitest1.config.js',
|
||||
'./vitest2.config.js',
|
||||
])
|
||||
@ -0,0 +1,18 @@
|
||||
import { defineConfig } from 'vitest/config'
|
||||
|
||||
export default defineConfig({
|
||||
test: {
|
||||
projects: [
|
||||
{
|
||||
test: {
|
||||
name: 'test',
|
||||
},
|
||||
},
|
||||
{
|
||||
test: {
|
||||
name: 'test',
|
||||
},
|
||||
},
|
||||
]
|
||||
}
|
||||
})
|
||||
@ -1,14 +0,0 @@
|
||||
import { defineWorkspace } from 'vitest/config'
|
||||
|
||||
export default defineWorkspace([
|
||||
{
|
||||
test: {
|
||||
name: 'test',
|
||||
},
|
||||
},
|
||||
{
|
||||
test: {
|
||||
name: 'test',
|
||||
},
|
||||
},
|
||||
])
|
||||
@ -0,0 +1,9 @@
|
||||
import { defineConfig } from 'vitest/config'
|
||||
|
||||
export default defineConfig({
|
||||
test: {
|
||||
projects: [
|
||||
'./vitest.config.js'
|
||||
],
|
||||
},
|
||||
})
|
||||
@ -1,5 +0,0 @@
|
||||
import { defineWorkspace } from 'vitest/config'
|
||||
|
||||
export default defineWorkspace([
|
||||
'./vitest.config.js'
|
||||
])
|
||||
10
test/config/fixtures/workspace/negated/vitest.config.ts
Normal file
10
test/config/fixtures/workspace/negated/vitest.config.ts
Normal file
@ -0,0 +1,10 @@
|
||||
import { defineConfig } from 'vitest/config';
|
||||
|
||||
export default defineConfig({
|
||||
test: {
|
||||
projects: [
|
||||
'packages/*',
|
||||
'!packages/b'
|
||||
],
|
||||
},
|
||||
})
|
||||
@ -1,4 +0,0 @@
|
||||
export default [
|
||||
'packages/*',
|
||||
'!packages/b'
|
||||
]
|
||||
@ -0,0 +1,9 @@
|
||||
import { defineConfig } from 'vitest/config'
|
||||
|
||||
export default defineConfig({
|
||||
test: {
|
||||
projects: [
|
||||
'./test/*.config.*.ts',
|
||||
],
|
||||
},
|
||||
})
|
||||
@ -1,3 +0,0 @@
|
||||
export default [
|
||||
'./test/*.config.*.ts'
|
||||
]
|
||||
@ -0,0 +1,10 @@
|
||||
import { defineConfig } from 'vitest/config';
|
||||
|
||||
export default defineConfig({
|
||||
test: {
|
||||
projects: [
|
||||
'projects/*',
|
||||
'apps/*'
|
||||
],
|
||||
},
|
||||
})
|
||||
@ -1,4 +0,0 @@
|
||||
export default [
|
||||
'projects/*',
|
||||
'apps/*'
|
||||
]
|
||||
@ -68,7 +68,7 @@ test('filters projects with a wildcard', async () => {
|
||||
|
||||
test('assignes names as browsers in a custom project', async () => {
|
||||
const { projects } = await vitest({
|
||||
workspace: [
|
||||
projects: [
|
||||
{
|
||||
test: {
|
||||
name: 'custom',
|
||||
@ -207,7 +207,7 @@ test('coverage provider v8 works correctly in browser mode if instances are filt
|
||||
test('coverage provider v8 works correctly in workspaced browser mode if instances are filtered', async () => {
|
||||
const { projects } = await vitest({
|
||||
project: 'browser (chromium)',
|
||||
workspace: [
|
||||
projects: [
|
||||
{
|
||||
test: {
|
||||
name: 'browser',
|
||||
@ -236,7 +236,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',
|
||||
workspace: [
|
||||
projects: [
|
||||
{
|
||||
test: {
|
||||
name: 'myproject',
|
||||
@ -275,7 +275,7 @@ test('can enable browser-cli options for multi-project workspace', async () => {
|
||||
},
|
||||
},
|
||||
{
|
||||
workspace: [
|
||||
projects: [
|
||||
{
|
||||
test: {
|
||||
name: 'unit',
|
||||
@ -373,7 +373,7 @@ function getCliConfig(options: UserConfig, cli: string[], fs: TestFsStructure =
|
||||
describe('[e2e] workspace configs are affected by the CLI options', () => {
|
||||
test('UI is not enabled by default in headless config', async () => {
|
||||
const vitest = await getCliConfig({
|
||||
workspace: [
|
||||
projects: [
|
||||
{
|
||||
test: {
|
||||
name: 'unit',
|
||||
@ -426,7 +426,7 @@ describe('[e2e] workspace configs are affected by the CLI options', () => {
|
||||
|
||||
test('CLI options correctly override inline workspace options', async () => {
|
||||
const vitest = await getCliConfig({
|
||||
workspace: [
|
||||
projects: [
|
||||
{
|
||||
test: {
|
||||
name: 'unit',
|
||||
@ -481,7 +481,7 @@ describe('[e2e] workspace configs are affected by the CLI options', () => {
|
||||
test('CLI options correctly override config file workspace options', async () => {
|
||||
const vitest = await getCliConfig(
|
||||
{
|
||||
workspace: [
|
||||
projects: [
|
||||
{
|
||||
test: {
|
||||
name: 'unit',
|
||||
|
||||
@ -30,7 +30,7 @@ test('can change global configuration', async () => {
|
||||
|
||||
test('can change the project and the global configurations', async () => {
|
||||
const v = await vitest({}, {
|
||||
workspace: [
|
||||
projects: [
|
||||
{
|
||||
plugins: [
|
||||
{
|
||||
@ -59,7 +59,7 @@ test('plugin is not called if the project is filtered out', async () => {
|
||||
const { projects } = await vitest({
|
||||
project: 'project-2',
|
||||
}, {
|
||||
workspace: [
|
||||
projects: [
|
||||
{
|
||||
test: {
|
||||
name: 'project-1',
|
||||
@ -113,7 +113,7 @@ test('injected plugin is filtered by the --project filter', async () => {
|
||||
let newWorkspace: TestProject[] = []
|
||||
const { projects } = await vitest({
|
||||
project: 'project-1',
|
||||
workspace: [
|
||||
projects: [
|
||||
{
|
||||
test: {
|
||||
name: 'project-1',
|
||||
@ -143,7 +143,7 @@ test('injected plugin is not filtered by the --project filter when it\'s overrid
|
||||
let newWorkspace: TestProject[] = []
|
||||
const { projects } = await vitest({
|
||||
project: 'project-1',
|
||||
workspace: [
|
||||
projects: [
|
||||
{
|
||||
test: {
|
||||
name: 'project-1',
|
||||
@ -174,7 +174,7 @@ test('injected plugin is not filtered by the --project filter when it\'s overrid
|
||||
|
||||
test('adding a plugin with existing name throws and error', async () => {
|
||||
await expect(() => vitest({
|
||||
workspace: [
|
||||
projects: [
|
||||
{
|
||||
test: {
|
||||
name: 'project-1',
|
||||
@ -194,10 +194,10 @@ test('adding a plugin with existing name throws and error', async () => {
|
||||
},
|
||||
],
|
||||
}),
|
||||
).rejects.toThrowError('Project name "project-1" is not unique. All projects in a workspace should have unique names. Make sure your configuration is correct.')
|
||||
).rejects.toThrowError('Project name "project-1" is not unique. All projects should have unique names. Make sure your configuration is correct.')
|
||||
|
||||
await expect(() => vitest({
|
||||
workspace: [
|
||||
projects: [
|
||||
{
|
||||
plugins: [
|
||||
{
|
||||
@ -219,10 +219,10 @@ test('adding a plugin with existing name throws and error', async () => {
|
||||
},
|
||||
],
|
||||
}),
|
||||
).rejects.toThrowError('Project name "project-1" is not unique. All projects in a workspace should have unique names. Make sure your configuration is correct.')
|
||||
).rejects.toThrowError('Project name "project-1" is not unique. All projects should have unique names. Make sure your configuration is correct.')
|
||||
|
||||
await expect(() => vitest({
|
||||
workspace: [
|
||||
projects: [
|
||||
{
|
||||
plugins: [
|
||||
{
|
||||
@ -246,5 +246,5 @@ test('adding a plugin with existing name throws and error', async () => {
|
||||
},
|
||||
],
|
||||
}),
|
||||
).rejects.toThrowError('Project name "project-1" is not unique. All projects in a workspace should have unique names. Make sure your configuration is correct.')
|
||||
).rejects.toThrowError('Project name "project-1" is not unique. All projects should have unique names. Make sure your configuration is correct.')
|
||||
})
|
||||
|
||||
@ -476,7 +476,7 @@ test('browser.instances throws an error if no custom name is provided', async ()
|
||||
},
|
||||
},
|
||||
})
|
||||
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.')
|
||||
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.')
|
||||
})
|
||||
|
||||
test('browser.instances throws an error if no custom name is provided, but the config name is inherited', async () => {
|
||||
@ -491,12 +491,12 @@ test('browser.instances throws an error if no custom name is provided, but the c
|
||||
],
|
||||
},
|
||||
})
|
||||
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.')
|
||||
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.')
|
||||
})
|
||||
|
||||
test('throws an error if name conflicts with a workspace name', async () => {
|
||||
const { stderr } = await runVitest({
|
||||
workspace: [
|
||||
projects: [
|
||||
{ test: { name: '1 (firefox)' } },
|
||||
{
|
||||
test: {
|
||||
@ -511,7 +511,7 @@ test('throws an error if name conflicts with a workspace name', async () => {
|
||||
},
|
||||
],
|
||||
})
|
||||
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.')
|
||||
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.')
|
||||
})
|
||||
|
||||
test('throws an error if several browsers are headed in nonTTY mode', async () => {
|
||||
|
||||
@ -15,7 +15,6 @@ it('correctly runs workspace tests when workspace config path is specified', asy
|
||||
it('runs the workspace if there are several vitest config files', async () => {
|
||||
const { stderr, stdout } = await runVitest({
|
||||
root: 'fixtures/workspace/several-configs',
|
||||
workspace: './fixtures/workspace/several-configs/vitest.workspace.ts',
|
||||
})
|
||||
expect(stderr).toBe('')
|
||||
expect(stdout).toContain('workspace/several-configs')
|
||||
@ -28,7 +27,6 @@ it('runs the workspace if there are several vitest config files', async () => {
|
||||
it('correctly resolves workspace projects with a several folder globs', async () => {
|
||||
const { stderr, stdout } = await runVitest({
|
||||
root: 'fixtures/workspace/several-folders',
|
||||
workspace: './fixtures/workspace/several-folders/vitest.workspace.ts',
|
||||
})
|
||||
expect(stderr).toBe('')
|
||||
expect(stdout).toContain('test - a')
|
||||
@ -38,7 +36,6 @@ it('correctly resolves workspace projects with a several folder globs', async ()
|
||||
it('supports glob negation pattern', async () => {
|
||||
const { stderr, stdout } = await runVitest({
|
||||
root: 'fixtures/workspace/negated',
|
||||
workspace: './fixtures/workspace/negated/vitest.workspace.ts',
|
||||
})
|
||||
expect(stderr).toBe('')
|
||||
expect(stdout).toContain('test - a')
|
||||
@ -49,7 +46,6 @@ it('supports glob negation pattern', async () => {
|
||||
it('fails if project names are identical with a nice error message', async () => {
|
||||
const { stderr } = await runVitest({
|
||||
root: 'fixtures/workspace/invalid-duplicate-configs',
|
||||
workspace: './fixtures/workspace/invalid-duplicate-configs/vitest.workspace.ts',
|
||||
}, [], 'test', {}, { fails: true })
|
||||
expect(stderr).toContain(
|
||||
`Project name "test" from "vitest2.config.js" is not unique. The project is already defined by "vitest1.config.js".
|
||||
@ -58,34 +54,31 @@ Your config matched these files:
|
||||
- vitest1.config.js
|
||||
- vitest2.config.js
|
||||
|
||||
All projects in a workspace should have unique names. Make sure your configuration is correct.`,
|
||||
All projects should have unique names. Make sure your configuration is correct.`,
|
||||
)
|
||||
})
|
||||
|
||||
it('fails if project names are identical inside the inline config', async () => {
|
||||
const { stderr } = await runVitest({
|
||||
root: 'fixtures/workspace/invalid-duplicate-inline',
|
||||
workspace: './fixtures/workspace/invalid-duplicate-inline/vitest.workspace.ts',
|
||||
}, [], 'test', {}, { fails: true })
|
||||
expect(stderr).toContain(
|
||||
'Project name "test" is not unique. All projects in a workspace should have unique names. Make sure your configuration is correct.',
|
||||
'Project name "test" is not unique. All projects should have unique names. Make sure your configuration is correct.',
|
||||
)
|
||||
})
|
||||
|
||||
it('fails if referenced file doesnt exist', async () => {
|
||||
const { stderr } = await runVitest({
|
||||
root: 'fixtures/workspace/invalid-non-existing-config',
|
||||
workspace: './fixtures/workspace/invalid-non-existing-config/vitest.workspace.ts',
|
||||
}, [], 'test', {}, { fails: true })
|
||||
expect(stderr).toContain(
|
||||
`Workspace config file "vitest.workspace.ts" references a non-existing file or a directory: ${resolve('fixtures/workspace/invalid-non-existing-config/vitest.config.js')}`,
|
||||
`Projects definition references a non-existing file or a directory: ${resolve('fixtures/workspace/invalid-non-existing-config/vitest.config.js')}`,
|
||||
)
|
||||
})
|
||||
|
||||
it('vite import analysis is applied when loading workspace config', async () => {
|
||||
const { stderr, stdout } = await runVitest({
|
||||
root: 'fixtures/workspace/config-import-analysis',
|
||||
workspace: './fixtures/workspace/config-import-analysis/vitest.workspace.ts',
|
||||
})
|
||||
expect(stderr).toBe('')
|
||||
expect(stdout).toContain('test - a')
|
||||
@ -97,7 +90,7 @@ it('can define inline workspace config programmatically', async () => {
|
||||
env: {
|
||||
TEST_ROOT: '1',
|
||||
},
|
||||
workspace: [
|
||||
projects: [
|
||||
{
|
||||
extends: true,
|
||||
test: {
|
||||
@ -137,9 +130,9 @@ it('correctly inherits the root config', async () => {
|
||||
|
||||
it('fails if workspace is empty', async () => {
|
||||
const { stderr } = await runVitest({
|
||||
workspace: [],
|
||||
projects: [],
|
||||
})
|
||||
expect(stderr).toContain('No projects were found. Make sure your configuration is correct. The workspace: [].')
|
||||
expect(stderr).toContain('No projects were found. Make sure your configuration is correct. The projects definition: [].')
|
||||
})
|
||||
|
||||
it('fails if workspace is filtered by the project', async () => {
|
||||
@ -147,11 +140,11 @@ it('fails if workspace is filtered by the project', async () => {
|
||||
project: 'non-existing',
|
||||
root: 'fixtures/workspace/config-empty',
|
||||
config: './vitest.config.js',
|
||||
workspace: [
|
||||
projects: [
|
||||
'./vitest.config.js',
|
||||
],
|
||||
})
|
||||
expect(stderr).toContain(`No projects were found. Make sure your configuration is correct. The filter matched no projects: non-existing. The workspace: [
|
||||
expect(stderr).toContain(`No projects were found. Make sure your configuration is correct. The filter matched no projects: non-existing. The projects definition: [
|
||||
"./vitest.config.js"
|
||||
].`)
|
||||
})
|
||||
@ -1,3 +1,5 @@
|
||||
import type { LabelColor } from 'vitest'
|
||||
import type { Pool } from 'vitest/node'
|
||||
import { basename, dirname, join, resolve } from 'pathe'
|
||||
import { defaultExclude, defineConfig } from 'vitest/config'
|
||||
|
||||
@ -135,5 +137,20 @@ export default defineConfig({
|
||||
return false
|
||||
}
|
||||
},
|
||||
projects: [
|
||||
project('threads', 'red'),
|
||||
project('forks', 'green'),
|
||||
project('vmThreads', 'blue'),
|
||||
],
|
||||
},
|
||||
})
|
||||
|
||||
function project(pool: Pool, color: LabelColor) {
|
||||
return {
|
||||
extends: './vite.config.ts',
|
||||
test: {
|
||||
name: { label: pool, color },
|
||||
pool,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,25 +0,0 @@
|
||||
import { defineWorkspace } from 'vitest/config'
|
||||
|
||||
export default defineWorkspace([
|
||||
{
|
||||
extends: './vite.config.ts',
|
||||
test: {
|
||||
name: { label: 'threads', color: 'red' },
|
||||
pool: 'threads',
|
||||
},
|
||||
},
|
||||
{
|
||||
extends: './vite.config.ts',
|
||||
test: {
|
||||
name: { label: 'forks', color: 'green' },
|
||||
pool: 'forks',
|
||||
},
|
||||
},
|
||||
{
|
||||
extends: './vite.config.ts',
|
||||
test: {
|
||||
name: { label: 'vmThreads', color: 'blue' },
|
||||
pool: 'vmThreads',
|
||||
},
|
||||
},
|
||||
])
|
||||
@ -1,3 +1,7 @@
|
||||
import { defineConfig } from 'vitest/config'
|
||||
|
||||
export default defineConfig({})
|
||||
export default defineConfig({
|
||||
test: {
|
||||
projects: ['space-1', 'space-2'],
|
||||
},
|
||||
})
|
||||
|
||||
@ -1,3 +0,0 @@
|
||||
import { defineWorkspace } from "vitest/config";
|
||||
|
||||
export default defineWorkspace(['space-1', 'space-2'])
|
||||
7
test/snapshots/test/fixtures/workspace/vitest.config.ts
vendored
Normal file
7
test/snapshots/test/fixtures/workspace/vitest.config.ts
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
import { defineConfig, defineWorkspace } from 'vitest/config'
|
||||
|
||||
export default defineConfig({
|
||||
test: {
|
||||
projects: ['packages/*'],
|
||||
},
|
||||
})
|
||||
@ -1,5 +0,0 @@
|
||||
import { defineWorkspace } from 'vitest/config'
|
||||
|
||||
export default defineWorkspace([
|
||||
'packages/*',
|
||||
])
|
||||
@ -23,7 +23,6 @@ test('--update works for workspace project', async () => {
|
||||
const { stdout, exitCode } = await runVitest({
|
||||
update: true,
|
||||
root: 'test/fixtures/workspace',
|
||||
workspace: 'vitest.workspace.ts',
|
||||
})
|
||||
expect.soft(stdout).include('Snapshots 1 updated')
|
||||
expect.soft(exitCode).toBe(0)
|
||||
|
||||
@ -10,7 +10,7 @@ test('reruns tests when config changes', async () => {
|
||||
|
||||
export default {
|
||||
test: {
|
||||
workspace: [
|
||||
projects: [
|
||||
'./project-1',
|
||||
'./project-2',
|
||||
],
|
||||
|
||||
@ -11,5 +11,28 @@ export default defineConfig({
|
||||
reporters: ['default', 'json'],
|
||||
outputFile: './results.json',
|
||||
globalSetup: './globalTest.ts',
|
||||
projects: [
|
||||
'./space_*/*.config.ts',
|
||||
{
|
||||
test: {
|
||||
name: 'space_browser_inline',
|
||||
root: './space_browser_inline',
|
||||
browser: {
|
||||
enabled: true,
|
||||
instances: [{ browser: process.env.BROWSER || 'chromium' }],
|
||||
headless: true,
|
||||
provider: process.env.PROVIDER || 'playwright',
|
||||
},
|
||||
alias: {
|
||||
'test-alias-from-vitest': new URL('./space_browser_inline/test-alias-to.ts', import.meta.url).pathname,
|
||||
},
|
||||
},
|
||||
resolve: {
|
||||
alias: {
|
||||
'test-alias-from-vite': new URL('./space_browser_inline/test-alias-to.ts', import.meta.url).pathname,
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
})
|
||||
|
||||
@ -1,25 +0,0 @@
|
||||
import { defineWorkspace } from 'vitest/config'
|
||||
|
||||
export default defineWorkspace([
|
||||
'./space_*/*.config.ts',
|
||||
{
|
||||
test: {
|
||||
name: 'space_browser_inline',
|
||||
root: './space_browser_inline',
|
||||
browser: {
|
||||
enabled: true,
|
||||
instances: [{ browser: process.env.BROWSER || 'chromium' }],
|
||||
headless: true,
|
||||
provider: process.env.PROVIDER || 'playwright',
|
||||
},
|
||||
alias: {
|
||||
'test-alias-from-vitest': new URL('./space_browser_inline/test-alias-to.ts', import.meta.url).pathname,
|
||||
},
|
||||
},
|
||||
resolve: {
|
||||
alias: {
|
||||
'test-alias-from-vite': new URL('./space_browser_inline/test-alias-to.ts', import.meta.url).pathname,
|
||||
},
|
||||
},
|
||||
},
|
||||
])
|
||||
@ -5,7 +5,7 @@ export default defineConfig({
|
||||
{
|
||||
name: 'throw-error',
|
||||
config() {
|
||||
throw new Error('This file should not initiate a workspace project.')
|
||||
throw new Error('This file should not initiate a test project.')
|
||||
},
|
||||
},
|
||||
],
|
||||
|
||||
@ -1,3 +1,6 @@
|
||||
import type { Vite } from 'vitest/node'
|
||||
import remapping from '@ampproject/remapping'
|
||||
import MagicString from 'magic-string'
|
||||
import { defineConfig } from 'vitest/config'
|
||||
import { cwdPlugin } from './cwdPlugin.js'
|
||||
|
||||
@ -19,5 +22,161 @@ export default defineConfig({
|
||||
provide: {
|
||||
globalConfigValue: true,
|
||||
},
|
||||
projects: [
|
||||
|
||||
'space_2',
|
||||
'./space_*/vitest.config.ts',
|
||||
'./space_1/*.config.ts',
|
||||
async () => ({
|
||||
test: {
|
||||
name: 'happy-dom',
|
||||
root: './space_shared',
|
||||
environment: 'happy-dom',
|
||||
setupFiles: ['./setup.jsdom.ts'],
|
||||
provide: {
|
||||
providedConfigValue: 'actual config value',
|
||||
},
|
||||
},
|
||||
}),
|
||||
Promise.resolve({
|
||||
test: {
|
||||
name: 'node',
|
||||
root: './space_shared',
|
||||
environment: 'node',
|
||||
setupFiles: ['./setup.node.ts'],
|
||||
},
|
||||
}),
|
||||
|
||||
// Projects testing pool and poolOptions
|
||||
{
|
||||
test: {
|
||||
name: 'Threads pool',
|
||||
include: [
|
||||
'./space-pools/threads.test.ts',
|
||||
'./space-pools/multi-worker.test.ts',
|
||||
'./space-pools/isolate.test.ts',
|
||||
],
|
||||
pool: 'threads',
|
||||
},
|
||||
},
|
||||
{
|
||||
test: {
|
||||
name: 'Single thread pool',
|
||||
include: [
|
||||
'./space-pools/threads.test.ts',
|
||||
'./space-pools/single-worker.test.ts',
|
||||
],
|
||||
pool: 'threads',
|
||||
poolOptions: { threads: { singleThread: true } },
|
||||
},
|
||||
},
|
||||
{
|
||||
test: {
|
||||
name: 'Non-isolated thread pool #1',
|
||||
include: [
|
||||
'./space-pools/threads.test.ts',
|
||||
'./space-pools/no-isolate.test.ts',
|
||||
],
|
||||
pool: 'threads',
|
||||
poolOptions: { threads: { isolate: false } },
|
||||
},
|
||||
},
|
||||
{
|
||||
test: {
|
||||
name: 'Non-isolated thread pool #2',
|
||||
include: [
|
||||
'./space-pools/threads.test.ts',
|
||||
'./space-pools/no-isolate.test.ts',
|
||||
],
|
||||
pool: 'threads',
|
||||
isolate: false,
|
||||
},
|
||||
},
|
||||
{
|
||||
test: {
|
||||
name: 'Forks pool',
|
||||
include: [
|
||||
'./space-pools/forks.test.ts',
|
||||
'./space-pools/multi-worker.test.ts',
|
||||
'./space-pools/isolate.test.ts',
|
||||
],
|
||||
pool: 'forks',
|
||||
},
|
||||
},
|
||||
{
|
||||
test: {
|
||||
name: 'Single fork pool',
|
||||
include: [
|
||||
'./space-pools/forks.test.ts',
|
||||
'./space-pools/single-worker.test.ts',
|
||||
],
|
||||
pool: 'forks',
|
||||
poolOptions: { forks: { singleFork: true } },
|
||||
},
|
||||
},
|
||||
{
|
||||
test: {
|
||||
name: 'Non-isolated fork pool #1',
|
||||
include: [
|
||||
'./space-pools/forks.test.ts',
|
||||
'./space-pools/no-isolate.test.ts',
|
||||
],
|
||||
pool: 'forks',
|
||||
poolOptions: { forks: { isolate: false } },
|
||||
},
|
||||
},
|
||||
{
|
||||
test: {
|
||||
name: 'Non-isolated fork pool #2',
|
||||
include: [
|
||||
'./space-pools/forks.test.ts',
|
||||
'./space-pools/no-isolate.test.ts',
|
||||
],
|
||||
pool: 'forks',
|
||||
isolate: false,
|
||||
},
|
||||
},
|
||||
|
||||
// These two projects run on same environment but still transform
|
||||
// a single file differently due to Vite plugins
|
||||
{
|
||||
plugins: [customPlugin(0)],
|
||||
test: {
|
||||
name: 'Project with custom plugin #1',
|
||||
environment: 'node',
|
||||
include: ['./space-multi-transform/test/project-1.test.ts'],
|
||||
},
|
||||
},
|
||||
{
|
||||
plugins: [customPlugin(15)],
|
||||
test: {
|
||||
name: 'Project with custom plugin #2',
|
||||
environment: 'node',
|
||||
include: ['./space-multi-transform/test/project-2.test.ts'],
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
})
|
||||
|
||||
function customPlugin(offset: number): Vite.Plugin {
|
||||
return {
|
||||
name: 'vitest-custom-multi-transform',
|
||||
enforce: 'pre',
|
||||
transform(code, id) {
|
||||
if (id.includes('space-multi-transform/src/multi-transform.ts')) {
|
||||
const padding = '\n*****'.repeat(offset)
|
||||
|
||||
const transformed = new MagicString(code)
|
||||
transformed.replace('\'default-padding\'', `\`${padding}\``)
|
||||
|
||||
const map = remapping(
|
||||
[transformed.generateMap({ hires: true }), this.getCombinedSourcemap() as any],
|
||||
() => null,
|
||||
) as any
|
||||
|
||||
return { code: transformed.toString(), map }
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,160 +0,0 @@
|
||||
import type { Plugin } from 'vite'
|
||||
import remapping from '@ampproject/remapping'
|
||||
import MagicString from 'magic-string'
|
||||
import { defineWorkspace } from 'vitest/config'
|
||||
|
||||
export default defineWorkspace([
|
||||
'space_2',
|
||||
'./space_*/vitest.config.ts',
|
||||
'./space_1/*.config.ts',
|
||||
async () => ({
|
||||
test: {
|
||||
name: 'happy-dom',
|
||||
root: './space_shared',
|
||||
environment: 'happy-dom',
|
||||
setupFiles: ['./setup.jsdom.ts'],
|
||||
provide: {
|
||||
providedConfigValue: 'actual config value',
|
||||
},
|
||||
},
|
||||
}),
|
||||
Promise.resolve({
|
||||
test: {
|
||||
name: 'node',
|
||||
root: './space_shared',
|
||||
environment: 'node',
|
||||
setupFiles: ['./setup.node.ts'],
|
||||
},
|
||||
}),
|
||||
|
||||
// Projects testing pool and poolOptions
|
||||
{
|
||||
test: {
|
||||
name: 'Threads pool',
|
||||
include: [
|
||||
'./space-pools/threads.test.ts',
|
||||
'./space-pools/multi-worker.test.ts',
|
||||
'./space-pools/isolate.test.ts',
|
||||
],
|
||||
pool: 'threads',
|
||||
},
|
||||
},
|
||||
{
|
||||
test: {
|
||||
name: 'Single thread pool',
|
||||
include: [
|
||||
'./space-pools/threads.test.ts',
|
||||
'./space-pools/single-worker.test.ts',
|
||||
],
|
||||
pool: 'threads',
|
||||
poolOptions: { threads: { singleThread: true } },
|
||||
},
|
||||
},
|
||||
{
|
||||
test: {
|
||||
name: 'Non-isolated thread pool #1',
|
||||
include: [
|
||||
'./space-pools/threads.test.ts',
|
||||
'./space-pools/no-isolate.test.ts',
|
||||
],
|
||||
pool: 'threads',
|
||||
poolOptions: { threads: { isolate: false } },
|
||||
},
|
||||
},
|
||||
{
|
||||
test: {
|
||||
name: 'Non-isolated thread pool #2',
|
||||
include: [
|
||||
'./space-pools/threads.test.ts',
|
||||
'./space-pools/no-isolate.test.ts',
|
||||
],
|
||||
pool: 'threads',
|
||||
isolate: false,
|
||||
},
|
||||
},
|
||||
{
|
||||
test: {
|
||||
name: 'Forks pool',
|
||||
include: [
|
||||
'./space-pools/forks.test.ts',
|
||||
'./space-pools/multi-worker.test.ts',
|
||||
'./space-pools/isolate.test.ts',
|
||||
],
|
||||
pool: 'forks',
|
||||
},
|
||||
},
|
||||
{
|
||||
test: {
|
||||
name: 'Single fork pool',
|
||||
include: [
|
||||
'./space-pools/forks.test.ts',
|
||||
'./space-pools/single-worker.test.ts',
|
||||
],
|
||||
pool: 'forks',
|
||||
poolOptions: { forks: { singleFork: true } },
|
||||
},
|
||||
},
|
||||
{
|
||||
test: {
|
||||
name: 'Non-isolated fork pool #1',
|
||||
include: [
|
||||
'./space-pools/forks.test.ts',
|
||||
'./space-pools/no-isolate.test.ts',
|
||||
],
|
||||
pool: 'forks',
|
||||
poolOptions: { forks: { isolate: false } },
|
||||
},
|
||||
},
|
||||
{
|
||||
test: {
|
||||
name: 'Non-isolated fork pool #2',
|
||||
include: [
|
||||
'./space-pools/forks.test.ts',
|
||||
'./space-pools/no-isolate.test.ts',
|
||||
],
|
||||
pool: 'forks',
|
||||
isolate: false,
|
||||
},
|
||||
},
|
||||
|
||||
// These two projects run on same environment but still transform
|
||||
// a single file differently due to Vite plugins
|
||||
{
|
||||
plugins: [customPlugin(0)],
|
||||
test: {
|
||||
name: 'Project with custom plugin #1',
|
||||
environment: 'node',
|
||||
include: ['./space-multi-transform/test/project-1.test.ts'],
|
||||
},
|
||||
},
|
||||
{
|
||||
plugins: [customPlugin(15)],
|
||||
test: {
|
||||
name: 'Project with custom plugin #2',
|
||||
environment: 'node',
|
||||
include: ['./space-multi-transform/test/project-2.test.ts'],
|
||||
},
|
||||
},
|
||||
])
|
||||
|
||||
function customPlugin(offset: number): Plugin {
|
||||
return {
|
||||
name: 'vitest-custom-multi-transform',
|
||||
enforce: 'pre',
|
||||
transform(code, id) {
|
||||
if (id.includes('space-multi-transform/src/multi-transform.ts')) {
|
||||
const padding = '\n*****'.repeat(offset)
|
||||
|
||||
const transformed = new MagicString(code)
|
||||
transformed.replace('\'default-padding\'', `\`${padding}\``)
|
||||
|
||||
const map = remapping(
|
||||
[transformed.generateMap({ hires: true }), this.getCombinedSourcemap() as any],
|
||||
() => null,
|
||||
) as any
|
||||
|
||||
return { code: transformed.toString(), map }
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user