import { fireEvent, render, screen } from '@testing-library/react'; import { describe, expect, it } from 'vitest'; import { createAuthContext } from '../../src/auth/createAuthContext'; type User = { id: string; username: string; }; const defaultAuth = createAuthContext(); function createUser(username: string): User { return { id: `id-${username}`, username, }; } function AuthHarness() { const { authToken, refreshToken, currentUser, setSession, setCurrentUser, clearSession } = defaultAuth.useAuth(); return (
{authToken ?? 'none'} {refreshToken ?? 'none'} {currentUser?.username ?? 'none'}
); } describe('createAuthContext', () => { it('throws when hook is used outside the provider', () => { function Invalid() { defaultAuth.useAuth(); return null; } expect(() => render()).toThrow('useAuth must be used within AuthProvider'); }); it('reads persisted tokens and cleans default legacy keys', () => { localStorage.setItem('authToken', 'auth-1'); localStorage.setItem('refreshToken', 'refresh-1'); localStorage.setItem('auth_token', 'legacy'); localStorage.setItem('auth_user', 'legacy'); localStorage.setItem('token', 'legacy'); render( , ); expect(screen.getByTestId('auth-token')).toHaveTextContent('auth-1'); expect(screen.getByTestId('refresh-token')).toHaveTextContent('refresh-1'); expect(localStorage.getItem('auth_token')).toBeNull(); expect(localStorage.getItem('auth_user')).toBeNull(); expect(localStorage.getItem('token')).toBeNull(); }); it('supports session lifecycle updates', () => { render( , ); fireEvent.click(screen.getByRole('button', { name: 'set-session' })); expect(screen.getByTestId('auth-token')).toHaveTextContent('auth-next'); expect(screen.getByTestId('refresh-token')).toHaveTextContent('refresh-next'); expect(screen.getByTestId('username')).toHaveTextContent('after-set'); expect(localStorage.getItem('authToken')).toBe('auth-next'); expect(localStorage.getItem('refreshToken')).toBe('refresh-next'); fireEvent.click(screen.getByRole('button', { name: 'set-user' })); expect(screen.getByTestId('username')).toHaveTextContent('patched'); fireEvent.click(screen.getByRole('button', { name: 'clear' })); expect(screen.getByTestId('auth-token')).toHaveTextContent('none'); expect(screen.getByTestId('refresh-token')).toHaveTextContent('none'); expect(screen.getByTestId('username')).toHaveTextContent('none'); expect(localStorage.getItem('authToken')).toBeNull(); expect(localStorage.getItem('refreshToken')).toBeNull(); }); it('supports custom token keys and legacy cleanup keys', () => { const customAuth = createAuthContext({ authTokenKey: 'custom-auth', refreshTokenKey: 'custom-refresh', legacyKeys: ['legacy-a', 'legacy-b'], }); function CustomHarness() { const { authToken, refreshToken, setSession } = customAuth.useAuth(); return (
{authToken ?? 'none'} {refreshToken ?? 'none'}
); } localStorage.setItem('custom-auth', 'auth-1'); localStorage.setItem('custom-refresh', 'refresh-1'); localStorage.setItem('legacy-a', 'legacy'); localStorage.setItem('legacy-b', 'legacy'); render( , ); expect(screen.getByTestId('custom-auth-token')).toHaveTextContent('auth-1'); expect(screen.getByTestId('custom-refresh-token')).toHaveTextContent('refresh-1'); expect(localStorage.getItem('legacy-a')).toBeNull(); expect(localStorage.getItem('legacy-b')).toBeNull(); fireEvent.click(screen.getByRole('button', { name: 'set-custom-session' })); expect(localStorage.getItem('custom-auth')).toBe('next-auth'); expect(localStorage.getItem('custom-refresh')).toBe('next-refresh'); }); });