import { describe, expect, test } from "bun:test"; import { buildUrl, candidateNames, LibretroProvider, sanitizeName, } from "../src/art/libretro.js"; import { parseTitle } from "../src/domain/titles.js"; import { platformById } from "../src/domain/platforms.js"; const snes = platformById("snes")!; const nswitch = platformById("switch")!; describe("libretro name handling", () => { test("sanitizeName replaces the forbidden characters with underscore", () => { expect(sanitizeName("Ratchet & Clank")).toBe("Ratchet _ Clank"); expect(sanitizeName("Where in the World?")).toBe("Where in the World_"); }); test("candidateNames walks exact → region → base", () => { const names = candidateNames(parseTitle("Chrono Trigger (USA) (Rev 1)")); expect(names[0]).toBe("Chrono Trigger (USA) (Rev 1)"); // exact expect(names).toContain("Chrono Trigger (USA)"); // region-kept expect(names).toContain("Chrono Trigger (Europe)"); // region-relaxed expect(names.at(-1)).toBe("Chrono Trigger"); // bare }); }); describe("LibretroProvider", () => { test("returns the first probe hit as a portrait", async () => { const hit = buildUrl( snes.libretroSystem!, sanitizeName("Chrono Trigger (USA)"), ); const provider = new LibretroProvider((url) => Promise.resolve(url === hit), ); const art = await provider.resolve( snes, parseTitle("Chrono Trigger (USA)"), ); expect(art).toEqual({ portrait: hit }); }); test("returns null when nothing matches", async () => { const provider = new LibretroProvider(() => Promise.resolve(false)); expect( await provider.resolve(snes, parseTitle("Nonexistent Game")), ).toBeNull(); }); test("returns null for a platform with no libretro system (Switch)", async () => { const provider = new LibretroProvider(() => Promise.resolve(true)); expect(await provider.resolve(nswitch, parseTitle("Zelda"))).toBeNull(); }); });