Skip to content

testCommand()

function testCommand(
command: cli.Command,
argv: string,
config?: Record<string, any>
): Promise<{ result: any; messages: string; exitCode: number | undefined }>

Runs a single command against a throwaway CLI (test-cli, version 1.0.0) and returns what it did. No process is spawned and no config file is read.

import { command, testCommand } from 'clibuilder'
const { result, messages } = await testCommand(
command({
name: 'cmd-a',
description: 'a command',
run() {
this.ui.info('miku')
return 'x'
}
}),
'cmd-a'
)
expect(result).toBe('x')
expect(messages).toBe('miku')
Parameter Type Description
command cli.Command The command to run. Sub-commands come along with it.
argv string The command line after the CLI name — 'cmd-a --flag value'.
config Record<string, any> Optional. Stands in for the config file the command would have loaded. Still validated against the command’s config schema.
Field Type Description
result any What run() returned or resolved to.
messages string Everything written through this.uiinfo, warn, and error — joined with \n. Empty when nothing was printed.
exitCode number | undefined The code the cli would have exited with, or undefined when it did not fail.

The display level is info, so this.ui.debug() output does not appear in messages unless the argv you pass includes --verbose.

Address a nested command by its full path:

const repo = command({
name: 'repo',
description: 'manage repositories',
commands: [create, remove]
})
const { messages } = await testCommand(repo, 'repo create my-project')
const { result } = await testCommand(
command({
name: 'cfg',
description: 'reads config',
config: z.object({ a: z.string() }),
run() {
return this.config
}
}),
'cfg',
{ a: 'hi' }
)
expect(result).toEqual({ a: 'hi' })

Passing a config that fails the schema is how you test the failure path — result is undefined, exitCode is 1, and messages carries the validation errors and the help message.

Failures don’t reject — they are reported and recorded. Assert on exitCode and messages:

const { result, messages, exitCode } = await testCommand(cmd, 'cmd --unknown-flag')
expect(result).toBeUndefined()
expect(exitCode).toBe(2)
expect(messages).toContain('unknown option --unknown-flag')

A command that throws CliError is recorded the same way, with the code it chose.

See Testing for the wider picture, including injecting fakes through a command’s context.