import { beforeEach, describe, expect, it, vi } from "vitest"; // PCH-01-004: deviceId must live in chrome.storage.local (device-local), never // in chrome.storage.sync (which roams across profiles and collides identities). type StorageShape = Record; const DEVICE_ID_KEY = "peach_device_id"; describe("device-identity getOrCreateDeviceId (PCH-01-004)", () => { let local: StorageShape; let sync: StorageShape; let localSet: ReturnType; let syncSet: ReturnType; let syncRemove: ReturnType; function makeArea(store: StorageShape, set: ReturnType, remove?: ReturnType) { return { get: vi.fn(async (key?: string | string[]) => { if (!key) return store; if (typeof key === "string") return { [key]: store[key] }; return key.reduce>((r, k) => { r[k] = store[k]; return r; }, {}); }), set, remove: remove ?? vi.fn(async () => undefined), }; } beforeEach(() => { vi.resetModules(); local = {}; sync = {}; localSet = vi.fn(async (next: Record) => { Object.assign(local, next); }); syncSet = vi.fn(async (next: Record) => { Object.assign(sync, next); }); syncRemove = vi.fn(async (key: string) => { delete sync[key]; }); const chromeMock = { storage: { local: makeArea(local, localSet), sync: makeArea(sync, syncSet, syncRemove), }, } as unknown as typeof chrome; (globalThis as { chrome?: typeof chrome }).chrome = chromeMock; }); it("fresh_install_writes_id_to_local_only", async () => { const { getOrCreateDeviceId } = await import("./device-identity"); const id = await getOrCreateDeviceId(); expect(typeof id).toBe("string"); expect(id.length).toBeGreaterThan(0); expect(local[DEVICE_ID_KEY]).toBe(id); expect(syncSet).not.toHaveBeenCalled(); }); it("returns_a_stable_id_across_calls", async () => { const { getOrCreateDeviceId } = await import("./device-identity"); const first = await getOrCreateDeviceId(); const second = await getOrCreateDeviceId(); expect(second).toBe(first); }); });