···4141- Components testing ([Vue](./examples/vue), [React](./examples/react), [Svelte](./examples/svelte), [Lit](./examples/lit), [Vitesse](./examples/vitesse))
4242- Workers multi-threading via [Tinypool](https://github.com/tinylibs/tinypool) (a lightweight fork of [Piscina](https://github.com/piscinajs/piscina))
4343- Benchmarking support with [Tinybench](https://github.com/tinylibs/tinybench)
4444+- [Workspace](/guide/workspace) support
4445- ESM first, top level await
4546- Out-of-box TypeScript / JSX support
4647- Filtering, timeouts, concurrent for suite and tests
47484848-> Vitest requires Vite >=v3.0.0 and Node >=v14
4949+> Vitest requires Vite >=v3.0.0 and Node >=v14.18
495050515152```ts
···251251252252 When `partial` is `true` it will expect a `Partial<T>` as a return value.
253253 ```ts
254254- import example from './example'
255255-256256- vi.mock('./example')
254254+ import example from './example.js'
255255+256256+ vi.mock('./example.js')
257257258258 test('1+1 equals 2', async () => {
259259 vi.mocked(example.calc).mockRestore()
···271271 Imports module, bypassing all checks if it should be mocked. Can be useful if you want to mock module partially.
272272273273 ```ts
274274- vi.mock('./example', async () => {
275275- const axios = await vi.importActual('./example')
274274+ vi.mock('./example.js', async () => {
275275+ const axios = await vi.importActual('./example.js')
276276277277 return { ...axios, get: vi.fn() }
278278 })
+32-24
docs/config/index.md
···7474In addition to the following options, 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.
7575:::
76767777+::: tip
7878+All configuration options that are not supported inside a [workspace](/guide/workspace) project config have <NonProjectOption /> sign next them.
7979+:::
8080+7781### include
78827983- **Type:** `string[]`
···99103- **Type:** `DepOptimizationConfig & { enabled: boolean }`
100104- **Version:** Since Vitest 0.29.0
101105- **See also:** [Dep Optimization Options](https://vitejs.dev/config/dep-optimization-options.html)
106106+107107+::: warning
108108+This feature is temporary disabled since Vitest 0.30.0.
109109+:::
102110103111Enable dependency optimization. If you have a lot of tests, this might improve their performance.
104112···141149142150This might potentially cause some misalignment if a package has different logic in ESM and CJS mode.
143151144144-#### deps.registerNodeLoader
152152+#### deps.registerNodeLoader<NonProjectOption />
145153146154- **Type:** `boolean`
147155- **Default:** `false`
···411419})
412420```
413421414414-### update
422422+### update<NonProjectOption />
415423416424- **Type:** `boolean`
417425- **Default:** `false`
···419427420428Update snapshot files. This will update all changed snapshots and delete obsolete ones.
421429422422-### watch
430430+### watch<NonProjectOption />
423431424432- **Type:** `boolean`
425433- **Default:** `true`
···434442435443Project root
436444437437-### reporters
445445+### reporters<NonProjectOption />
438446439447- **Type:** `Reporter | Reporter[]`
440448- **Default:** `'default'`
···452460 - `'hanging-process'` - displays a list of hanging processes, if Vitest cannot exit process safely. This might be a heavy operation, enable it only if Vitest consistently cannot exit process
453461 - path of a custom reporter (e.g. `'./path/to/reporter.ts'`, `'@scope/reporter'`)
454462455455-### outputFile
463463+### outputFile<NonProjectOption />
456464457465- **Type:** `string | Record<string, string>`
458466- **CLI:** `--outputFile=<path>`, `--outputFile.json=./path`
···485493This might cause all sorts of issues, if you are relying on global state (frontend frameworks usually do) or your code relies on environment to be defined separately for each test. But can be a speed boost for your tests (up to 3 times faster), that don't necessarily rely on global state or can easily bypass that.
486494:::
487495488488-### maxThreads
496496+### maxThreads<NonProjectOption />
489497490498- **Type:** `number`
491499- **Default:** _available CPUs_
492500493501Maximum number of threads. You can also use `VITEST_MAX_THREADS` environment variable.
494502495495-### minThreads
503503+### minThreads<NonProjectOption />
496504497505- **Type:** `number`
498506- **Default:** _available CPUs_
499507500508Minimum number of threads. You can also use `VITEST_MIN_THREADS` environment variable.
501509502502-### useAtomics
510510+### useAtomics<NonProjectOption />
503511504512- **Type:** `boolean`
505513- **Default:** `false`
···524532525533Default timeout of a hook in milliseconds
526534527527-### teardownTimeout
535535+### teardownTimeout<NonProjectOption />
528536529537- **Type:** `number`
530538- **Default:** `10000`
531539532540Default timeout to wait for close when Vitest shuts down, in milliseconds
533541534534-### silent
542542+### silent<NonProjectOption />
535543536544- **Type:** `boolean`
537545- **Default:** `false`
···591599:::
592600593601594594-### watchExclude
602602+### watchExclude<NonProjectOption />
595603596604- **Type:** `string[]`
597605- **Default:** `['**/node_modules/**', '**/dist/**']`
598606599607Glob pattern of file paths to be ignored from triggering watch rerun.
600608601601-### forceRerunTriggers
609609+### forceRerunTriggers<NonProjectOption />
602610603611- **Type**: `string[]`
604612- **Default:** `['**/package.json/**', '**/vitest.config.*/**', '**/vite.config.*/**']`
···626634627635Isolate environment for each test file. Does not work if you disable [`--threads`](#threads).
628636629629-### coverage
637637+### coverage<NonProjectOption />
630638631639You can use [`c8`](https://github.com/bcoe/c8), [`istanbul`](https://istanbul.js.org/) or [a custom coverage solution](/guide/coverage#custom-coverage-provider) for coverage collection.
632640···703711- **Type:** `boolean`
704712- **Default:** `false`
705713- **Available for providers:** `'c8' | 'istanbul'`
706706-- **CLI:** `--coverage.all`, --coverage.all=false`
714714+- **CLI:** `--coverage.all`, `--coverage.all=false`
707715708716Whether to include all files, including the untested ones into report.
709717···906914907915Specifies the module name or path for the custom coverage provider module. See [Guide - Custom Coverage Provider](/guide/coverage#custom-coverage-provider) for more information.
908916909909-### testNamePattern
917917+### testNamePattern<NonProjectOption />
910918911919- **Type** `string | RegExp`
912920- **CLI:** `-t <pattern>`, `--testNamePattern=<pattern>`, `--test-name-pattern=<pattern>`
···928936})
929937```
930938931931-### open
939939+### open<NonProjectOption />
932940933941- **Type:** `boolean`
934942- **Default:** `false`
···10911099})
10921100```
1093110110941094-### snapshotFormat
11021102+### snapshotFormat<NonProjectOption />
1095110310961104- **Type:** `PrettyFormatOptions`
1097110510981106Format options for snapshot testing. These options are passed down to [`pretty-format`](https://www.npmjs.com/package/pretty-format).
1099110711001100-### resolveSnapshotPath
11081108+### resolveSnapshotPath<NonProjectOption />
1101110911021110- **Type**: `(testPath: string, snapExtension: string) => string`
11031111- **Default**: stores snapshot files in `__snapshots__` directory
···1122113011231131Allow tests and suites that are marked as only.
1124113211251125-### dangerouslyIgnoreUnhandledErrors
11331133+### dangerouslyIgnoreUnhandledErrors<NonProjectOption />
1126113411271135- **Type**: `boolean`
11281136- **Default**: `false`
···1130113811311139Ignore any unhandled errors that occur.
1132114011331133-### passWithNoTests
11411141+### passWithNoTests<NonProjectOption />
1134114211351143- **Type**: `boolean`
11361144- **Default**: `false`
···1199120712001208Test above this limit will be queued to run when available slot appears.
1201120912021202-### cache
12101210+### cache<NonProjectOption />
1203121112041212- **Type**: `false | { dir? }`
12051213···12241232npx vitest --sequence.shuffle --sequence.seed=1000
12251233```
1226123412271227-#### sequence.sequencer
12351235+#### sequence.sequencer<NonProjectOption />
1228123612291237- **Type**: `TestSequencerConstructor`
12301238- **Default**: `BaseSequencer`
···1243125112441252Vitest usually uses cache to sort tests, so long running tests start earlier - this makes tests run faster. If your tests will run in random order you will lose this performance improvement, but it may be useful to track tests that accidentally depend on another run previously.
1245125312461246-#### sequence.seed
12541254+#### sequence.seed<NonProjectOption />
1247125512481256- **Type**: `number`
12491257- **Default**: `Date.now()`
···1330133813311339Path to custom tsconfig, relative to the project root.
1332134013331333-### slowTestThreshold
13411341+### slowTestThreshold<NonProjectOption />
1334134213351343- **Type**: `number`
13361344- **Default**: `300`
+35-1
docs/guide/index.md
···3232```
33333434:::tip
3535-Vitest requires Vite >=v3.0.0 and Node >=v14
3535+Vitest requires Vite >=v3.0.0 and Node >=v14.18
3636:::
37373838It is recommended that you install a copy of `vitest` in your `package.json`, using one of the methods listed above. However, if you would prefer to run `vitest` directly, you can use `npx vitest` (the `npx` command comes with npm and Node.js).
···6060```
61616262See the list of config options in the [Config Reference](../config/)
6363+6464+## Workspaces Support
6565+6666+Run different project configurations inside the same project with [Vitest Workspaces](/guide/workspace). You can define a list of files and folders that define you workspace in `vitest.workspace` file. The file supports `js`/`ts`/`json` extensions. This feature works great with monorepo setups.
6767+6868+```ts
6969+import { defineWorkspace } from 'vitest/config'
7070+7171+export default defineWorkspace([
7272+ // you can use a list of glob patterns to define your workspaces
7373+ // Vitest expects a list of config files
7474+ // or directories where there is a config file
7575+ 'packages/*',
7676+ 'tests/*/vitest.config.{e2e,unit}.ts',
7777+ // you can even run the same tests,
7878+ // but with different configs in the same "vitest" process
7979+ {
8080+ test: {
8181+ name: 'happy-dom',
8282+ root: './shared_tests',
8383+ environment: 'happy-dom',
8484+ setupFiles: ['./setup.happy-dom.ts'],
8585+ },
8686+ },
8787+ {
8888+ test: {
8989+ name: 'node',
9090+ root: './shared_tests',
9191+ environment: 'node',
9292+ setupFiles: ['./setup.node.ts'],
9393+ },
9494+ },
9595+])
9696+```
63976498## Command Line Interface
6599
···11+# Workspace
22+33+Vitest provides built-in support for monorepositories through a workspace configuration file. You can create a workspace to define your project's setups.
44+55+## Defining a workspace
66+77+A workspace should have a `vitest.workspace` or `vitest.projects` file in its root (in the same folder with your config file, if you have one). Vitest supports `ts`/`js`/`json` extensions for this file.
88+99+Workspace configuration file should have a default export with a list of files or glob patterns referencing your projects. For example, if you have a folder with your projects named `packages`, you can define a workspace with this config file:
1010+1111+:::code-group
1212+```ts [vitest.workspace.ts]
1313+export default [
1414+ 'packages/*'
1515+]
1616+```
1717+:::
1818+1919+Vitest will consider every folder in `packages` as a separate project even if it doesn't have a config file inside.
2020+2121+::: warning
2222+Vitest will not consider the root config as a workspace project (so it will not run tests specified in `include`) unless it is specified in this config.
2323+:::
2424+2525+You can also reference projects with their config files:
2626+2727+:::code-group
2828+```ts [vitest.workspace.ts]
2929+export default [
3030+ 'packages/*/vitest.config.{e2e,unit}.ts'
3131+]
3232+```
3333+:::
3434+3535+This pattern will only include projects with `vitest.config` file that includes `e2e` and `unit` before the extension.
3636+3737+::: warning
3838+If you are referencing filenames with glob pattern, make sure your config file starts with `vite.config` or `vitest.config`. Otherwise Vitest will skip it.
3939+:::
4040+4141+You can also define projects with inline config. Workspace file supports using both syntaxes at the same time.
4242+4343+:::code-group
4444+```ts [vitest.workspace.ts]
4545+import { defineWorkspace } from 'vitest/config'
4646+4747+// defineWorkspace provides a nice type hinting DX
4848+export default defineWorkspace([
4949+ 'packages/*',
5050+ {
5151+ // add "extends" to merge two configs together
5252+ extends: './vite.config.js',
5353+ test: {
5454+ include: ['tests/**/*.{browser}.test.{ts,js}'],
5555+ // it is recommended to define a name when using inline configs
5656+ name: 'happy-dom',
5757+ environment: 'happy-dom',
5858+ }
5959+ },
6060+ {
6161+ test: {
6262+ include: ['tests/**/*.{node}.test.{ts,js}'],
6363+ name: 'node',
6464+ environment: 'node',
6565+ }
6666+ }
6767+])
6868+```
6969+:::
7070+7171+::: warning
7272+All projects should have unique names. Otherwise Vitest will throw an error. If you do not provide a name inside inline config, Vitest will assign a number. If you don't provide a name inside a project config defined with glob syntax, Vitest will use the directory name by default.
7373+:::
7474+7575+If you don't rely on inline configs, you can just create a small json file in your root directory:
7676+7777+:::code-group
7878+```json [vitest.workspace.json]
7979+[
8080+ "packages/*"
8181+]
8282+```
8383+:::
8484+8585+Workspace projects don't support all configuration properties. For better type safety, use `defineProject` instead of `defineConfig` method inside project configuration files:
8686+8787+:::code-group
8888+```ts [packages/a/vitest.config.ts]
8989+import { defineProject } from 'vitest/config'
9090+9191+export default defineProject({
9292+ test: {
9393+ environment: 'jsdom',
9494+ // "reporters" is not supported in a project config,
9595+ // so it will show an error
9696+ reporters: ['json']
9797+ }
9898+})
9999+```
100100+:::
101101+102102+## Configuration
103103+104104+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:
105105+106106+:::code-group
107107+```ts [packages/a/vitest.config.ts]
108108+import { defineProject, mergeConfig } from 'vitest/config'
109109+import configShared from '../vitest.shared.js'
110110+111111+export default mergeConfig(
112112+ configShared,
113113+ defineProject({
114114+ test: {
115115+ environment: 'jsdom',
116116+ }
117117+ })
118118+)
119119+```
120120+:::
121121+122122+Also some of the configuration options are not allowed in a project config. Most notably:
123123+124124+- `coverage`: coverage is done for the whole workspace
125125+- `reporters`: only root-level reporters can be supported
126126+- `resolveSnapshotPath`: only root-level resolver is respected
127127+- all other options that don't affect test runners
128128+129129+::: tip
130130+All configuration options that are not supported inside a project config have <NonProjectOption /> sign next them in ["Config"](/config/) page.
131131+:::
132132+133133+## Coverage
134134+135135+Coverage for workspace projects works out of the box. But if you have [`all`](/config/#coverage-all) option enabled and use non-conventional extensions in some of you projects, you will need to have a plugin that handles this extension in your root configuration file.
136136+137137+For example, if you have a package that uses Vue files and it has its own config file, but some of the files are not imported in your tests, coverage will fail trying to analyze the usage of unused files, because it relies on the root configuration rather than project configuration.
···11import { defineConfig } from 'vite'
22-import { BaseSequencer } from 'vitest/node'
22+import { BaseSequencer, type WorkspaceSpec } from 'vitest/node'
3344export default defineConfig({
55 test: {
66 threads: false,
77 sequence: {
88 sequencer: class Sequences extends BaseSequencer {
99- public async sort(files: string[]): Promise<string[]> {
99+ public async sort(files: WorkspaceSpec[]): Promise<WorkspaceSpec[]> {
1010 return files.sort()
1111 }
1212 },
+1-1
test/watch/vitest.config.ts
···66 include: ['test/**/*.test.*'],
7788 // For Windows CI mostly
99- testTimeout: 30_000,
99+ testTimeout: process.env.CI ? 30_000 : 10_000,
10101111 // Test cases may have side effects, e.g. files under fixtures/ are modified on the fly to trigger file watchers
1212 singleThread: true,
···11+import { defineConfig } from 'vitest/config'
22+33+if (process.env.TEST_WATCH) {
44+ // Patch stdin on the process so that we can fake it to seem like a real interactive terminal and pass the TTY checks
55+ process.stdin.isTTY = true
66+ process.stdin.setRawMode = () => process.stdin
77+}
88+99+export default defineConfig({
1010+ test: {
1111+ coverage: {
1212+ all: true,
1313+ },
1414+ reporters: ['default', 'json'],
1515+ outputFile: './results.json',
1616+ globalSetup: './globalTest.ts',
1717+ },
1818+})
···11+import { expect, it } from 'vitest'
22+33+declare global {
44+ const testValue: string
55+}
66+77+it('the same file works with different projects', () => {
88+ expect(testValue).toBe(expect.getState().environment === 'node' ? 'node' : 'jsdom')
99+})
+3
test/workspaces/src/math.ts
···11+export function sum(a: number, b: number) {
22+ return a + b
33+}
···11export type { Vitest } from './core'
22+export type { WorkspaceProject as VitestWorkspace } from './workspace'
23export { createVitest } from './create'
34export { VitestPlugin } from './plugins'
45export { startVitest } from './cli-api'
66+export type { WorkspaceSpec } from './pool'
5768export { VitestExecutor } from '../runtime/execute'
79export type { ExecuteOptions } from '../runtime/execute'
+9-2
packages/vitest/src/node/logger.ts
···109109 if (this.ctx.config.sequence.sequencer === RandomSequencer)
110110 this.log(c.gray(` Running tests with seed "${this.ctx.config.sequence.seed}"`))
111111112112- if (this.ctx.config.browser.enabled)
113113- this.log(c.dim(c.green(` Browser runner started at http://${this.ctx.config.browser.api?.host || 'localhost'}:${c.bold(`${this.ctx.browser.config.server.port}`)}`)))
112112+ this.ctx.projects.forEach((project) => {
113113+ if (!project.browser)
114114+ return
115115+ const name = project.getName()
116116+ const output = project.isCore() ? '' : ` [${name}]`
117117+118118+ this.log(c.dim(c.green(` ${output} Browser runner started at http://${project.config.browser.api?.host || 'localhost'}:${c.bold(`${project.browser.config.server.port}`)}`)))
119119+ })
120120+114121 if (this.ctx.config.ui)
115122 this.log(c.dim(c.green(` UI started at http://${this.ctx.config.api?.host || 'localhost'}:${c.bold(`${this.ctx.server.config.server.port}`)}${this.ctx.config.uiBase}`)))
116123 else if (this.ctx.config.api)
+18-22
packages/vitest/src/node/pool.ts
···77import { createChildProcessPool } from './pools/child'
88import { createThreadsPool } from './pools/threads'
99import { createBrowserPool } from './pools/browser'
1010+import type { WorkspaceProject } from './workspace'
10111111-export type RunWithFiles = (files: string[], invalidates?: string[]) => Promise<void>
1212+export type WorkspaceSpec = [project: WorkspaceProject, testFile: string]
1313+export type RunWithFiles = (files: WorkspaceSpec[], invalidates?: string[]) => Promise<void>
12141315export interface ProcessPool {
1416 runTests: RunWithFiles
···3032 browser: null,
3133 }
32343333- function getDefaultPoolName() {
3434- if (ctx.config.browser.enabled)
3535+ function getDefaultPoolName(project: WorkspaceProject) {
3636+ if (project.config.browser.enabled)
3537 return 'browser'
3636- if (ctx.config.threads)
3838+ if (project.config.threads)
3739 return 'threads'
3840 return 'child_process'
3941 }
40424141- function getPoolName(file: string) {
4242- for (const [glob, pool] of ctx.config.poolMatchGlobs || []) {
4343- if (mm.isMatch(file, glob, { cwd: ctx.server.config.root }))
4343+ function getPoolName([project, file]: WorkspaceSpec) {
4444+ for (const [glob, pool] of project.config.poolMatchGlobs || []) {
4545+ if (mm.isMatch(file, glob, { cwd: project.config.root }))
4446 return pool
4547 }
4646- return getDefaultPoolName()
4848+ return getDefaultPoolName(project)
4749 }
48504949- async function runTests(files: string[], invalidate?: string[]) {
5151+ async function runTests(files: WorkspaceSpec[], invalidate?: string[]) {
5052 const conditions = ctx.server.config.resolve.conditions?.flatMap(c => ['--conditions', c]) || []
51535254 // Instead of passing whole process.execArgv to the workers, pick allowed options.
···7981 }
80828183 const filesByPool = {
8282- child_process: [] as string[],
8383- threads: [] as string[],
8484- browser: [] as string[],
8484+ child_process: [] as WorkspaceSpec[],
8585+ threads: [] as WorkspaceSpec[],
8686+ browser: [] as WorkspaceSpec[],
8587 }
86888787- if (!ctx.config.poolMatchGlobs) {
8888- const name = getDefaultPoolName()
8989- filesByPool[name] = files
9090- }
9191- else {
9292- for (const file of files) {
9393- const pool = getPoolName(file)
9494- filesByPool[pool].push(file)
9595- }
8989+ for (const spec of files) {
9090+ const pool = getPoolName(spec)
9191+ filesByPool[pool].push(spec)
9692 }
97939894 await Promise.all(Object.entries(filesByPool).map(([pool, files]) => {
9995 if (!files.length)
10096 return null
10197102102- if (ctx.browserProvider && pool === 'browser') {
9898+ if (pool === 'browser') {
10399 pools.browser ??= createBrowserPool(ctx)
104100 return pools.browser.runTests(files, invalidate)
105101 }
+17-6
packages/vitest/src/node/state.ts
···11import type { ErrorWithDiff, File, Task, TaskResultPack, UserConsoleLog } from '../types'
22// can't import actual functions from utils, because it's incompatible with @vitest/browsers
33import type { AggregateError as AggregateErrorPonyfill } from '../utils'
44+import type { WorkspaceProject } from './workspace'
4556interface CollectingPromise {
67 promise: Promise<void>
···16171718// Note this file is shared for both node and browser, be aware to avoid node specific logic
1819export class StateManager {
1919- filesMap = new Map<string, File>()
2020+ filesMap = new Map<string, File[]>()
2021 pathsSet: Set<string> = new Set()
2122 collectingPromise: CollectingPromise | undefined = undefined
2223 browserTestPromises = new Map<string, { resolve: (v: unknown) => void; reject: (v: unknown) => void }>()
···55565657 getFiles(keys?: string[]): File[] {
5758 if (keys)
5858- return keys.map(key => this.filesMap.get(key)!).filter(Boolean)
5959- return Array.from(this.filesMap.values())
5959+ return keys.map(key => this.filesMap.get(key)!).filter(Boolean).flat()
6060+ return Array.from(this.filesMap.values()).flat()
6061 }
61626263 getFilepaths(): string[] {
···77787879 collectFiles(files: File[] = []) {
7980 files.forEach((file) => {
8080- this.filesMap.set(file.filepath, file)
8181+ const existing = (this.filesMap.get(file.filepath) || [])
8282+ const otherProject = existing.filter(i => i.projectName !== file.projectName)
8383+ otherProject.push(file)
8484+ this.filesMap.set(file.filepath, otherProject)
8185 this.updateId(file)
8286 })
8387 }
84888585- clearFiles(paths: string[] = []) {
8989+ clearFiles(project: WorkspaceProject, paths: string[] = []) {
8690 paths.forEach((path) => {
8787- this.filesMap.delete(path)
9191+ const files = this.filesMap.get(path)
9292+ if (!files)
9393+ return
9494+ const filtered = files.filter(file => file.projectName !== project.config.name)
9595+ if (!filtered.length)
9696+ this.filesMap.delete(path)
9797+ else
9898+ this.filesMap.set(path, filtered)
8899 })
89100 }
90101
···44import type { RawSourceMap } from 'vite-node'
5566import { calculateSuiteHash, generateHash, interpretTaskModes, someTasksAreOnly } from '@vitest/runner/utils'
77-import type { File, Suite, Test, Vitest } from '../types'
77+import type { File, Suite, Test } from '../types'
88+import type { WorkspaceProject } from '../node/workspace'
89910interface ParsedFile extends File {
1011 start: number
···3839 definitions: LocalCallDefinition[]
3940}
40414141-export async function collectTests(ctx: Vitest, filepath: string): Promise<null | FileInformation> {
4242+export async function collectTests(ctx: WorkspaceProject, filepath: string): Promise<null | FileInformation> {
4243 const request = await ctx.vitenode.transformRequest(filepath)
4344 if (!request)
4445 return null
···5051 const file: ParsedFile = {
5152 filepath,
5253 type: 'suite',
5353- id: generateHash(testFilepath),
5454+ id: generateHash(`${testFilepath}${ctx.config.name || ''}`),
5455 name: testFilepath,
5556 mode: 'run',
5657 tasks: [],
+3-2
packages/vitest/src/typecheck/typechecker.ts
···55import { SourceMapConsumer } from 'source-map'
66import { getTasks } from '../utils'
77import { ensurePackageInstalled } from '../node/pkg'
88-import type { Awaitable, File, ParsedStack, Task, TaskResultPack, TaskState, TscErrorInfo, Vitest } from '../types'
88+import type { Awaitable, File, ParsedStack, Task, TaskResultPack, TaskState, TscErrorInfo } from '../types'
99+import type { WorkspaceProject } from '../node/workspace'
910import { getRawErrsMapFromTsCompile, getTsconfig } from './parse'
1011import { createIndexMap } from './utils'
1112import type { FileInformation } from './collect'
···4041 private allowJs?: boolean
4142 private process!: ExecaChildProcess
42434343- constructor(protected ctx: Vitest, protected files: string[]) { }
4444+ constructor(protected ctx: WorkspaceProject, protected files: string[]) { }
44454546 public onParseStart(fn: Callback) {
4647 this._onParseStart = fn
+2-2
packages/vitest/src/types/browser.ts
···11import type { Awaitable } from '@vitest/utils'
22-import type { Vitest } from '../node'
22+import type { WorkspaceProject } from '../node/workspace'
33import type { ApiConfig } from './config'
4455export interface BrowserProviderOptions {
···99export interface BrowserProvider {
1010 name: string
1111 getSupportedBrowsers(): readonly string[]
1212- initialize(ctx: Vitest, options: BrowserProviderOptions): Awaitable<void>
1212+ initialize(ctx: WorkspaceProject, options: BrowserProviderOptions): Awaitable<void>
1313 openPage(url: string): Awaitable<void>
1414 close(): Awaitable<void>
1515}
+124-81
packages/vitest/src/types/config.ts
···35353636export type VitestRunMode = 'test' | 'benchmark' | 'typecheck'
37373838+interface SequenceOptions {
3939+ /**
4040+ * Class that handles sorting and sharding algorithm.
4141+ * If you only need to change sorting, you can extend
4242+ * your custom sequencer from `BaseSequencer` from `vitest/node`.
4343+ * @default BaseSequencer
4444+ */
4545+ sequencer?: TestSequencerConstructor
4646+ /**
4747+ * Should tests run in random order.
4848+ * @default false
4949+ */
5050+ shuffle?: boolean
5151+ /**
5252+ * Defines how setup files should be ordered
5353+ * - 'parallel' will run all setup files in parallel
5454+ * - 'list' will run all setup files in the order they are defined in the config file
5555+ * @default 'parallel'
5656+ */
5757+ setupFiles?: SequenceSetupFiles
5858+ /**
5959+ * Seed for the random number generator.
6060+ * @default Date.now()
6161+ */
6262+ seed?: number
6363+ /**
6464+ * Defines how hooks should be ordered
6565+ * - `stack` will order "after" hooks in reverse order, "before" hooks will run sequentially
6666+ * - `list` will order hooks in the order they are defined
6767+ * - `parallel` will run hooks in a single group in parallel
6868+ * @default 'parallel'
6969+ */
7070+ hooks?: SequenceHooks
7171+}
7272+7373+interface DepsOptions {
7474+ /**
7575+ * Enable dependency optimization. This can improve the performance of your tests.
7676+ */
7777+ experimentalOptimizer?: Omit<DepOptimizationConfig, 'disabled'> & {
7878+ enabled: boolean
7979+ }
8080+ /**
8181+ * Externalize means that Vite will bypass the package to native Node.
8282+ *
8383+ * Externalized dependencies will not be applied Vite's transformers and resolvers.
8484+ * And does not support HMR on reload.
8585+ *
8686+ * Typically, packages under `node_modules` are externalized.
8787+ */
8888+ external?: (string | RegExp)[]
8989+ /**
9090+ * Vite will process inlined modules.
9191+ *
9292+ * This could be helpful to handle packages that ship `.js` in ESM format (that Node can't handle).
9393+ *
9494+ * If `true`, every dependency will be inlined
9595+ */
9696+ inline?: (string | RegExp)[] | true
9797+9898+ /**
9999+ * Interpret CJS module's default as named exports
100100+ *
101101+ * @default true
102102+ */
103103+ interopDefault?: boolean
104104+105105+ /**
106106+ * When a dependency is a valid ESM package, try to guess the cjs version based on the path.
107107+ * This will significantly improve the performance in huge repo, but might potentially
108108+ * cause some misalignment if a package have different logic in ESM and CJS mode.
109109+ *
110110+ * @default false
111111+ */
112112+ fallbackCJS?: boolean
113113+114114+ /**
115115+ * Use experimental Node loader to resolve imports inside node_modules using Vite resolve algorithm.
116116+ * @default false
117117+ */
118118+ registerNodeLoader?: boolean
119119+}
120120+38121export interface InlineConfig {
39122 /**
40123 * Name of the project. Will be used to display in the reporter.
···71154 /**
72155 * Handling for dependencies inlining or externalizing
73156 */
7474- deps?: {
7575- /**
7676- * Enable dependency optimization. This can improve the performance of your tests.
7777- */
7878- experimentalOptimizer?: Omit<DepOptimizationConfig, 'disabled'> & {
7979- enabled: boolean
8080- }
8181- /**
8282- * Externalize means that Vite will bypass the package to native Node.
8383- *
8484- * Externalized dependencies will not be applied Vite's transformers and resolvers.
8585- * And does not support HMR on reload.
8686- *
8787- * Typically, packages under `node_modules` are externalized.
8888- */
8989- external?: (string | RegExp)[]
9090- /**
9191- * Vite will process inlined modules.
9292- *
9393- * This could be helpful to handle packages that ship `.js` in ESM format (that Node can't handle).
9494- *
9595- * If `true`, every dependency will be inlined
9696- */
9797- inline?: (string | RegExp)[] | true
9898-9999- /**
100100- * Interpret CJS module's default as named exports
101101- *
102102- * @default true
103103- */
104104- interopDefault?: boolean
105105-106106- /**
107107- * When a dependency is a valid ESM package, try to guess the cjs version based on the path.
108108- * This will significantly improve the performance in huge repo, but might potentially
109109- * cause some misalignment if a package have different logic in ESM and CJS mode.
110110- *
111111- * @default false
112112- */
113113- fallbackCJS?: boolean
114114-115115- /**
116116- * Use experimental Node loader to resolve imports inside node_modules using Vite resolve algorithm.
117117- * @default false
118118- */
119119- registerNodeLoader?: boolean
120120- }
157157+ deps?: DepsOptions
121158122159 /**
123160 * Base directory to scan for the test files
···480517 /**
481518 * Options for configuring the order of running tests.
482519 */
483483- sequence?: {
484484- /**
485485- * Class that handles sorting and sharding algorithm.
486486- * If you only need to change sorting, you can extend
487487- * your custom sequencer from `BaseSequencer` from `vitest/node`.
488488- * @default BaseSequencer
489489- */
490490- sequencer?: TestSequencerConstructor
491491- /**
492492- * Should tests run in random order.
493493- * @default false
494494- */
495495- shuffle?: boolean
496496- /**
497497- * Defines how setup files should be ordered
498498- * - 'parallel' will run all setup files in parallel
499499- * - 'list' will run all setup files in the order they are defined in the config file
500500- * @default 'parallel'
501501- */
502502- setupFiles?: SequenceSetupFiles
503503- /**
504504- * Seed for the random number generator.
505505- * @default Date.now()
506506- */
507507- seed?: number
508508- /**
509509- * Defines how hooks should be ordered
510510- * - `stack` will order "after" hooks in reverse order, "before" hooks will run sequentially
511511- * - `list` will order hooks in the order they are defined
512512- * - `parallel` will run hooks in a single group in parallel
513513- * @default 'parallel'
514514- */
515515- hooks?: SequenceHooks
516516- }
520520+ sequence?: SequenceOptions
517521518522 /**
519523 * Specifies an `Object`, or an `Array` of `Object`,
···681685 runner?: string
682686}
683687688688+export type ProjectConfig = Omit<
689689+ UserConfig,
690690+ | 'sequencer'
691691+ | 'shard'
692692+ | 'watch'
693693+ | 'run'
694694+ | 'cache'
695695+ | 'update'
696696+ | 'reporters'
697697+ | 'outputFile'
698698+ | 'maxThreads'
699699+ | 'minThreads'
700700+ | 'useAtomics'
701701+ | 'teardownTimeout'
702702+ | 'silent'
703703+ | 'watchExclude'
704704+ | 'forceRerunTriggers'
705705+ | 'testNamePattern'
706706+ | 'ui'
707707+ | 'open'
708708+ | 'uiBase'
709709+ // TODO: allow snapshot options
710710+ | 'snapshotFormat'
711711+ | 'resolveSnapshotPath'
712712+ | 'passWithNoTests'
713713+ | 'onConsoleLog'
714714+ | 'dangerouslyIgnoreUnhandledErrors'
715715+ | 'slowTestThreshold'
716716+ | 'inspect'
717717+ | 'inspectBrk'
718718+ | 'deps'
719719+ | 'coverage'
720720+> & {
721721+ sequencer?: Omit<SequenceOptions, 'sequencer' | 'seed'>
722722+ deps?: Omit<DepsOptions, 'registerNodeLoader'>
723723+}
724724+684725export type RuntimeConfig = Pick<
685726 UserConfig,
686727 | 'allowOnly'
···692733 | 'fakeTimers'
693734 | 'maxConcurrency'
694735> & { sequence?: { hooks?: SequenceHooks } }
736736+737737+export type { UserWorkspaceConfig } from '../config'
···11import { shuffle } from '@vitest/utils'
22+import type { WorkspaceSpec } from '../pool'
23import { BaseSequencer } from './BaseSequencer'
3445export class RandomSequencer extends BaseSequencer {
55- public async sort(files: string[]) {
66+ public async sort(files: WorkspaceSpec[]) {
67 const { sequence } = this.ctx.config
7889 return shuffle(files, sequence.seed)
+3-2
packages/vitest/src/node/sequencers/types.ts
···11import type { Awaitable } from '../../types'
22import type { Vitest } from '../core'
33+import type { WorkspaceSpec } from '../pool'
3445export interface TestSequencer {
56 /**
67 * Slicing tests into shards. Will be run before `sort`.
78 * Only run, if `shard` is defined.
89 */
99- shard(files: string[]): Awaitable<string[]>
1010- sort(files: string[]): Awaitable<string[]>
1010+ shard(files: WorkspaceSpec[]): Awaitable<WorkspaceSpec[]>
1111+ sort(files: WorkspaceSpec[]): Awaitable<WorkspaceSpec[]>
1112}
12131314export interface TestSequencerConstructor {