Testing
dreamcli's test harness runs commands in-process with full control over inputs and outputs. No subprocesses, no process.argv mutation, no mocking.
Basic Usage
ts
import { } from '@kjanat/dreamcli/testkit';
const = await (, ['Alice', '--loud']);
(.).(0);
(.).(['HELLO, ALICE!\n']);
(.).([]);
(.).();RunOptions
Control every dimension of CLI behavior from tests:
ts
import { } from '@kjanat/dreamcli/testkit';
await (, ['production'], {
// environment variables
: { : 'eu' },
});
await (, ['production'], {
// config file values
: { : { : 'us' } },
});
await (, ['production'], {
// prompt answers (consumed in order)
: ['ap'],
});
await (, ['production'], {
// piped stdin for args configured with .stdin()
: '<your input>',
// simulate --json mode
: true,
// verbosity level
: 'quiet',
// simulate TTY output
: true,
});Available Options
| Option | Type | Description |
|---|---|---|
env | Record<string, string | undefined> | Environment variables |
config | Record<string, unknown> | Config file values |
stdinData | string | null | Data supplied to command stdin for .stdin() args |
answers | unknown[] | Prompt answers in order |
prompter | PromptEngine | Custom prompt handler |
jsonMode | boolean | Simulate --json mode |
help | HelpOptions | Help formatting options |
verbosity | Verbosity | Output verbosity level |
isTTY | boolean | Simulate a TTY stdout connection |
Testing Prompts
ts
import {
,
,
,
} from '@kjanat/dreamcli/testkit';
// Sequential answers
await (, [], {
: ['eu'],
});
// Simulate prompt cancellation
await (, [], {
: ([]),
});Asserting Activity Events
Spinners and progress bars emit testable events:
ts
import { } from '@kjanat/dreamcli/testkit';
const = await (, []);
(.).(
.({ : 'spinner:start' }),
);
(.).(
.({ : 'spinner:succeed' }),
);Captured Output
ts
import type { RunResult } from '@kjanat/dreamcli/testkit';
type = <
RunResult,
'stdout' | 'stderr' | 'exitCode' | 'error'
>;
declare const : ;
activity is tracked separately from captured output and is covered in the section above.
Design Philosophy
- No lifecycle hooks — isolation comes from the testkit architecture
- No snapshots — all assertions are explicit
- No mocking — use
RunOptionsinjection instead ofvi.mock() - No
process.argv— everything is passed as parameters