Testing
Test command results, terminal behavior, and prompts.
Use run() for values and errors, captureExecute() for what a terminal user sees, and runInteractive() for prompts.
npm install -D @crustjs/testing@crustjs/testing requires @crustjs/core as a peer. runInteractive() lives in @crustjs/testing/interactive and also needs @crustjs/prompts; install it if your project does not already use it.
Inspect values and errors
const app = new Crust("app").action(({ stdout }) => {
stdout("first\nsecond");
return 3;
});
test("returns output and the action result", async () => {
const outcome = await app.run([]);
expect(outcome.stdout).toBe("first\nsecond");
expect(outcome.status).toBe("completed");
if (outcome.status === "completed") expect(outcome.result).toBe(3);
});run() answers whether a Command Action completed, finished early, or failed, and captures its result, error, stdout, and stderr. Use it for tests and embedding; see the full run() contract.
When many tests target one subcommand, bind it once with app.at(path) and call handle.run(input?, io?) with the same typed input and outcome.
Capture terminal behavior
test("captures terminal errors", async () => {
const result = await captureExecute(app, ["--unknown"]);
expect(result.stdout).toBe("");
expect(result.stderr).toContain("Unknown flag");
expect(result.exitCode).toBe(1);
});captureExecute() answers what execute() would print and which exit code it would set. It includes Extension error rendering and restores the prior process exit state after the test; see the captureExecute() reference.
Drive prompts
const greeting = new Crust("greet").action(async ({ stderr }) => {
const name = await input({ message: "Name?" });
stderr(`Hello, ${name}!`);
});
test("drives a prompt", async () => {
const run = runInteractive(greeting, []);
await run.waitFor(/Name\?/);
run.type("Ada");
run.keys("return");
await run.done;
expect(run.screen()).toContain("Name? Ada");
expect(run.screen()).toContain("Hello, Ada!");
});runInteractive() answers what a user sees while a built-in prompt reads fake terminal input. screen() contains prompt, progress, and stderr output, while stdout remains available from run(); see the runInteractive() reference.