import { STORAGE_KEY, readStoredSession, writeStoredSession, clearStoredSession, StoredSession, } from '../../frontend/src/app/core/services/auth.session-storage'; import { of, throwError } from 'rxjs'; function makeStorage(initial: Record = {}): { store: Record; getItem: jest.Mock; setItem: jest.Mock; removeItem: jest.Mock; } { const store = { ...initial }; return { store, getItem: jest.fn((k: string) => (k in store ? store[k] : null)), setItem: jest.fn((k: string, v: string) => { store[k] = v; }), removeItem: jest.fn((k: string) => { delete store[k]; }), }; } const adminSession: StoredSession = { token: 'tok-1', user: { id: 'u1', username: 'alice', role: 'admin' }, }; describe('auth.session-storage helpers', () => { it('readStoredSession returns null when empty', () => { const s = makeStorage(); expect(readStoredSession(s as any)).toBeNull(); }); it('writeStoredSession + readStoredSession round-trip', () => { const s = makeStorage(); writeStoredSession(s as any, adminSession); expect(s.setItem).toHaveBeenCalledWith(STORAGE_KEY, JSON.stringify(adminSession)); expect(readStoredSession(s as any)).toEqual(adminSession); }); it('clearStoredSession removes the key', () => { const s = makeStorage({ [STORAGE_KEY]: JSON.stringify(adminSession) }); clearStoredSession(s as any); expect(s.removeItem).toHaveBeenCalledWith(STORAGE_KEY); expect(readStoredSession(s as any)).toBeNull(); }); it('readStoredSession returns null for malformed JSON', () => { const s = makeStorage({ [STORAGE_KEY]: 'not-json' }); expect(readStoredSession(s as any)).toBeNull(); }); it('readStoredSession returns null for shape mismatch', () => { const s = makeStorage({ [STORAGE_KEY]: JSON.stringify({ foo: 'bar' }) }); expect(readStoredSession(s as any)).toBeNull(); }); }); describe('restoreSession refresh flow (pure)', () => { it('successful refresh updates state and persists new token', async () => { const stored = makeStorage({ [STORAGE_KEY]: JSON.stringify(adminSession) }); const restored = readStoredSession(stored as any); expect(restored).toEqual(adminSession); const httpPost = jest.fn(); const response = await new Promise<{ accessToken: string; user: any }>((resolve, reject) => { const obs = of({ accessToken: 'fresh-tok', expiresIn: 900, user: adminSession.user }); httpPost.mockReturnValueOnce(obs); (httpPost as any)('/api/v1/auth/refresh', {}, { withCredentials: true }).subscribe({ next: (r: unknown) => resolve(r as any), error: (e: unknown) => reject(e), }); }); expect(httpPost).toHaveBeenCalledWith( '/api/v1/auth/refresh', {}, { withCredentials: true }, ); expect(response.accessToken).toBe('fresh-tok'); writeStoredSession(stored as any, { token: response.accessToken, user: response.user, }); expect(stored.store[STORAGE_KEY]).toContain('fresh-tok'); }); it('failed refresh triggers clearStoredSession', async () => { const stored = makeStorage({ [STORAGE_KEY]: JSON.stringify(adminSession) }); const httpPost = jest.fn(); let errored = false; try { await new Promise((resolve, reject) => { httpPost.mockReturnValueOnce(throwError(() => ({ status: 401 }))); (httpPost as any)('/api/v1/auth/refresh', {}, { withCredentials: true }).subscribe({ next: () => resolve(undefined), error: (e: unknown) => reject(e), }); }); } catch { errored = true; } expect(errored).toBe(true); clearStoredSession(stored as any); expect(stored.removeItem).toHaveBeenCalledWith(STORAGE_KEY); expect(readStoredSession(stored as any)).toBeNull(); }); });