Files
Arkie-Library-Frontend/src/api.test.ts

73 lines
2.3 KiB
TypeScript
Raw Normal View History

2026-05-16 18:21:37 +08:00
import { describe, expect, it, vi } from "vitest";
async function loadApi(apiUrl = "") {
vi.resetModules();
vi.stubEnv("VITE_API_URL", apiUrl);
2026-05-26 14:07:10 +08:00
vi.stubEnv("VITE_API_PREFIX", "");
2026-05-16 18:21:37 +08:00
return import("./api");
}
function jsonResponse(body: unknown, init?: ResponseInit) {
return new Response(JSON.stringify(body), {
status: 200,
headers: { "Content-Type": "application/json" },
...init,
});
}
describe("api helpers", () => {
it("normalizes nullish API arrays", async () => {
const { itemsOrEmpty } = await loadApi();
expect(itemsOrEmpty(null)).toEqual([]);
expect(itemsOrEmpty(undefined)).toEqual([]);
expect(itemsOrEmpty(["a"])).toEqual(["a"]);
});
it("builds asset URLs from API base while preserving absolute URLs", async () => {
const { assetUrl } = await loadApi("https://api.example.com");
expect(assetUrl("/uploads/file.png")).toBe(
"https://api.example.com/uploads/file.png",
);
expect(assetUrl("https://cdn.example.com/file.png")).toBe(
"https://cdn.example.com/file.png",
);
expect(assetUrl(undefined)).toBe("");
});
it("fetches JSON with API base and throws response text on failure", async () => {
const { getJSON } = await loadApi("https://api.example.com");
const fetchMock = vi
.fn()
.mockResolvedValueOnce(jsonResponse({ ok: true }))
.mockResolvedValueOnce(new Response("boom", { status: 500 }));
vi.stubGlobal("fetch", fetchMock);
await expect(getJSON("/api/resources")).resolves.toEqual({ ok: true });
expect(fetchMock).toHaveBeenCalledWith(
"https://api.example.com/api/resources",
);
await expect(getJSON("/api/fail")).rejects.toThrow("boom");
});
it("posts JSON with optional bearer token", async () => {
const { postJSON } = await loadApi();
const fetchMock = vi.fn().mockResolvedValue(jsonResponse({ id: 1 }));
vi.stubGlobal("fetch", fetchMock);
await expect(
postJSON("/api/admin/resources", { title: "Demo" }, "token-123"),
).resolves.toEqual({ id: 1 });
expect(fetchMock).toHaveBeenCalledWith("/api/admin/resources", {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: "Bearer token-123",
},
body: JSON.stringify({ title: "Demo" }),
});
});
});