Files
lemonspace_app/tests/lib/dashboard-snapshot-cache.test.ts

114 lines
3.4 KiB
TypeScript

/* @vitest-environment jsdom */
import { beforeEach, describe, expect, it } from "vitest";
import {
clearDashboardSnapshotCache,
emitDashboardSnapshotCacheInvalidationSignal,
invalidateDashboardSnapshotForLastSignedInUser,
readDashboardSnapshotCache,
writeDashboardSnapshotCache,
} from "@/lib/dashboard-snapshot-cache";
const USER_ID = "user-cache-test";
const LAST_DASHBOARD_USER_KEY = "ls-last-dashboard-user";
const INVALIDATION_SIGNAL_KEY = "lemonspace.dashboard:snapshot:invalidate:v1";
describe("dashboard snapshot cache", () => {
beforeEach(() => {
const data = new Map<string, string>();
const sessionData = new Map<string, string>();
const localStorageMock = {
getItem: (key: string) => data.get(key) ?? null,
setItem: (key: string, value: string) => {
data.set(key, value);
},
removeItem: (key: string) => {
data.delete(key);
},
};
const sessionStorageMock = {
getItem: (key: string) => sessionData.get(key) ?? null,
setItem: (key: string, value: string) => {
sessionData.set(key, value);
},
removeItem: (key: string) => {
sessionData.delete(key);
},
};
Object.defineProperty(window, "localStorage", {
value: localStorageMock,
configurable: true,
});
Object.defineProperty(window, "sessionStorage", {
value: sessionStorageMock,
configurable: true,
});
clearDashboardSnapshotCache(USER_ID);
});
it("reads back a written snapshot", () => {
const snapshot = {
balance: { available: 320 },
generatedAt: 100,
};
writeDashboardSnapshotCache(USER_ID, snapshot);
const cached = readDashboardSnapshotCache<typeof snapshot>(USER_ID);
expect(cached?.snapshot).toEqual(snapshot);
expect(typeof cached?.cachedAt).toBe("number");
});
it("invalidates stale cache entries via ttl", () => {
const snapshot = {
balance: { available: 100 },
generatedAt: 50,
};
writeDashboardSnapshotCache(USER_ID, snapshot);
const fresh = readDashboardSnapshotCache<typeof snapshot>(USER_ID, {
now: Date.now(),
ttlMs: 60_000,
});
expect(fresh?.snapshot).toEqual(snapshot);
const stale = readDashboardSnapshotCache<typeof snapshot>(USER_ID, {
now: Date.now() + 61_000,
ttlMs: 60_000,
});
expect(stale).toBeNull();
});
it("clears user cache explicitly", () => {
writeDashboardSnapshotCache(USER_ID, { generatedAt: 1 });
clearDashboardSnapshotCache(USER_ID);
expect(readDashboardSnapshotCache(USER_ID)).toBeNull();
});
it("invalidates cache for the last signed-in user", () => {
writeDashboardSnapshotCache(USER_ID, { generatedAt: 1 });
window.sessionStorage.setItem(LAST_DASHBOARD_USER_KEY, USER_ID);
invalidateDashboardSnapshotForLastSignedInUser();
expect(readDashboardSnapshotCache(USER_ID)).toBeNull();
expect(window.sessionStorage.getItem(LAST_DASHBOARD_USER_KEY)).toBe(USER_ID);
});
it("does not fail if no last dashboard user exists", () => {
expect(() => invalidateDashboardSnapshotForLastSignedInUser()).not.toThrow();
});
it("emits a localStorage invalidation signal", () => {
emitDashboardSnapshotCacheInvalidationSignal();
const signal = window.localStorage.getItem(INVALIDATION_SIGNAL_KEY);
expect(typeof signal).toBe("string");
expect(Number(signal)).toBeGreaterThan(0);
});
});