Skip to content

Commit 201bd06

Browse files
authoredMar 14, 2024··
feat(cli): support wildcards in --project option (#5295)
1 parent 600b44d commit 201bd06

File tree

10 files changed

+63
-7
lines changed

10 files changed

+63
-7
lines changed
 

‎docs/guide/cli.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ Run only [benchmark](https://vitest.dev/guide/features.html#benchmarking-experim
106106
| `--typecheck [options]` | Custom options for typecheck pool. If passed without options, enables typechecking |
107107
| `--typecheck.enabled` | Enable typechecking alongside tests (default: `false`) |
108108
| `--typecheck.only` | Run only typecheck tests. This automatically enables typecheck (default: `false`) |
109-
| `--project` | The name of the project to run if you are using Vitest workspace feature. This can be repeated for multiple projects: `--project=1 --project=2` |
109+
| `--project` | The name of the project to run if you are using Vitest workspace feature. This can be repeated for multiple projects: `--project=1 --project=2`. You can also filter projects using wildcards like `--project=packages*` |
110110
| `-h, --help` | Display available CLI options |
111111

112112
::: tip

‎packages/vitest/src/node/cli/cli-config.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -524,7 +524,7 @@ export const cliOptionsConfig: VitestCLIOptions = {
524524
},
525525
},
526526
project: {
527-
description: 'The name of the project to run if you are using Vitest workspace feature. This can be repeated for multiple projects: --project=1 --project=2',
527+
description: 'The name of the project to run if you are using Vitest workspace feature. This can be repeated for multiple projects: --project=1 --project=2. You can also filter projects using wildcards like --project=packages*',
528528
argument: '<name>',
529529
array: true,
530530
},

‎packages/vitest/src/node/core.ts

+8-5
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import type { CancelReason, File } from '@vitest/runner'
1111
import { ViteNodeServer } from 'vite-node/server'
1212
import type { defineWorkspace } from 'vitest/config'
1313
import type { ArgumentsType, CoverageProvider, OnServerRestartHandler, Reporter, ResolvedConfig, UserConfig, UserWorkspaceConfig, VitestRunMode } from '../types'
14-
import { hasFailed, noop, slash, toArray } from '../utils'
14+
import { hasFailed, noop, slash, toArray, wildcardPatternToRegExp } from '../utils'
1515
import { getCoverageProvider } from '../integrations/coverage'
1616
import type { BrowserProvider } from '../types/browser'
1717
import { CONFIG_NAMES, configFiles, workspacesFiles as workspaceFiles } from '../constants'
@@ -161,11 +161,14 @@ export class Vitest {
161161
await Promise.all(this._onSetServer.map(fn => fn()))
162162

163163
const projects = await this.resolveWorkspace(cliOptions)
164-
this.projects = projects
165164
this.resolvedProjects = projects
166-
const filteredProjects = toArray(resolved.project)
167-
if (filteredProjects.length)
168-
this.projects = this.projects.filter(p => filteredProjects.includes(p.getName()))
165+
this.projects = projects
166+
const filters = toArray(resolved.project).map(s => wildcardPatternToRegExp(s))
167+
if (filters.length > 0) {
168+
this.projects = this.projects.filter(p =>
169+
filters.some(pattern => pattern.test(p.getName())),
170+
)
171+
}
169172
if (!this.coreWorkspaceProject)
170173
this.coreWorkspaceProject = WorkspaceProject.createBasicProject(this)
171174

‎packages/vitest/src/utils/base.ts

+9
Original file line numberDiff line numberDiff line change
@@ -160,3 +160,12 @@ export function setProcessTitle(title: string) {
160160
}
161161
catch {}
162162
}
163+
164+
export function escapeRegExp(s: string) {
165+
// From https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions#escaping
166+
return s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&') // $& means the whole matched string
167+
}
168+
169+
export function wildcardPatternToRegExp(pattern: string): RegExp {
170+
return new RegExp(`^${pattern.split('*').map(escapeRegExp).join('.*')}$`, 'i')
171+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import { expect, test } from "vitest";
2+
3+
test("", () => {
4+
expect(1).toBe(1);
5+
})
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import { expect, test } from "vitest";
2+
3+
test("", () => {
4+
expect(1).toBe(1);
5+
})
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import { expect, test } from "vitest";
2+
3+
test("", () => {
4+
expect(1).toBe(1);
5+
})
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
import { defineConfig } from "vitest/config";
2+
3+
export default defineConfig({})
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export default [
2+
'packages/*'
3+
]

‎test/cli/test/project.test.ts

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import { expect, test } from 'vitest'
2+
import { runVitestCli } from '../../test-utils'
3+
4+
test.each([
5+
{ pattern: 'project_1', expected: ['project_1'] },
6+
{ pattern: '*', expected: ['project_1', 'project_2', 'space_1'] },
7+
{ pattern: '*j*', expected: ['project_1', 'project_2'] },
8+
{ pattern: 'project*', expected: ['project_1', 'project_2'] },
9+
{ pattern: 'space*', expected: ['space_1'] },
10+
])('should match projects correctly: $pattern', async ({ pattern, expected }) => {
11+
const { stdout, stderr } = await runVitestCli(
12+
'run',
13+
'--root',
14+
'fixtures/project',
15+
'--project',
16+
pattern,
17+
)
18+
19+
expect(stderr).toBeFalsy()
20+
expect(stdout).toBeTruthy()
21+
22+
expected.forEach(name => expect(stdout).toContain(name))
23+
})

0 commit comments

Comments
 (0)
Please sign in to comment.