import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; const store = new Map(); async function load(search: string) { vi.resetModules(); vi.stubGlobal("location", { search }); vi.stubGlobal("localStorage", { getItem: (k: string) => store.get(k) ?? null, setItem: (k: string, v: string) => void store.set(k, v), removeItem: (k: string) => void store.delete(k), }); return import("../skins"); } describe("skins", () => { beforeEach(() => store.clear()); afterEach(() => vi.unstubAllGlobals()); it("is the dolphin with nothing chosen", async () => { const m = await load(""); expect(m.SKIN.id).toBe("dolphin"); }); it("takes ?theme= and remembers it", async () => { const m = await load("?theme=dinosaur"); expect(m.SKIN.id).toBe("dinosaur"); expect(store.get(m.STORAGE_KEY)).toBe("dinosaur"); }); it("uses the remembered skin when the URL has none", async () => { store.set("musicmouse.theme", "dinosaur"); const m = await load("?pi=1"); expect(m.SKIN.id).toBe("dinosaur"); }); it("lets ?theme= switch back", async () => { store.set("musicmouse.theme", "dinosaur"); const m = await load("?theme=dolphin"); expect(m.SKIN.id).toBe("dolphin"); expect(store.get(m.STORAGE_KEY)).toBe("dolphin"); }); it("gives every skin a complete, readable game world", async () => { const { SKINS } = await load(""); const { CREATURE_IDS } = await import("../tippen/pets"); const { ANIMALS } = await import("../tippen/grading"); for (const skin of Object.values(SKINS)) { const { game } = skin; for (const id of CREATURE_IDS) expect(game.pets[id].name, `${skin.id} ${id}`).not.toBe(""); const ladder = ANIMALS.map((animal) => game.ladder[animal.id]); for (const rung of ladder) expect(rung.name && rung.emoji && rung.praise, skin.id).toBeTruthy(); // One look per rung: two rungs sharing a name or an emoji would read as no progress. expect(new Set(ladder.map((rung) => rung.emoji)).size, skin.id).toBe(ladder.length); expect(new Set(ladder.map((rung) => rung.name)).size, skin.id).toBe(ladder.length); // ⭐ is the star rating, three lines below the animal on the result sheet. for (const rung of ladder) expect(rung.emoji, skin.id).not.toBe("⭐"); for (const mode of Object.values(game.modes)) expect(mode.name && mode.emoji, skin.id).toBeTruthy(); expect(game.feedItems.length, skin.id).toBeGreaterThan(0); } }); it("ignores unknown values, in the URL and in storage", async () => { store.set("musicmouse.theme", "toString"); const m = await load("?theme=unicorn"); expect(m.SKIN.id).toBe("dolphin"); expect(store.get(m.STORAGE_KEY)).toBe("toString"); }); });