import { describe, expect, it, beforeEach, vi } from "vitest"; import { ApiError, get, isAuthError, SESSION_EXPIRED_EVENT } from "../client"; describe("api/client", () => { beforeEach(() => { vi.restoreAllMocks(); }); it("dispatches session-expired for 401 responses", async () => { const dispatchSpy = vi.spyOn(window, "dispatchEvent"); global.fetch = vi.fn().mockResolvedValue({ ok: false, status: 401, text: vi.fn().mockResolvedValue("Unauthorized"), }); await expect(get("/test")).rejects.toBeInstanceOf(ApiError); expect(dispatchSpy).toHaveBeenCalledTimes(1); const call = dispatchSpy.mock.calls[0]; expect(call).toBeDefined(); const event = call?.[0] as Event; expect(event.type).toBe(SESSION_EXPIRED_EVENT); }); it("dispatches session-expired for 403 responses", async () => { const dispatchSpy = vi.spyOn(window, "dispatchEvent"); global.fetch = vi.fn().mockResolvedValue({ ok: false, status: 403, text: vi.fn().mockResolvedValue("Forbidden"), }); await expect(get("/test")).rejects.toBeInstanceOf(ApiError); expect(dispatchSpy).toHaveBeenCalledTimes(1); const call = dispatchSpy.mock.calls[0]; expect(call).toBeDefined(); const event = call?.[0] as Event; expect(event.type).toBe(SESSION_EXPIRED_EVENT); }); it("does not treat non-auth errors as auth errors", () => { const error = new ApiError(500, "Server error"); expect(isAuthError(error)).toBe(false); }); it("recognizes 401 and 403 ApiError as auth errors", () => { expect(isAuthError(new ApiError(401, "Unauthorized"))).toBe(true); expect(isAuthError(new ApiError(403, "Forbidden"))).toBe(true); }); });