import { beforeEach, describe, expect, mock, test } from 'bun:test'; const storage = new Map(); let storageSetCount = 0; let runtimeKey = 'runtime-a'; let diskResponseBody: Record = { version: 1, exists: false }; const safeStorage = { getItem: (key: string) => storage.get(key) ?? null, setItem: (key: string, value: string) => { storageSetCount += 1; storage.set(key, value); }, removeItem: (key: string) => { storage.delete(key); }, clear: () => { storage.clear(); }, key: (index: number) => Array.from(storage.keys())[index] ?? null, get length() { return storage.size; }, } as Storage; mock.module('./utils/safeStorage', () => ({ getDeferredSafeStorage: () => safeStorage, getSafeStorage: () => safeStorage, })); mock.module('@/lib/desktop', () => ({ isVSCodeRuntime: () => false, })); mock.module('@/lib/runtime-fetch', () => ({ runtimeFetch: mock(async () => new Response(JSON.stringify(diskResponseBody), { headers: { 'Content-Type': 'application/json' } })), })); mock.module('@/lib/runtime-switch', () => ({ getRuntimeKey: () => runtimeKey })); const { useSessionFoldersStore } = await import('./useSessionFoldersStore'); const waitForPersist = () => new Promise((resolve) => setTimeout(resolve, 350)); describe('useSessionFoldersStore folder assignments', () => { beforeEach(() => { storage.clear(); storageSetCount = 0; runtimeKey = 'runtime-a'; diskResponseBody = { version: 1, exists: false }; useSessionFoldersStore.getState().resetForRuntimeSwitch(runtimeKey); useSessionFoldersStore.setState({ foldersMap: {}, collapsedFolderIds: new Set(), }); }); test('repeated addSessionToFolder to the same folder preserves foldersMap reference', async () => { const store = useSessionFoldersStore.getState(); const folder = store.createFolder('/workspace/project', 'Work'); store.addSessionToFolder('/workspace/project', folder.id, 'ses_1'); await waitForPersist(); storageSetCount = 0; const before = useSessionFoldersStore.getState().foldersMap; useSessionFoldersStore.getState().addSessionToFolder('/workspace/project', folder.id, 'ses_1'); await waitForPersist(); expect(useSessionFoldersStore.getState().foldersMap).toBe(before); expect(storageSetCount).toBe(0); }); test('repeated addSessionsToFolder to the same folder preserves foldersMap reference', async () => { const store = useSessionFoldersStore.getState(); const folder = store.createFolder('/workspace/project', 'Batch'); store.addSessionsToFolder('/workspace/project', folder.id, ['ses_1', 'ses_2']); await waitForPersist(); storageSetCount = 0; const before = useSessionFoldersStore.getState().foldersMap; useSessionFoldersStore.getState().addSessionsToFolder('/workspace/project', folder.id, ['ses_1', 'ses_2']); await waitForPersist(); expect(useSessionFoldersStore.getState().foldersMap).toBe(before); expect(storageSetCount).toBe(0); }); test('restores independent folder snapshots across runtime switches', async () => { useSessionFoldersStore.getState().createFolder('/workspace/project', 'Runtime A'); await waitForPersist(); runtimeKey = 'runtime-b'; useSessionFoldersStore.getState().resetForRuntimeSwitch(runtimeKey); expect(useSessionFoldersStore.getState().getFoldersForScope('/workspace/project')).toEqual([]); useSessionFoldersStore.getState().createFolder('/workspace/project', 'Runtime B'); await waitForPersist(); runtimeKey = 'runtime-a'; useSessionFoldersStore.getState().resetForRuntimeSwitch(runtimeKey); expect(useSessionFoldersStore.getState().getFoldersForScope('/workspace/project').map((folder) => folder.name)).toEqual(['Runtime A']); }); test('flushes the outgoing runtime before a debounced browser write can be lost', () => { useSessionFoldersStore.getState().createFolder('/workspace/project', 'Runtime A pending'); runtimeKey = 'runtime-b'; useSessionFoldersStore.getState().resetForRuntimeSwitch(runtimeKey); runtimeKey = 'runtime-a'; useSessionFoldersStore.getState().resetForRuntimeSwitch(runtimeKey); expect(useSessionFoldersStore.getState().getFoldersForScope('/workspace/project').map((folder) => folder.name)).toEqual(['Runtime A pending']); }); test('does not replace browser folders when the server has no disk snapshot', async () => { useSessionFoldersStore.getState().createFolder('/workspace/project', 'Browser folder'); runtimeKey = 'runtime-b'; useSessionFoldersStore.getState().resetForRuntimeSwitch(runtimeKey); runtimeKey = 'runtime-a'; useSessionFoldersStore.getState().resetForRuntimeSwitch(runtimeKey); await new Promise((resolve) => setTimeout(resolve, 0)); expect(useSessionFoldersStore.getState().getFoldersForScope('/workspace/project').map((folder) => folder.name)).toEqual(['Browser folder']); }); test('does not silently evict folder state from older runtimes', () => { for (let index = 0; index < 10; index += 1) { runtimeKey = `runtime-${index}`; useSessionFoldersStore.getState().resetForRuntimeSwitch(runtimeKey); useSessionFoldersStore.getState().createFolder('/workspace/project', `Folder ${index}`); } runtimeKey = 'runtime-0'; useSessionFoldersStore.getState().resetForRuntimeSwitch(runtimeKey); expect(useSessionFoldersStore.getState().getFoldersForScope('/workspace/project').map((folder) => folder.name)).toEqual(['Folder 0']); }); });