import { describe, expect, it } from "bun:test"; import { z } from "zod"; import { apiError, bodySchema, querySchema } from "./route-helpers"; describe("route helpers", () => { it("querySchema parses/coerces values", () => { const parseQuery = querySchema( z.object({ sinceId: z.coerce.number().int().nonnegative().default(0), limit: z.coerce.number().int().min(1).max(100).default(20), }) ); const result = parseQuery("?sinceId=10&limit=5"); expect(result).toEqual({ sinceId: 10, limit: 5 }); }); it("querySchema supports defaults", () => { const parseQuery = querySchema( z.object({ limit: z.coerce.number().int().min(1).max(100).default(20), }) ); const result = parseQuery(new URLSearchParams()); expect(result.limit).toBe(20); }); it("bodySchema parses JSON body", async () => { const parseBody = bodySchema( z.object({ text: z.string().min(1), }) ); const request = new Request("http://localhost/api/chat/send", { method: "POST", headers: { "content-type": "application/json" }, body: JSON.stringify({ text: "mandu" }), }); await expect(parseBody(request)).resolves.toEqual({ text: "mandu" }); }); it("bodySchema accepts +json content type", async () => { const parseBody = bodySchema(z.object({ text: z.string() })); const request = new Request("http://localhost/api/chat/send", { method: "POST", headers: { "content-type": "application/problem+json; charset=utf-8" }, body: JSON.stringify({ text: "mandu" }), }); await expect(parseBody(request)).resolves.toEqual({ text: "mandu" }); }); it("bodySchema rejects non-json content type", async () => { const parseBody = bodySchema(z.object({ text: z.string() })); const request = new Request("http://localhost/api/chat/send", { method: "POST", headers: { "content-type": "text/plain" }, body: "text=mandu", }); await expect(parseBody(request)).rejects.toThrow("application/json"); }); it("bodySchema normalizes invalid JSON parse failure", async () => { const parseBody = bodySchema(z.object({ text: z.string() })); const request = new Request("http://localhost/api/chat/send", { method: "POST", headers: { "content-type": "application/json" }, body: "{\"text\":" , }); await expect(parseBody(request)).rejects.toThrow("Request body contains invalid JSON"); }); it("apiError returns standardized payload", async () => { const res = apiError("invalid input", "BAD_REQUEST", { status: 422 }); expect(res.status).toBe(422); await expect(res.json()).resolves.toEqual({ error: "invalid input", code: "BAD_REQUEST", }); }); });