import { describe, it, expect, beforeEach, afterEach, vi } from "vitest"; import { get } from "svelte/store"; import { getAchievementRarity, getRarityColour, toastStore } from "./toasts"; import type { AchievementUnlockedEvent } from "$lib/types/achievements"; // --- describe("getAchievementRarity", () => { describe("legendary tier", () => { it("classifies TokenMaster as legendary", () => { expect(getAchievementRarity("TokenMaster")).toBe("legendary"); }); }); describe("epic tier", () => { it("classifies CodeMachine as epic", () => { expect(getAchievementRarity("CodeMachine")).toBe("epic"); }); it("classifies Unstoppable as epic", () => { expect(getAchievementRarity("Unstoppable")).toBe("epic"); }); }); describe("rare tier", () => { it("classifies BlossomingCoder as rare", () => { expect(getAchievementRarity("BlossomingCoder")).toBe("rare"); }); it("classifies CodeWizard as rare", () => { expect(getAchievementRarity("CodeWizard")).toBe("rare"); }); it("classifies MasterBuilder as rare", () => { expect(getAchievementRarity("MasterBuilder")).toBe("rare"); }); it("classifies EnduranceChamp as rare", () => { expect(getAchievementRarity("EnduranceChamp")).toBe("rare"); }); it("classifies DeepDive as rare", () => { expect(getAchievementRarity("DeepDive")).toBe("rare"); }); it("classifies CreativeCoder as rare", () => { expect(getAchievementRarity("CreativeCoder")).toBe("rare"); }); }); describe("common tier", () => { it("classifies unknown IDs as common", () => { expect(getAchievementRarity("FirstChat")).toBe("common"); expect(getAchievementRarity("SomeNewAchievement")).toBe("common"); expect(getAchievementRarity("")).toBe("common"); }); }); }); describe("getRarityColour", () => { it("returns yellow-to-orange gradient for legendary", () => { expect(getRarityColour("legendary")).toBe("from-yellow-400 to-orange-500"); }); it("returns purple-to-pink gradient for epic", () => { expect(getRarityColour("epic")).toBe("from-purple-400 to-pink-500"); }); it("returns blue-to-indigo gradient for rare", () => { expect(getRarityColour("rare")).toBe("from-blue-400 to-indigo-500"); }); it("returns green-to-emerald gradient for common", () => { expect(getRarityColour("common")).toBe("from-green-400 to-emerald-500"); }); it("falls back to green-to-emerald gradient for unknown rarities", () => { expect(getRarityColour("mythic")).toBe("from-green-400 to-emerald-500"); expect(getRarityColour("")).toBe("from-green-400 to-emerald-500"); }); describe("end-to-end rarity pipeline", () => { it("produces the correct colour for a legendary achievement", () => { const colour = getRarityColour(getAchievementRarity("TokenMaster")); expect(colour).toBe("from-yellow-400 to-orange-500"); }); it("produces the correct colour for an epic achievement", () => { const colour = getRarityColour(getAchievementRarity("CodeMachine")); expect(colour).toBe("from-purple-400 to-pink-500"); }); it("produces the correct colour for a rare achievement", () => { const colour = getRarityColour(getAchievementRarity("CodeWizard")); expect(colour).toBe("from-blue-400 to-indigo-500"); }); it("produces the correct colour for a common achievement", () => { const colour = getRarityColour(getAchievementRarity("FirstChat")); expect(colour).toBe("from-green-400 to-emerald-500"); }); }); }); // --- describe("toastStore", () => { beforeEach(() => { vi.useFakeTimers(); // Clear all toasts before each test const current = get(toastStore); for (const toast of current) { toastStore.remove(toast.id); } }); afterEach(() => { vi.useRealTimers(); }); describe("addInfo", () => { it("adds an info toast with the correct fields", () => { toastStore.addInfo("Hello world", "🌍"); const toasts = get(toastStore); expect(toasts).toHaveLength(1); const toast = toasts[0]; expect(toast.kind).toBe("info"); if (toast.kind === "info") { expect(toast.message).toBe("Hello world"); expect(toast.icon).toBe("🌍"); expect(typeof toast.id).toBe("string"); expect(toast.id.length).toBeGreaterThan(0); } }); it("uses a default icon when none is provided", () => { toastStore.addInfo("Default icon test"); const toasts = get(toastStore); const toast = toasts[0]; if (toast.kind === "info") { expect(toast.icon).toBe("â„šī¸"); } }); it("auto-dismisses after 4000ms", () => { toastStore.addInfo("Auto-dismiss test"); expect(get(toastStore)).toHaveLength(1); vi.advanceTimersByTime(3999); expect(get(toastStore)).toHaveLength(1); vi.advanceTimersByTime(1); expect(get(toastStore)).toHaveLength(0); }); }); describe("addAchievement", () => { const mockAchievement: AchievementUnlockedEvent["achievement"] = { id: "FirstMessage", name: "First Message", description: "Sent your first message", icon: "đŸ’Ŧ", unlocked_at: "2026-01-01T00:00:00Z", }; it("adds an achievement toast with the correct fields", () => { toastStore.addAchievement(mockAchievement); const toasts = get(toastStore); expect(toasts).toHaveLength(1); const toast = toasts[0]; expect(toast.kind).toBe("achievement"); if (toast.kind === "achievement") { expect(toast.achievement).toEqual(mockAchievement); expect(typeof toast.id).toBe("string"); } }); it("auto-dismisses after 5000ms", () => { toastStore.addAchievement(mockAchievement); expect(get(toastStore)).toHaveLength(1); vi.advanceTimersByTime(4999); expect(get(toastStore)).toHaveLength(1); vi.advanceTimersByTime(1); expect(get(toastStore)).toHaveLength(0); }); }); describe("addUpdate", () => { it("adds a persistent update toast with the correct fields", () => { toastStore.addUpdate("2.0.0", "1.9.0", "https://example.com/release"); const toasts = get(toastStore); expect(toasts).toHaveLength(1); const toast = toasts[0]; expect(toast.kind).toBe("update"); if (toast.kind === "update") { expect(toast.latestVersion).toBe("2.0.0"); expect(toast.currentVersion).toBe("1.9.0"); expect(toast.releaseUrl).toBe("https://example.com/release"); expect(typeof toast.id).toBe("string"); } }); it("does not auto-dismiss after a long time", () => { toastStore.addUpdate("2.0.0", "1.9.0", "https://example.com/release"); expect(get(toastStore)).toHaveLength(1); vi.advanceTimersByTime(60000); expect(get(toastStore)).toHaveLength(1); }); }); describe("remove", () => { it("removes a toast by id", () => { toastStore.addInfo("To be removed"); const toasts = get(toastStore); expect(toasts).toHaveLength(1); const id = toasts[0].id; toastStore.remove(id); expect(get(toastStore)).toHaveLength(0); }); it("does not affect other toasts when removing by id", () => { toastStore.addInfo("First toast"); toastStore.addInfo("Second toast"); const toasts = get(toastStore); expect(toasts).toHaveLength(2); toastStore.remove(toasts[0].id); const remaining = get(toastStore); expect(remaining).toHaveLength(1); if (remaining[0].kind === "info") { expect(remaining[0].message).toBe("Second toast"); } }); it("is a no-op when the id does not exist", () => { toastStore.addInfo("Existing toast"); toastStore.remove("non-existent-id"); expect(get(toastStore)).toHaveLength(1); }); }); });