import { afterEach, describe, expect, it, vi } from "vitest"; import { loadUiPreferences, saveUiPreferences, setRosterChangeListener } from "./accountRepository"; import { normalizeUiPreferences } from "../game/uiLayout"; import type { PlayerSession } from "./types"; function storage() { const values = new Map(); return { getItem: (key: string) => values.get(key) ?? null, setItem: (key: string, value: string) => { values.set(key, value); }, removeItem: (key: string) => { values.delete(key); } }; } afterEach(() => { vi.useRealTimers(); vi.unstubAllGlobals(); setRosterChangeListener(null); }); describe("profile UI persistence", () => { it("isolates owners and persists templates without requiring a character", () => { const local = storage(); const ui = normalizeUiPreferences(null); ui.slots.pc[1] = { name: "Healer", layout: ui.current.pc }; ui.keybinds.pc["move-forward"] = "ArrowUp"; ui.keybinds.controller.jump = "Button4&Button3"; saveUiPreferences("one", ui, local); expect(loadUiPreferences("one", local).slots.pc[1]?.name).toBe("Healer"); expect(loadUiPreferences("two", local).slots.pc[1]).toBeNull(); expect(loadUiPreferences("one", local).keybinds).toEqual(ui.keybinds); expect(loadUiPreferences("two", local).keybinds.pc["move-forward"]).toBe("KeyW"); ui.slots.pc[1].name = "Unsaved change"; expect(loadUiPreferences("one", local).slots.pc[1]?.name).toBe("Healer"); }); it("uploads all six slots and restores them into a separate device cache", async () => { vi.useFakeTimers(); const first = storage(); const second = storage(); vi.stubGlobal("window", { localStorage: first }); let cloudData: unknown = { version: 1, characters: [] }; vi.stubGlobal("fetch", vi.fn(async (_url: string, init: RequestInit) => { if (init.method === "PUT") cloudData = JSON.parse(String(init.body)).data; return new Response(JSON.stringify({ revision: 1, updatedAt: 1, data: cloudData }), { status: 200, headers: { "Content-Type": "application/json" } }); })); const client = await import("./onlineAccountClient"); const session: PlayerSession = { ownerId: "cloud-user", kind: "account", displayName: "Player", accessToken: "test-token" }; client.activateOnlineSession(session); const ui = normalizeUiPreferences(null); ui.slots.pc[2] = { name: "Desktop raid", layout: ui.current.pc }; ui.slots.mobile[1] = { name: "On the go", layout: ui.current.mobile }; ui.keybinds.pc["move-forward"] = "ArrowUp"; ui.keybinds.pc["look-up"] = null; ui.keybinds.controller.jump = "Button4&Button3"; saveUiPreferences(session.ownerId, ui); await vi.advanceTimersByTimeAsync(501); expect(client.useCloudSaveStatus.getState().state).toBe("synced"); vi.stubGlobal("window", { localStorage: second }); await client.hydrateOnlineSession(session); expect(loadUiPreferences(session.ownerId)).toEqual(ui); expect(loadUiPreferences("different-account").slots.pc[2]).toBeNull(); }); });