import { describe, expect, it } from "vitest"; import { createBrowserStorageAdapter } from "../../src/adapters/storage/browser-storage-adapter.js"; import { STORAGE_REGISTRY, buildPhysicalKey, defineStorageKey, } from "../../src/contracts/storage-keys.js"; /** * @param {{quota?: boolean}} [options] * @returns {Storage} */ function createStorage({ quota = false } = {}) { const values = /** @type {Map} */ (new Map()); return { getItem: (key) => values.get(key) ?? null, setItem: (key, value) => { if (quota) throw new DOMException("full", "QuotaExceededError"); values.set(key, value); }, removeItem: (key) => values.delete(key), clear: () => values.clear(), key: () => null, get length() { return values.size; }, }; } describe("storage registry", () => { it("builds namespace and schema-versioned physical keys", () => { expect(buildPhysicalKey("preference", 2, "theme")).toBe( "ca-frontend:preference:v2:theme", ); expect(STORAGE_REGISTRY.COLOR_SCHEME.physicalKey).toContain(":v1:"); }); it("rejects token or secret persistence registrations", () => { expect(() => defineStorageKey({ logicalName: "TOKEN", scope: "auth", name: "token", backend: "localStorage", classification: "sensitive-forbidden", schemaVersion: 1, ttl: null, migration: "discard", quotaFallback: "feature-disable", }), ).toThrow("Sensitive client storage registration is forbidden"); }); it("round-trips public preferences through the adapter", () => { const localStorage = createStorage(); const adapter = createBrowserStorageAdapter({ localStorage }); expect(adapter.write("COLOR_SCHEME", "dark")).toEqual({ ok: true }); expect(adapter.read("COLOR_SCHEME")).toEqual({ ok: true, value: "dark" }); }); it("falls back to memory when preference storage quota is exceeded", () => { const localStorage = createStorage({ quota: true }); const adapter = createBrowserStorageAdapter({ localStorage }); expect(adapter.write("COLOR_SCHEME", "dark")).toMatchObject({ ok: false, fallback: "memory", error: { kind: "STORAGE_QUOTA_EXCEEDED" }, }); expect(adapter.read("COLOR_SCHEME")).toEqual({ ok: true, value: "dark" }); }); it("discards data from a previous schema version", () => { const localStorage = createStorage(); localStorage.setItem( STORAGE_REGISTRY.COLOR_SCHEME.physicalKey, JSON.stringify({ schemaVersion: 0, value: "dark" }), ); const adapter = createBrowserStorageAdapter({ localStorage }); expect(adapter.read("COLOR_SCHEME")).toEqual({ ok: true, value: undefined }); }); });