diff --git a/packages/cli/__tests__/index.test.ts b/packages/cli/__tests__/index.test.ts index 01f781616..fe5b0eb5f 100644 --- a/packages/cli/__tests__/index.test.ts +++ b/packages/cli/__tests__/index.test.ts @@ -1,14 +1,73 @@ -import { describe, expect, it, vi } from "vitest"; +import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; -const parse = vi.fn(); +let parseAsync: ReturnType; -vi.mock("../src/program.js", () => ({ - createProgram: () => ({ parse }), -})); +beforeEach(() => { + vi.resetModules(); + parseAsync = vi.fn().mockResolvedValue(undefined); + vi.doMock("../src/program.js", () => ({ + createProgram: () => ({ parseAsync }), + })); +}); + +afterEach(() => { + vi.restoreAllMocks(); +}); describe("cli entrypoint", () => { it("parses the created program", async () => { await import("../src/index.js"); - expect(parse).toHaveBeenCalledOnce(); + expect(parseAsync).toHaveBeenCalledOnce(); + }); + + it("prints a clean message and exits 1 on ConfigNotFoundError", async () => { + const { ConfigNotFoundError } = await import("@composio/ao-core"); + const error = new ConfigNotFoundError(); + let rejectionHandler: + | ((reason: unknown) => unknown) + | undefined; + + parseAsync.mockImplementation( + () => + ({ + catch: (handler: (reason: unknown) => unknown) => { + rejectionHandler = handler; + }, + }) as Promise, + ); + + const errorSpy = vi.spyOn(console, "error").mockImplementation(() => {}); + const exitSpy = vi + .spyOn(process, "exit") + .mockImplementation(() => undefined as never); + + await import("../src/index.js"); + + expect(rejectionHandler).toBeTypeOf("function"); + rejectionHandler?.(error); + + expect(errorSpy).toHaveBeenCalledWith(`Error: ${error.message}`); + expect(exitSpy).toHaveBeenCalledWith(1); + }); + + it("re-throws non-ConfigNotFoundError errors", async () => { + const error = new Error("unexpected"); + let rejectionHandler: + | ((reason: unknown) => unknown) + | undefined; + + parseAsync.mockImplementation( + () => + ({ + catch: (handler: (reason: unknown) => unknown) => { + rejectionHandler = handler; + }, + }) as Promise, + ); + + await import("../src/index.js"); + + expect(rejectionHandler).toBeTypeOf("function"); + expect(() => rejectionHandler?.(error)).toThrow(error); }); }); diff --git a/packages/cli/src/index.ts b/packages/cli/src/index.ts index b7791ffbc..fb2b54723 100644 --- a/packages/cli/src/index.ts +++ b/packages/cli/src/index.ts @@ -1,5 +1,15 @@ #!/usr/bin/env node +import { ConfigNotFoundError } from "@composio/ao-core"; import { createProgram } from "./program.js"; -createProgram().parse(); +createProgram() + .parseAsync() + .catch((err) => { + if (err instanceof ConfigNotFoundError) { + console.error(`Error: ${err.message}`); + process.exit(1); + return; + } + throw err; + });