Files
punktfunk-plugin-rom-manager/plugin/test/libretro.test.ts
T
enricobuehler 899028e20f feat: Effect services + HttpApi implementation + kit entry/CLI/dev server
- RomConfig/RomCache on the kit's ConfigService/CacheStore; RomSync wires the
  pure domain into the kit SyncEngine (poll/watch/coalesce/fingerprint) and
  ProviderClient; EngineStatus assembly shared by REST + SSE
- makeApi: HttpApiBuilder groups over live service values (handler runtime
  shares the plugin runtime's singletons) + sseRoute status feed
- index.ts: definePluginKit entry (async-main boundary); headless-first (UI
  serve failure logged, engine continues)
- cli.ts on the kit dispatcher: scan/detect/preview offline, sync/uninstall
  online; set-password is gone with the standalone server
- dev.ts: auth-free loopback API server (:5885) — the dev:live proxy target;
  never bundled
- verified live host-less: raw config round-trip on disk, status/platforms/
  preview endpoints, soft-fail reconcile without a host
- CI: workspace install, per-package typecheck, publish from plugin/

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-20 19:04:25 +02:00

57 lines
1.9 KiB
TypeScript

import { describe, expect, test } from "bun:test";
import {
buildUrl,
candidateNames,
LibretroProvider,
sanitizeName,
} from "../src/art/libretro.js";
import { platformById } from "../src/domain/platforms.js";
import { parseTitle } from "../src/domain/titles.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();
});
});