oscli

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.

Vitest example

tests/cli.test.ts
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) => ({
      description: "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.

On this page