Honest baseline after removing 45 gaming suppressions. Structural: lib/game plus root hooks extraction, CORS origin echo, DEV_ORIGINS layering. Fixes: error-cause binding, discord 5xx split, null-cache guard, co-located tests, rejecting-fetch coverage, naming and typing cleanup, socket controller, cache bound, cascade helpers, latch resets. Hardening: per-IP rate limit on API routes, deterministic-miss UX, retry cooldown plus cap. Suite 140 green, build plus lint clean.
92 lines
3.0 KiB
TypeScript
92 lines
3.0 KiB
TypeScript
import { afterEach, describe, expect, it, vi } from "vitest";
|
|
import { getGameProfile } from "@/lib/game/game-profile";
|
|
|
|
afterEach(() => {
|
|
vi.unstubAllGlobals();
|
|
vi.restoreAllMocks();
|
|
});
|
|
|
|
function mockFetch(handler: (url: string, init?: RequestInit) => unknown) {
|
|
vi.stubGlobal(
|
|
"fetch",
|
|
vi.fn(async (url: string, init?: RequestInit) => handler(url, init)),
|
|
);
|
|
}
|
|
|
|
function ok(data: unknown) {
|
|
return { ok: true, json: async () => data };
|
|
}
|
|
|
|
function baseEnv() {
|
|
vi.stubGlobal("process", { ...process, env: {} });
|
|
}
|
|
|
|
describe("getGameProfile", () => {
|
|
it("rejects non-numeric ids without fetching", async () => {
|
|
baseEnv();
|
|
const fetchMock = vi.fn();
|
|
vi.stubGlobal("fetch", fetchMock);
|
|
await expect(getGameProfile("abc")).resolves.toBeNull();
|
|
expect(fetchMock).not.toHaveBeenCalled();
|
|
});
|
|
|
|
it("assembles a profile from Steam when providers are absent", async () => {
|
|
baseEnv();
|
|
mockFetch((url) => {
|
|
if (url.includes("discord.com")) {
|
|
return ok({ id: "1", name: "Game" });
|
|
}
|
|
if (url.includes("detectables")) {
|
|
return ok([
|
|
{
|
|
id: "1",
|
|
name: "Game",
|
|
third_party_skus: [{ distributor: "steam", id: "100" }],
|
|
},
|
|
]);
|
|
}
|
|
if (url.includes("appdetails")) {
|
|
return ok({
|
|
"100": {
|
|
success: true,
|
|
data: {
|
|
name: "Game",
|
|
developers: ["Dev"],
|
|
publishers: ["Pub"],
|
|
platforms: { windows: true, mac: false, linux: false },
|
|
},
|
|
},
|
|
});
|
|
}
|
|
if (url.includes("appreviews")) {
|
|
return ok({
|
|
query_summary: {
|
|
review_score_desc: "Positive",
|
|
total_positive: 8,
|
|
total_negative: 2,
|
|
total_reviews: 10,
|
|
},
|
|
});
|
|
}
|
|
throw new Error(`unexpected fetch: ${url}`);
|
|
});
|
|
const profile = await getGameProfile("1", "en", "US");
|
|
expect(profile?.name).toBe("Game");
|
|
expect(profile?.developers).toEqual(["Dev"]);
|
|
expect(profile?.platforms).toContain("Windows");
|
|
expect(profile?.sources).toEqual({ igdb: false, steam: true, itad: false });
|
|
expect(profile?.itad).toBeNull();
|
|
});
|
|
|
|
it("returns null when Discord RPC is missing", async () => {
|
|
baseEnv();
|
|
mockFetch((url) => {
|
|
if (url.includes("discord.com")) {
|
|
return { ok: false, status: 404 };
|
|
}
|
|
throw new Error(`unexpected fetch: ${url}`);
|
|
});
|
|
await expect(getGameProfile("1")).resolves.toBeNull();
|
|
});
|
|
});
|