import { beforeEach, describe, expect, it, vi } from "vitest"; import { ApiError } from "@/lib/auth/api-client"; import { listPacks } from "@/lib/apiaries/offline-pack"; import { offlinePack, storedPack } from "@/lib/apiaries/offline-pack.fixtures"; import { withPackFallback } from "./pack-fallback"; vi.mock("@/lib/apiaries/offline-pack", () => ({ listPacks: vi.fn() })); const PACKS = [storedPack(offlinePack({ apiaryId: "apiary-1", apiaryName: "Obstwiese" }))]; const apiaryNames = vi.fn((packs: typeof PACKS) => packs.map((pack) => pack.pack.apiary.name)); describe("withPackFallback", () => { beforeEach(() => { vi.mocked(listPacks).mockReset().mockResolvedValue(PACKS); apiaryNames.mockClear(); }); it("answers from the server whenever the server answers", async () => { const result = await withPackFallback(async () => ["vom Server"], apiaryNames, "user-1"); expect(result).toEqual(["vom Server"]); expect(listPacks).not.toHaveBeenCalled(); }); it("falls back to the pack on a network error", async () => { const result = await withPackFallback( () => Promise.reject(new TypeError("Failed to fetch")), apiaryNames, "user-1", ); expect(result).toEqual(["Obstwiese"]); expect(listPacks).toHaveBeenCalledWith("user-1"); }); it("falls back to the pack when the request timed out", async () => { const timeout = new DOMException("Zeitüberschreitung der Anfrage", "TimeoutError"); const result = await withPackFallback(() => Promise.reject(timeout), apiaryNames, "user-1"); expect(result).toEqual(["Obstwiese"]); }); it("rethrows an ApiError instead of showing pack data", async () => { for (const status of [403, 404, 500]) { const rejection = new ApiError(status, "Nein"); await expect( withPackFallback(() => Promise.reject(rejection), apiaryNames, "user-1"), ).rejects.toBe(rejection); } expect(listPacks).not.toHaveBeenCalled(); expect(apiaryNames).not.toHaveBeenCalled(); }); it("rethrows when the pack has nothing", async () => { const offline = new TypeError("Failed to fetch"); await expect( withPackFallback(() => Promise.reject(offline), () => null, "user-1"), ).rejects.toBe(offline); }); it("rethrows the network error when the packs cannot be read", async () => { const offline = new TypeError("Failed to fetch"); vi.mocked(listPacks).mockRejectedValue(new Error("IndexedDB gesperrt")); await expect( withPackFallback(() => Promise.reject(offline), apiaryNames, "user-1"), ).rejects.toBe(offline); }); });