···4545export interface ProcessPool {
4646 name: string
4747 runTests: (files: [project: WorkspaceProject, testFile: string][], invalidates?: string[]) => Promise<void>
4848+ collectTests: (files: [project: WorkspaceProject, testFile: string][], invalidates?: string[]) => Promise<void>
4849 close?: () => Promise<void>
4950}
5051```
···5657Vitest will wait until `runTests` is executed before finishing a run (i.e., it will emit [`onFinished`](/guide/reporters) only after `runTests` is resolved).
57585859If you are using a custom pool, you will have to provide test files and their results yourself - you can reference [`vitest.state`](https://github.com/vitest-dev/vitest/blob/main/packages/vitest/src/node/state.ts) for that (most important are `collectFiles` and `updateTasks`). Vitest uses `startTests` function from `@vitest/runner` package to do that.
6060+6161+Vitest will call `collectTests` if `vitest.collect` is called or `vitest list` is invoked via a CLI command. It works the same way as `runTests`, but you don't have to run test callbacks, only report their tasks by calling `vitest.state.collectFiles(files)`.
59626063To communicate between different processes, you can create methods object using `createMethodsRPC` from `vitest/node`, and use any form of communication that you prefer. For example, to use WebSockets with `birpc` you can write something like this:
6164
+30
docs/guide/cli.md
···55555656Run only [benchmark](https://vitest.dev/guide/features.html#benchmarking-experimental) tests, which compare performance results.
57575858+### `vitest init`
5959+6060+`vitest init <name>` can be used to setup project configuration. At the moment, it only supports [`browser`](/guide/browser) value:
6161+6262+```bash
6363+vitest init browser
6464+```
6565+6666+### `vitest list`
6767+6868+`vitest list` command inherits all `vitest` options to print the list of all matching tests. This command ignores `reporters` option. By default, it will print the names of all tests that matched the file filter and name pattern:
6969+7070+```shell
7171+vitest list filename.spec.ts -t="some-test"
7272+```
7373+7474+```txt
7575+describe > some-test
7676+describe > some-test > test 1
7777+describe > some-test > test 2
7878+```
7979+8080+You can pass down `--json` flag to print tests in JSON format or save it in a separate file:
8181+8282+```bash
8383+vitest list filename.spec.ts -t="some-test" --json=./file.json
8484+```
8585+8686+If `--json` flag doesn't receive a value, it will output the JSON into stdout.
8787+5888## Options
59896090<!--@include: ./cli-table.md-->
-21
packages/vitest/LICENSE.md
···438438By: Mathias Bynens
439439Repository: https://github.com/mathiasbynens/emoji-regex.git
440440441441-> Copyright Mathias Bynens <https://mathiasbynens.be/>
442442->
443443-> Permission is hereby granted, free of charge, to any person obtaining
444444-> a copy of this software and associated documentation files (the
445445-> "Software"), to deal in the Software without restriction, including
446446-> without limitation the rights to use, copy, modify, merge, publish,
447447-> distribute, sublicense, and/or sell copies of the Software, and to
448448-> permit persons to whom the Software is furnished to do so, subject to
449449-> the following conditions:
450450->
451451-> The above copyright notice and this permission notice shall be
452452-> included in all copies or substantial portions of the Software.
453453->
454454-> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
455455-> EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
456456-> MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
457457-> NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
458458-> LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
459459-> OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
460460-> WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
461461-462441---------------------------------------
463442464443## expect-type
···136136 return output()
137137 }
138138139139- if (args.includes('--watch')) {
139139+ if (args[0] !== 'list' && args.includes('--watch')) {
140140 if (command === 'vitest') {
141141 // Wait for initial test run to complete
142142 await cli.waitForStdout('Waiting for file changes')
···44 unwrapSerializableConfig,
55} from './runtime/workers/utils'
66export { provideWorkerState } from './utils/global'
77-export { run as runVitestWorker } from './runtime/worker'
77+export { run as runVitestWorker, collect as collectVitestWorkerTests } from './runtime/worker'
88export { runVmTests } from './runtime/workers/vm'
99export { runBaseTests } from './runtime/workers/base'
1010export type { WorkerRpcOptions, VitestWorker } from './runtime/workers/types'
+174
test/cli/test/list.test.ts
···11+import { readFileSync, rmSync } from 'node:fs'
22+import { expect, onTestFinished, test } from 'vitest'
33+import { runVitestCli } from '../../test-utils'
44+55+test.each([
66+ ['--pool=threads'],
77+ ['--pool=forks'],
88+ ['--pool=vmForks'],
99+ ['--browser.enabled'],
1010+])('correctly outputs all tests with args: "%s"', async (...args) => {
1111+ const { stdout, exitCode } = await runVitestCli('list', '-r=./fixtures/list', ...args)
1212+ expect(stdout).toMatchSnapshot()
1313+ expect(exitCode).toBe(0)
1414+})
1515+1616+test.each([
1717+ ['basic'],
1818+ ['json', '--json'],
1919+ ['json with a file', '--json=./list.json'],
2020+])('%s output shows error', async () => {
2121+ const { stderr, stdout, exitCode } = await runVitestCli('list', '-r=./fixtures/list', '-c=fail.config.ts')
2222+ expect(stdout).toBe('')
2323+ expect(stderr).toMatchSnapshot()
2424+ expect(exitCode).toBe(1)
2525+})
2626+2727+test('correctly outputs json', async () => {
2828+ const { stdout, exitCode } = await runVitestCli('list', '-r=./fixtures/list', '--json')
2929+ expect(relative(stdout)).toMatchInlineSnapshot(`
3030+ "[
3131+ {
3232+ "name": "basic suite > inner suite > some test",
3333+ "file": "<root>/fixtures/list/basic.test.ts"
3434+ },
3535+ {
3636+ "name": "basic suite > inner suite > another test",
3737+ "file": "<root>/fixtures/list/basic.test.ts"
3838+ },
3939+ {
4040+ "name": "basic suite > basic test",
4141+ "file": "<root>/fixtures/list/basic.test.ts"
4242+ },
4343+ {
4444+ "name": "outside test",
4545+ "file": "<root>/fixtures/list/basic.test.ts"
4646+ },
4747+ {
4848+ "name": "1 plus 1",
4949+ "file": "<root>/fixtures/list/math.test.ts"
5050+ },
5151+ {
5252+ "name": "failing test",
5353+ "file": "<root>/fixtures/list/math.test.ts"
5454+ }
5555+ ]
5656+ "
5757+ `)
5858+ expect(exitCode).toBe(0)
5959+})
6060+6161+test('correctly saves json', async () => {
6262+ const { stdout, exitCode } = await runVitestCli('list', '-r=./fixtures/list', '--json=./list.json')
6363+ onTestFinished(() => {
6464+ rmSync('./fixtures/list/list.json')
6565+ })
6666+ const json = readFileSync('./fixtures/list/list.json', 'utf-8')
6767+ expect(stdout).toBe('')
6868+ expect(relative(json)).toMatchInlineSnapshot(`
6969+ "[
7070+ {
7171+ "name": "basic suite > inner suite > some test",
7272+ "file": "<root>/fixtures/list/basic.test.ts"
7373+ },
7474+ {
7575+ "name": "basic suite > inner suite > another test",
7676+ "file": "<root>/fixtures/list/basic.test.ts"
7777+ },
7878+ {
7979+ "name": "basic suite > basic test",
8080+ "file": "<root>/fixtures/list/basic.test.ts"
8181+ },
8282+ {
8383+ "name": "outside test",
8484+ "file": "<root>/fixtures/list/basic.test.ts"
8585+ },
8686+ {
8787+ "name": "1 plus 1",
8888+ "file": "<root>/fixtures/list/math.test.ts"
8989+ },
9090+ {
9191+ "name": "failing test",
9292+ "file": "<root>/fixtures/list/math.test.ts"
9393+ }
9494+ ]"
9595+ `)
9696+ expect(exitCode).toBe(0)
9797+})
9898+9999+test('correctly filters by file', async () => {
100100+ const { stdout, exitCode } = await runVitestCli('list', 'math.test.ts', '-r=./fixtures/list')
101101+ expect(stdout).toMatchInlineSnapshot(`
102102+ "math.test.ts > 1 plus 1
103103+ math.test.ts > failing test
104104+ "
105105+ `)
106106+ expect(exitCode).toBe(0)
107107+})
108108+109109+test('correctly prints project name in basic report', async () => {
110110+ const { stdout } = await runVitestCli('list', 'math.test.ts', '-r=./fixtures/list', '--config=./custom.config.ts')
111111+ expect(stdout).toMatchInlineSnapshot(`
112112+ "[custom] math.test.ts > 1 plus 1
113113+ [custom] math.test.ts > failing test
114114+ "
115115+ `)
116116+})
117117+118118+test('correctly prints project name and locations in json report', async () => {
119119+ const { stdout } = await runVitestCli('list', 'math.test.ts', '-r=./fixtures/list', '--json', '--config=./custom.config.ts')
120120+ expect(relative(stdout)).toMatchInlineSnapshot(`
121121+ "[
122122+ {
123123+ "name": "1 plus 1",
124124+ "file": "<root>/fixtures/list/math.test.ts",
125125+ "projectName": "custom",
126126+ "location": {
127127+ "line": 3,
128128+ "column": 1
129129+ }
130130+ },
131131+ {
132132+ "name": "failing test",
133133+ "file": "<root>/fixtures/list/math.test.ts",
134134+ "projectName": "custom",
135135+ "location": {
136136+ "line": 7,
137137+ "column": 1
138138+ }
139139+ }
140140+ ]
141141+ "
142142+ `)
143143+})
144144+145145+test('correctly filters by test name', async () => {
146146+ const { stdout } = await runVitestCli('list', '-t=inner', '-r=./fixtures/list')
147147+ expect(stdout).toMatchInlineSnapshot(`
148148+ "basic.test.ts > basic suite > inner suite > some test
149149+ basic.test.ts > basic suite > inner suite > another test
150150+ "
151151+ `)
152152+})
153153+154154+test('ignores watch flag', async () => {
155155+ // if it ends, it works - otherwise it will hang
156156+ const { stdout } = await runVitestCli('list', '-r=./fixtures/list', '--watch')
157157+ expect(stdout).toMatchInlineSnapshot(`
158158+ "basic.test.ts > basic suite > inner suite > some test
159159+ basic.test.ts > basic suite > inner suite > another test
160160+ basic.test.ts > basic suite > basic test
161161+ basic.test.ts > outside test
162162+ math.test.ts > 1 plus 1
163163+ math.test.ts > failing test
164164+ "
165165+ `)
166166+})
167167+168168+function relative(stdout: string) {
169169+ return stdout.replace(new RegExp(slash(process.cwd()), 'gi'), '<root>')
170170+}
171171+172172+function slash(stdout: string) {
173173+ return stdout.replace(/\\/g, '/')
174174+}