shoc-frontend-new/src/test/api/api-error.test.ts

55 lines
1.7 KiB
TypeScript
Raw Normal View History

import ky from "ky";
import { describe, expect, it, vi } from "vitest";
import { normalizeApiRequestError } from "@/api/api-error";
const RESOURCE_URL = "https://example.test/api/resource";
function createClient(fetchImpl: typeof fetch) {
return ky.create({
fetch: fetchImpl,
retry: 0,
timeout: 50,
hooks: { beforeError: [({ error }) => normalizeApiRequestError(error)] },
});
}
describe("normalizeApiRequestError", () => {
it("surfaces Ky's pre-parsed JSON body for HTTP errors via the hook", async () => {
const fetchImpl = vi.fn(() =>
Promise.resolve(
new Response(JSON.stringify({ message: "Validation failed" }), {
status: 422,
headers: { "Content-Type": "application/json" },
}),
),
) as unknown as typeof fetch;
await expect(createClient(fetchImpl).get(RESOURCE_URL).json()).rejects.toThrow(
"Validation failed",
);
});
it("reports a connection failure for network errors", async () => {
const fetchImpl = vi.fn(() =>
Promise.reject(new TypeError("fetch failed")),
) as unknown as typeof fetch;
await expect(createClient(fetchImpl).get(RESOURCE_URL).json()).rejects.toThrow(
"No response from server. Please check your connection.",
);
});
it("returns a friendly timeout message", async () => {
const fetchImpl = vi.fn((_input: RequestInfo | URL, init?: RequestInit) => {
const signal = init?.signal;
return new Promise<Response>((_resolve, reject) => {
signal?.addEventListener("abort", () => reject(signal?.reason));
});
}) as unknown as typeof fetch;
await expect(createClient(fetchImpl).get(RESOURCE_URL).json()).rejects.toThrow(
"The request timed out. Please try again.",
);
});
});