feat: add extensive test suite
This commit is contained in:
@@ -0,0 +1,107 @@
|
||||
import { describe, expect, mock, test } from "bun:test";
|
||||
import { checkSlip } from "./payment";
|
||||
|
||||
describe("checkSlip", () => {
|
||||
test("posts the image, amount, and authorization to the configured API", async () => {
|
||||
const payload = { success: true, data: { amount: 125.5 } };
|
||||
const fetcher = mock(async () => Response.json(payload));
|
||||
|
||||
const result = await checkSlip(Buffer.from([0, 1, 2]), "image/png", 125.5, {
|
||||
fetch: fetcher as unknown as typeof fetch,
|
||||
apiUrl: "https://slip.test/check",
|
||||
apiKey: "secret",
|
||||
});
|
||||
|
||||
expect(result as unknown).toEqual(payload);
|
||||
expect(fetcher).toHaveBeenCalledTimes(1);
|
||||
const [url, init] = fetcher.mock.calls[0] as unknown as [
|
||||
string,
|
||||
RequestInit,
|
||||
];
|
||||
expect(url).toBe("https://slip.test/check");
|
||||
expect(init.method).toBe("POST");
|
||||
expect(init.headers).toEqual({ "x-authorization": "secret" });
|
||||
expect(init.body).toBeInstanceOf(FormData);
|
||||
|
||||
const body = init.body as FormData;
|
||||
expect(body.get("amount")).toBe("125.5");
|
||||
const image = body.get("files");
|
||||
expect(image).toBeInstanceOf(File);
|
||||
expect(image).toMatchObject({ name: "image", type: "image/png", size: 3 });
|
||||
expect([...new Uint8Array(await (image as File).arrayBuffer())]).toEqual([
|
||||
0, 1, 2,
|
||||
]);
|
||||
});
|
||||
|
||||
test.each([
|
||||
[0, "0"],
|
||||
[-10, "-10"],
|
||||
[Number.NaN, "NaN"],
|
||||
])("serializes amount %p as %s", async (amount, expected) => {
|
||||
const fetcher = mock(async (_url: unknown, init?: RequestInit) => {
|
||||
expect((init?.body as FormData).get("amount")).toBe(expected);
|
||||
return Response.json({});
|
||||
});
|
||||
await checkSlip(Buffer.from([]), "image/jpeg", amount, {
|
||||
fetch: fetcher as unknown as typeof fetch,
|
||||
apiUrl: "https://slip.test",
|
||||
apiKey: "key",
|
||||
});
|
||||
});
|
||||
|
||||
test("returns JSON even when the HTTP response is unsuccessful", async () => {
|
||||
const payload = {
|
||||
success: false,
|
||||
code: 1001,
|
||||
message: "invalid slip",
|
||||
} as const;
|
||||
const fetcher = mock(async () => Response.json(payload, { status: 422 }));
|
||||
expect(
|
||||
await checkSlip(Buffer.from([]), "image/jpeg", 1, {
|
||||
fetch: fetcher as unknown as typeof fetch,
|
||||
apiUrl: "https://slip.test",
|
||||
}),
|
||||
).toEqual(payload);
|
||||
});
|
||||
|
||||
test("propagates fetch failures", async () => {
|
||||
const failure = new Error("offline");
|
||||
const fetcher = mock(async () => {
|
||||
throw failure;
|
||||
});
|
||||
expect(
|
||||
checkSlip(Buffer.from([]), "image/jpeg", 1, {
|
||||
fetch: fetcher as unknown as typeof fetch,
|
||||
apiUrl: "https://slip.test",
|
||||
}),
|
||||
).rejects.toBe(failure);
|
||||
});
|
||||
|
||||
test("propagates invalid JSON responses", async () => {
|
||||
const fetcher = mock(async () => new Response("not json"));
|
||||
expect(
|
||||
checkSlip(Buffer.from([]), "image/jpeg", 1, {
|
||||
fetch: fetcher as unknown as typeof fetch,
|
||||
apiUrl: "https://slip.test",
|
||||
}),
|
||||
).rejects.toBeInstanceOf(SyntaxError);
|
||||
});
|
||||
|
||||
test("fails before fetching when no API URL is configured", async () => {
|
||||
const original = process.env.SLIPOK_API_URL;
|
||||
const fetcher = mock(async () => Response.json({}));
|
||||
delete process.env.SLIPOK_API_URL;
|
||||
|
||||
try {
|
||||
expect(
|
||||
checkSlip(Buffer.from([]), "image/jpeg", 1, {
|
||||
fetch: fetcher as unknown as typeof fetch,
|
||||
}),
|
||||
).rejects.toThrow("SLIPOK_API_URL is not configured");
|
||||
expect(fetcher).not.toHaveBeenCalled();
|
||||
} finally {
|
||||
if (original === undefined) delete process.env.SLIPOK_API_URL;
|
||||
else process.env.SLIPOK_API_URL = original;
|
||||
}
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user