Files

46 lines
1.6 KiB
TypeScript

import { describe, expect, mock, test } from "bun:test";
import z from "zod";
import { formatUnknownError, wrapCommandErrors } from "../../lib/error";
describe("CLI error handling", () => {
test("formats Zod errors without exposing internal parser details", () => {
const error = z.object({ name: z.string() }).safeParse({ name: 1 }).error;
expect(formatUnknownError(error)).toContain("name");
expect(formatUnknownError(error)).toContain("expected string");
});
test("catches errors from nested command handlers before Citty sees them", async () => {
const handleError = mock((_error: unknown) => {});
const command = {
subCommands: {
child: {
async run() {
throw new Error("command failed");
},
},
},
};
wrapCommandErrors(command, handleError);
await expect(command.subCommands.child.run()).resolves.toBeUndefined();
expect(handleError).toHaveBeenCalledTimes(1);
expect(handleError.mock.calls[0]?.[0]).toBeInstanceOf(Error);
expect(String(handleError.mock.calls[0]?.[0])).toContain("command failed");
});
test("formats a dispatched command error once and exits with code 1", async () => {
const process = Bun.spawn(["bun", "index.ts", "exec"], {
cwd: `${import.meta.dir}/../..`,
stdout: "pipe",
stderr: "pipe",
});
const [stderr, exitCode] = await Promise.all([
new Response(process.stderr).text(),
process.exited,
]);
expect(exitCode).toBe(1);
expect(stderr.match(/Deployment name is required/g)).toHaveLength(1);
});
});