import { afterEach, describe, expect, it, vi } from "vitest"; import { _resetIgdbState, getIgdbGame, igdbImage } from "@/lib/game/igdb"; afterEach(() => { vi.unstubAllGlobals(); vi.restoreAllMocks(); _resetIgdbState(); }); function tokenResponse() { return { ok: true, json: async () => ({ access_token: "tok", expires_in: 3600 }), } as Response; } describe("igdbImage", () => { it("upgrades thumbnail sizes", () => { expect(igdbImage("//images.igdb.com/t_thumb/1.jpg", "t_cover_big")).toBe( "https://images.igdb.com/t_cover_big/1.jpg", ); }); it("returns null without a url", () => { expect(igdbImage(undefined, "t_cover_big")).toBeNull(); }); }); describe("getIgdbGame", () => { it("returns null without credentials and warns once", async () => { vi.stubGlobal("process", { ...process, env: {} }); const fetchMock = vi.fn(); vi.stubGlobal("fetch", fetchMock); await expect(getIgdbGame("Game", null)).resolves.toBeNull(); await expect(getIgdbGame("Game", null)).resolves.toBeNull(); expect(fetchMock).not.toHaveBeenCalled(); }); it("returns null when the token fetch rejects", async () => { vi.stubGlobal("process", { ...process, env: { TWITCH_CLIENT_ID: "id", TWITCH_CLIENT_SECRET: "secret" }, }); vi.stubGlobal( "fetch", vi.fn(async () => { throw new Error("down"); }), ); await expect(getIgdbGame("Game", null)).resolves.toBeNull(); }); it("escapes backslashes and quotes in search queries", async () => { vi.stubGlobal("process", { ...process, env: { TWITCH_CLIENT_ID: "id", TWITCH_CLIENT_SECRET: "secret" }, }); const bodies: string[] = []; vi.stubGlobal( "fetch", vi.fn(async (_url: string, init?: RequestInit) => { if (typeof init?.body === "string" && init.body.includes("external_games")) { return { ok: true, json: async () => [] } as Response; } if (typeof init?.body === "string") { bodies.push(init.body); return { ok: true, json: async () => [] } as Response; } return tokenResponse(); }), ); await expect(getIgdbGame('a\\b"c', null)).resolves.toBeNull(); expect(bodies.some((b) => b.includes('a\\\\b\\"c'))).toBe(true); }); });