import { afterEach, describe, expect, it, vi } from "vitest"; import { _resetDetectablesCache, getDetectables, steamIdFromEntry } from "@/lib/game/detectables"; afterEach(() => { vi.unstubAllGlobals(); vi.restoreAllMocks(); _resetDetectablesCache(); }); describe("steamIdFromEntry", () => { it("extracts numeric Steam SKUs", () => { expect( steamIdFromEntry({ id: "game", name: "Game", third_party_skus: [{ distributor: "steam", id: "12345" }], }), ).toBe("12345"); }); it("rejects non-numeric or non-Steam SKUs", () => { expect( steamIdFromEntry({ id: "game", name: "Game", third_party_skus: [{ distributor: "steam", id: "abc" }], }), ).toBeNull(); expect( steamIdFromEntry({ id: "game", name: "Game", third_party_skus: [{ distributor: "gog", id: "12345" }], }), ).toBeNull(); }); it("handles missing entries", () => { expect(steamIdFromEntry(undefined)).toBeNull(); }); }); describe("getDetectables", () => { it("caches the snapshot within the TTL", async () => { const fetchMock = vi.fn( async () => ({ ok: true, json: async () => [{ id: "1", name: "Game" }], }) as Response, ); vi.stubGlobal("fetch", fetchMock); const first = await getDetectables(); const second = await getDetectables(); expect(first).toHaveLength(1); expect(second).toBe(first); expect(fetchMock).toHaveBeenCalledOnce(); }); it("falls back to empty when fetch rejects", async () => { vi.stubGlobal( "fetch", vi.fn(async () => { throw new Error("down"); }), ); await expect(getDetectables()).resolves.toEqual([]); }); it("falls back to empty on HTTP error", async () => { vi.stubGlobal( "fetch", vi.fn(async () => ({ ok: false, status: 500 }) as Response), ); await expect(getDetectables()).resolves.toEqual([]); }); });