import { describe, it, expect, beforeEach, vi } from "vitest"; import type { MessageCategory } from "../../src/shared/types.js"; import { ALL_CATEGORIES, DEFAULT_HIDDEN_CATEGORIES } from "../../src/shared/types.js"; // Test the localStorage persistence logic used by useFilters const STORAGE_KEY_CATEGORIES = "session-viewer:enabledCategories"; const STORAGE_KEY_AUTOREDACT = "session-viewer:autoRedact"; function loadEnabledCategories(): Set { try { const stored = localStorage.getItem(STORAGE_KEY_CATEGORIES); if (stored) { const arr = JSON.parse(stored) as string[]; const valid = arr.filter((c) => ALL_CATEGORIES.includes(c as MessageCategory) ) as MessageCategory[]; if (valid.length > 0) return new Set(valid); } } catch { // Fall through to default } const set = new Set(ALL_CATEGORIES); for (const cat of DEFAULT_HIDDEN_CATEGORIES) { set.delete(cat); } return set; } function loadAutoRedact(): boolean { try { const stored = localStorage.getItem(STORAGE_KEY_AUTOREDACT); if (stored !== null) return stored === "true"; } catch { // Fall through to default } return false; } // Mock localStorage const store: Record = {}; const localStorageMock = { getItem: vi.fn((key: string) => store[key] ?? null), setItem: vi.fn((key: string, value: string) => { store[key] = value; }), removeItem: vi.fn((key: string) => { delete store[key]; }), clear: vi.fn(() => { for (const key in store) delete store[key]; }), get length() { return Object.keys(store).length; }, key: vi.fn((i: number) => Object.keys(store)[i] ?? null), }; Object.defineProperty(globalThis, "localStorage", { value: localStorageMock }); describe("filter persistence", () => { beforeEach(() => { localStorageMock.clear(); vi.clearAllMocks(); }); describe("loadEnabledCategories", () => { it("returns default categories when localStorage is empty", () => { const result = loadEnabledCategories(); const expected = new Set(ALL_CATEGORIES); for (const cat of DEFAULT_HIDDEN_CATEGORIES) { expected.delete(cat); } expect(result).toEqual(expected); }); it("restores categories from localStorage", () => { const saved: MessageCategory[] = ["user_message", "assistant_text"]; store[STORAGE_KEY_CATEGORIES] = JSON.stringify(saved); const result = loadEnabledCategories(); expect(result).toEqual(new Set(saved)); }); it("filters out invalid category values from localStorage", () => { const saved = ["user_message", "invalid_category", "thinking"]; store[STORAGE_KEY_CATEGORIES] = JSON.stringify(saved); const result = loadEnabledCategories(); expect(result.has("user_message")).toBe(true); expect(result.has("thinking")).toBe(true); expect(result.size).toBe(2); }); it("falls back to defaults on corrupted localStorage data", () => { store[STORAGE_KEY_CATEGORIES] = "not valid json"; const result = loadEnabledCategories(); const expected = new Set(ALL_CATEGORIES); for (const cat of DEFAULT_HIDDEN_CATEGORIES) { expected.delete(cat); } expect(result).toEqual(expected); }); it("falls back to defaults when stored array is all invalid", () => { store[STORAGE_KEY_CATEGORIES] = JSON.stringify(["fake1", "fake2"]); const result = loadEnabledCategories(); const expected = new Set(ALL_CATEGORIES); for (const cat of DEFAULT_HIDDEN_CATEGORIES) { expected.delete(cat); } expect(result).toEqual(expected); }); }); describe("loadAutoRedact", () => { it("returns false when localStorage is empty", () => { expect(loadAutoRedact()).toBe(false); }); it("returns true when stored as 'true'", () => { store[STORAGE_KEY_AUTOREDACT] = "true"; expect(loadAutoRedact()).toBe(true); }); it("returns false when stored as 'false'", () => { store[STORAGE_KEY_AUTOREDACT] = "false"; expect(loadAutoRedact()).toBe(false); }); it("returns false for any non-'true' string", () => { store[STORAGE_KEY_AUTOREDACT] = "yes"; expect(loadAutoRedact()).toBe(false); }); }); });