Skip to content

Commit

Permalink
feat(cli): support wildcards in --project option (#5295)
Browse files Browse the repository at this point in the history
  • Loading branch information
fenghan34 committed Mar 14, 2024
1 parent 600b44d commit 201bd06
Show file tree
Hide file tree
Showing 10 changed files with 63 additions and 7 deletions.
2 changes: 1 addition & 1 deletion docs/guide/cli.md
Expand Up @@ -106,7 +106,7 @@ Run only [benchmark](https://vitest.dev/guide/features.html#benchmarking-experim
| `--typecheck [options]` | Custom options for typecheck pool. If passed without options, enables typechecking |
| `--typecheck.enabled` | Enable typechecking alongside tests (default: `false`) |
| `--typecheck.only` | Run only typecheck tests. This automatically enables typecheck (default: `false`) |
| `--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` |
| `--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*` |
| `-h, --help` | Display available CLI options |

::: tip
Expand Down
2 changes: 1 addition & 1 deletion packages/vitest/src/node/cli/cli-config.ts
Expand Up @@ -524,7 +524,7 @@ export const cliOptionsConfig: VitestCLIOptions = {
},
},
project: {
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',
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*',
argument: '<name>',
array: true,
},
Expand Down
13 changes: 8 additions & 5 deletions packages/vitest/src/node/core.ts
Expand Up @@ -11,7 +11,7 @@ import type { CancelReason, File } from '@vitest/runner'
import { ViteNodeServer } from 'vite-node/server'
import type { defineWorkspace } from 'vitest/config'
import type { ArgumentsType, CoverageProvider, OnServerRestartHandler, Reporter, ResolvedConfig, UserConfig, UserWorkspaceConfig, VitestRunMode } from '../types'
import { hasFailed, noop, slash, toArray } from '../utils'
import { hasFailed, noop, slash, toArray, wildcardPatternToRegExp } from '../utils'
import { getCoverageProvider } from '../integrations/coverage'
import type { BrowserProvider } from '../types/browser'
import { CONFIG_NAMES, configFiles, workspacesFiles as workspaceFiles } from '../constants'
Expand Down Expand Up @@ -161,11 +161,14 @@ export class Vitest {
await Promise.all(this._onSetServer.map(fn => fn()))

const projects = await this.resolveWorkspace(cliOptions)
this.projects = projects
this.resolvedProjects = projects
const filteredProjects = toArray(resolved.project)
if (filteredProjects.length)
this.projects = this.projects.filter(p => filteredProjects.includes(p.getName()))
this.projects = projects
const filters = toArray(resolved.project).map(s => wildcardPatternToRegExp(s))
if (filters.length > 0) {
this.projects = this.projects.filter(p =>
filters.some(pattern => pattern.test(p.getName())),
)
}
if (!this.coreWorkspaceProject)
this.coreWorkspaceProject = WorkspaceProject.createBasicProject(this)

Expand Down
9 changes: 9 additions & 0 deletions packages/vitest/src/utils/base.ts
Expand Up @@ -160,3 +160,12 @@ export function setProcessTitle(title: string) {
}
catch {}
}

export function escapeRegExp(s: string) {
// From https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions#escaping
return s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&') // $& means the whole matched string
}

export function wildcardPatternToRegExp(pattern: string): RegExp {
return new RegExp(`^${pattern.split('*').map(escapeRegExp).join('.*')}$`, 'i')
}
5 changes: 5 additions & 0 deletions test/cli/fixtures/project/packages/project_1/base.test.ts
@@ -0,0 +1,5 @@
import { expect, test } from "vitest";

test("", () => {
expect(1).toBe(1);
})
5 changes: 5 additions & 0 deletions test/cli/fixtures/project/packages/project_2/base.test.ts
@@ -0,0 +1,5 @@
import { expect, test } from "vitest";

test("", () => {
expect(1).toBe(1);
})
5 changes: 5 additions & 0 deletions test/cli/fixtures/project/packages/space_1/base.test.ts
@@ -0,0 +1,5 @@
import { expect, test } from "vitest";

test("", () => {
expect(1).toBe(1);
})
3 changes: 3 additions & 0 deletions test/cli/fixtures/project/vitest.config.ts
@@ -0,0 +1,3 @@
import { defineConfig } from "vitest/config";

export default defineConfig({})
3 changes: 3 additions & 0 deletions test/cli/fixtures/project/vitest.workspace.ts
@@ -0,0 +1,3 @@
export default [
'packages/*'
]
23 changes: 23 additions & 0 deletions test/cli/test/project.test.ts
@@ -0,0 +1,23 @@
import { expect, test } from 'vitest'
import { runVitestCli } from '../../test-utils'

test.each([
{ pattern: 'project_1', expected: ['project_1'] },
{ pattern: '*', expected: ['project_1', 'project_2', 'space_1'] },
{ pattern: '*j*', expected: ['project_1', 'project_2'] },
{ pattern: 'project*', expected: ['project_1', 'project_2'] },
{ pattern: 'space*', expected: ['space_1'] },
])('should match projects correctly: $pattern', async ({ pattern, expected }) => {
const { stdout, stderr } = await runVitestCli(
'run',
'--root',
'fixtures/project',
'--project',
pattern,
)

expect(stderr).toBeFalsy()
expect(stdout).toBeTruthy()

expected.forEach(name => expect(stdout).toContain(name))
})

0 comments on commit 201bd06

Please sign in to comment.