Testing
Run oscli flows in Vitest without touching stdin or process.exit.
cli.test() gives you a programmatic harness for the real CLI. It runs the
same code paths, but replaces stdin, stdout, stderr, and process exit behavior
so your tests stay deterministic.
Set binName when you want usage text in snapshots or assertions to match the
real executable name instead of the default test harness name.
Vitest example
import { describe, expect, it } from "vitest";
import { createCLI } from "@oscli-dev/oscli";
describe("init flow", () => {
it("stores the provided project name", async () => {
const cli = createCLI((b) => ({
title: "test",
prompts: {
name: b.text().label("Name"),
},
}));
cli.command("init", async () => {
await cli.prompt.name();
cli.success(`Created ${cli.storage.name}`);
});
const result = await cli.test({
argv: ["init"],
inputs: { name: "my-app" },
});
expect(result.storage.name).toBe("my-app");
expect(result.output).toContain("Created my-app");
expect(result.exitCode).toBe(0);
});
});TestOptions
Prop
Type
TestResult
Prop
Type
Test flow
Use this order when writing tests around a CLI.
Create the CLI in the test
Build the same CLI object you use in production code.
Run cli.test()
Pass inputs, flags, and argv to
drive the flow.
Assert on the result
Check storage, flags, output, and
exitCode directly.
Test mode always behaves like non-TTY output. Prompt summary lines are still written to the captured buffer so you can assert on them.