Files
paperclip/cli/src/__tests__/http.test.ts

62 lines
2.0 KiB
TypeScript

import { afterEach, describe, expect, it, vi } from "vitest";
import { ApiRequestError, PaperclipApiClient } from "../client/http.js";
describe("PaperclipApiClient", () => {
afterEach(() => {
vi.restoreAllMocks();
});
it("adds authorization and run-id headers", async () => {
const fetchMock = vi.fn().mockResolvedValue(
new Response(JSON.stringify({ ok: true }), { status: 200 }),
);
vi.stubGlobal("fetch", fetchMock);
const client = new PaperclipApiClient({
apiBase: "http://localhost:3100",
apiKey: "token-123",
runId: "run-abc",
});
await client.post("/api/test", { hello: "world" });
expect(fetchMock).toHaveBeenCalledTimes(1);
const call = fetchMock.mock.calls[0] as [string, RequestInit];
expect(call[0]).toContain("/api/test");
const headers = call[1].headers as Record<string, string>;
expect(headers.authorization).toBe("Bearer token-123");
expect(headers["x-paperclip-run-id"]).toBe("run-abc");
expect(headers["content-type"]).toBe("application/json");
});
it("returns null on ignoreNotFound", async () => {
const fetchMock = vi.fn().mockResolvedValue(
new Response(JSON.stringify({ error: "Not found" }), { status: 404 }),
);
vi.stubGlobal("fetch", fetchMock);
const client = new PaperclipApiClient({ apiBase: "http://localhost:3100" });
const result = await client.get("/api/missing", { ignoreNotFound: true });
expect(result).toBeNull();
});
it("throws ApiRequestError with details", async () => {
const fetchMock = vi.fn().mockResolvedValue(
new Response(
JSON.stringify({ error: "Issue checkout conflict", details: { issueId: "1" } }),
{ status: 409 },
),
);
vi.stubGlobal("fetch", fetchMock);
const client = new PaperclipApiClient({ apiBase: "http://localhost:3100" });
await expect(client.post("/api/issues/1/checkout", {})).rejects.toMatchObject({
status: 409,
message: "Issue checkout conflict",
details: { issueId: "1" },
} satisfies Partial<ApiRequestError>);
});
});