- fix(studio): stop markBatchDone infinite recursion so batches complete - refactor(api): merge api-response into api and drop the duplicate module - refactor(media): extract shared media loader and URL validator - refactor(ui): extract shared LoadingSpinner for site and admin groups - refactor(dates): consolidate raw date formatting into formatDate util - refactor(logs): share a single generic log-list loader across tables - refactor(theme): merge both ColorField components and reuse contrast helpers - refactor(import): extract shared ImportErrorBanner and SearchInput - chore(): remove dead theme-editor-tabs after inlining tab components
69 lines
1.9 KiB
TypeScript
69 lines
1.9 KiB
TypeScript
import { describe, expect, it } from "vitest";
|
|
import { apiOk, apiUnavailable, pagination, positiveBigInt } from "@/lib/api";
|
|
|
|
describe("apiOk", () => {
|
|
it("returns a BigInt-safe success envelope with ok: true", async () => {
|
|
const response = apiOk({ id: 9007199254740993n });
|
|
|
|
expect(response.status).toBe(200);
|
|
expect(response.headers.get("cache-control")).toBe("no-store");
|
|
await expect(response.json()).resolves.toEqual({
|
|
ok: true,
|
|
id: "9007199254740993",
|
|
});
|
|
});
|
|
|
|
it("allows empty payloads", async () => {
|
|
await expect(apiOk().json()).resolves.toEqual({ ok: true });
|
|
});
|
|
});
|
|
|
|
describe("apiUnavailable", () => {
|
|
it("returns a no-store 503 error without exposing internal details", async () => {
|
|
const response = apiUnavailable("Account data is temporarily unavailable");
|
|
|
|
expect(response.status).toBe(503);
|
|
expect(response.headers.get("cache-control")).toBe("no-store");
|
|
await expect(response.json()).resolves.toEqual({
|
|
error: "Account data is temporarily unavailable",
|
|
});
|
|
});
|
|
});
|
|
|
|
describe("positiveBigInt", () => {
|
|
it.each(["1", "9007199254740993"])("parses positive integer id %s", (raw) => {
|
|
expect(positiveBigInt(raw)).toBe(BigInt(raw));
|
|
});
|
|
|
|
it.each([null, "", "0", "-1", "1.5", "abc"])(
|
|
"rejects invalid id %s",
|
|
(raw) => {
|
|
expect(positiveBigInt(raw)).toBeNull();
|
|
},
|
|
);
|
|
});
|
|
|
|
describe("pagination", () => {
|
|
it("rejects fractional and malformed values before they reach the DB layer", () => {
|
|
const params = new URLSearchParams({ page: "2.5", perPage: "10.1" });
|
|
|
|
expect(pagination(params, 20, 100)).toEqual({
|
|
page: 1,
|
|
perPage: 20,
|
|
skip: 0,
|
|
take: 20,
|
|
});
|
|
});
|
|
|
|
it("clamps valid page sizes to the configured maximum", () => {
|
|
const params = new URLSearchParams({ page: "3", perPage: "999" });
|
|
|
|
expect(pagination(params, 20, 100)).toEqual({
|
|
page: 3,
|
|
perPage: 100,
|
|
skip: 200,
|
|
take: 100,
|
|
});
|
|
});
|
|
});
|