Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(cli): improve cac errors when mixing boolean and dot notation #3302

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
28 changes: 27 additions & 1 deletion packages/vitest/src/node/cli.ts
Expand Up @@ -77,7 +77,33 @@ cli
.command('[...filters]')
.action((filters, options) => start('test', filters, options))

cli.parse()
try {
cli.parse()
}
catch (originalError) {
// CAC may fail to parse arguments when boolean flags and dot notation are mixed
// e.g. "--coverage --coverage.reporter text" will fail, when "--coverage.enabled --coverage.reporter text" will pass
const fullArguments = cli.rawArgs.join(' ')
const conflictingArgs: { arg: string; dotArgs: string[] }[] = []

for (const arg of cli.rawArgs) {
if (arg.startsWith('--') && !arg.includes('.') && fullArguments.includes(`${arg}.`)) {
const dotArgs = cli.rawArgs.filter(rawArg => rawArg.startsWith(arg) && rawArg.includes('.'))
conflictingArgs.push({ arg, dotArgs })
}
}

if (conflictingArgs.length === 0)
throw originalError

const error = conflictingArgs
.map(({ arg, dotArgs }) =>
`A boolean argument "${arg}" was used with dot notation arguments "${dotArgs.join(' ')}".`
+ `\nPlease specify the "${arg}" argument with dot notation as well: "${arg}.enabled"`)
.join('\n')

throw new Error(error)
}

async function runRelated(relatedFiles: string[] | string, argv: CliOptions): Promise<void> {
argv.related = relatedFiles
Expand Down
14 changes: 14 additions & 0 deletions test/config/test/failures.test.ts
Expand Up @@ -43,3 +43,17 @@ test('c8 coverage provider cannot be used with browser', async () => {

expect(error).toMatch('Error: @vitest/coverage-c8 does not work with --browser. Use @vitest/coverage-istanbul instead')
})

test('boolean coverage flag without dot notation, with more dot notation options', async () => {
const { error } = await runVitest('run', ['--coverage', '--coverage.reporter', 'text'])

expect(error).toMatch('Error: A boolean argument "--coverage" was used with dot notation arguments "--coverage.reporter".')
expect(error).toMatch('Please specify the "--coverage" argument with dot notation as well: "--coverage.enabled"')
})

test('boolean browser flag without dot notation, with more dot notation options', async () => {
const { error } = await runVitest('run', ['--browser', '--browser.name', 'chrome'])

expect(error).toMatch('Error: A boolean argument "--browser" was used with dot notation arguments "--browser.name".')
expect(error).toMatch('Please specify the "--browser" argument with dot notation as well: "--browser.enabled"')
})
2 changes: 1 addition & 1 deletion test/config/test/utils.ts
Expand Up @@ -6,7 +6,7 @@ export async function runVitest(mode: 'run' | 'watch', cliArguments: string[]) {
let error = ''

subprocess.stderr?.on('data', (data) => {
error = stripAnsi(data.toString())
error += stripAnsi(data.toString())

// Sometimes on Windows CI execa doesn't exit properly. Force exit when stderr is caught.
subprocess.kill()
Expand Down
3 changes: 3 additions & 0 deletions test/config/vitest.config.ts
Expand Up @@ -3,5 +3,8 @@ import { defineConfig } from 'vitest/config'
export default defineConfig({
test: {
testTimeout: 60_000,
chaiConfig: {
truncateThreshold: 999,
},
},
})