Skip to content

Commit

Permalink
feat(vitest): expose parseCLI method (#5248)
Browse files Browse the repository at this point in the history
  • Loading branch information
sheremet-va committed Feb 20, 2024
1 parent 28f22b9 commit c793a13
Show file tree
Hide file tree
Showing 4 changed files with 119 additions and 8 deletions.
10 changes: 10 additions & 0 deletions docs/advanced/api.md
Expand Up @@ -46,6 +46,16 @@ const vitest = await createVitest('test', {
})
```
## parseCLI
You can use this method to parse CLI arguments. It accepts a string (where arguments are split by a single space) or a strings array of CLI arguments in the same format that Vitest CLI uses. It returns a filter and `options` that you can later pass down to `createVitest` or `startVitest` methods.
```ts
import { parseCLI } from 'vitest/node'

parseCLI('vitest ./files.ts --coverage --browser=chrome')
```
## Vitest
Vitest instance requires the current test mode. It can be either:
Expand Down
45 changes: 38 additions & 7 deletions packages/vitest/src/node/cli/cac.ts
Expand Up @@ -54,7 +54,11 @@ function addCommand(cli: CAC, name: string, option: CLIOption<any>) {
}
}

export function createCLI() {
interface CLIOptions {
allowUnknownOptions?: boolean
}

export function createCLI(options: CLIOptions = {}) {
const cli = cac('vitest')

cli
Expand Down Expand Up @@ -141,23 +145,23 @@ export function createCLI() {
})

cli
.command('run [...filters]')
.command('run [...filters]', undefined, options)
.action(run)

cli
.command('related [...filters]')
.command('related [...filters]', undefined, options)
.action(runRelated)

cli
.command('watch [...filters]')
.command('watch [...filters]', undefined, options)
.action(watch)

cli
.command('dev [...filters]')
.command('dev [...filters]', undefined, options)
.action(watch)

cli
.command('bench [...filters]')
.command('bench [...filters]', undefined, options)
.action(benchmark)

// TODO: remove in Vitest 2.0
Expand All @@ -168,12 +172,39 @@ export function createCLI() {
})

cli
.command('[...filters]')
.command('[...filters]', undefined, options)
.action((filters, options) => start('test', filters, options))

return cli
}

export function parseCLI(argv: string | string[], config: CLIOptions = {}): {
filter: string[]
options: CliOptions
} {
const arrayArgs = typeof argv === 'string' ? argv.split(' ') : argv
if (arrayArgs[0] !== 'vitest')
throw new Error(`Expected "vitest" as the first argument, received "${arrayArgs[0]}"`)
arrayArgs[0] = '/index.js'
arrayArgs.unshift('node')
let { args, options } = createCLI(config).parse(arrayArgs, {
run: false,
})
if (arrayArgs[2] === 'watch' || arrayArgs[2] === 'dev')
options.watch = true
if (arrayArgs[2] === 'run')
options.run = true
if (arrayArgs[2] === 'related') {
options.related = args
options.passWithNoTests ??= true
args = []
}
return {
filter: args as string[],
options,
}
}

async function runRelated(relatedFiles: string[] | string, argv: CliOptions): Promise<void> {
argv.related = relatedFiles
argv.passWithNoTests ??= true
Expand Down
1 change: 1 addition & 0 deletions packages/vitest/src/node/index.ts
Expand Up @@ -3,6 +3,7 @@ export type { WorkspaceProject } from './workspace'
export { createVitest } from './create'
export { VitestPlugin } from './plugins'
export { startVitest } from './cli/cli-api'
export { parseCLI } from './cli/cac'
export { registerConsoleShortcuts } from './stdin'
export type { GlobalSetupContext } from './globalSetup'
export type { WorkspaceSpec, ProcessPool } from './pool'
Expand Down
71 changes: 70 additions & 1 deletion test/core/test/cli-test.test.ts
@@ -1,5 +1,5 @@
import { expect, test } from 'vitest'
import { createCLI } from '../../../packages/vitest/src/node/cli/cac.js'
import { createCLI, parseCLI } from '../../../packages/vitest/src/node/cli/cac.js'

const vitestCli = createCLI()

Expand Down Expand Up @@ -253,3 +253,72 @@ test('browser by name', () => {
expect(args).toEqual([])
expect(options).toEqual({ browser: { enabled: true, name: 'firefox' } })
})

test('public parseCLI works correctly', () => {
expect(parseCLI('vitest dev')).toEqual({
filter: [],
options: {
'watch': true,
'--': [],
'color': true,
},
})
expect(parseCLI('vitest watch')).toEqual({
filter: [],
options: {
'watch': true,
'--': [],
'color': true,
},
})
expect(parseCLI('vitest run')).toEqual({
filter: [],
options: {
'run': true,
'--': [],
'color': true,
},
})
expect(parseCLI('vitest related ./some-files.js')).toEqual({
filter: [],
options: {
'passWithNoTests': true,
'related': ['./some-files.js'],
'--': [],
'color': true,
},
})

expect(parseCLI('vitest --coverage --browser=chrome')).toEqual({
filter: [],
options: {
'coverage': { enabled: true },
'browser': { enabled: true, name: 'chrome' },
'--': [],
'color': true,
},
})

expect(parseCLI('vitest ./tests.js --coverage')).toEqual({
filter: ['./tests.js'],
options: {
'coverage': { enabled: true },
'--': [],
'color': true,
},
})

expect(parseCLI('vitest ./tests.js --coverage --custom-options', { allowUnknownOptions: true })).toEqual({
filter: ['./tests.js'],
options: {
'coverage': { enabled: true },
'customOptions': true,
'--': [],
'color': true,
},
})

expect(() => {
parseCLI('node --test --coverage --browser --typecheck')
}).toThrowError(`Expected "vitest" as the first argument, received "node"`)
})

0 comments on commit c793a13

Please sign in to comment.