Skip to content

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

OptionTypeDescription
envRecord<string, string | undefined>Environment variables
configRecord<string, unknown>Config file values
stdinDatastring | nullData supplied to command stdin for .stdin() args
answersunknown[]Prompt answers in order
prompterPromptEngineCustom prompt handler
jsonModebooleanSimulate --json mode
helpHelpOptionsHelp formatting options
verbosityVerbosityOutput verbosity level
isTTYbooleanSimulate 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 RunOptions injection instead of vi.mock()
  • No process.argv — everything is passed as parameters

What's Next?

Released under the MIT License.