import React from 'react'; import { describe, it, expect, vi, beforeEach } from 'vitest'; import { render, screen, waitFor } from '@testing-library/react'; import { AuthProvider, useAuth } from './AuthContext'; import { useRouter } from 'next/navigation'; import { useCurrentSession } from '@/hooks/auth/useCurrentSession'; import { useLogout } from '@/hooks/auth/useLogout'; // Mock Next.js navigation vi.mock('next/navigation', () => ({ useRouter: vi.fn(), })); // Mock auth hooks vi.mock('@/hooks/auth/useCurrentSession', () => ({ useCurrentSession: vi.fn(), })); vi.mock('@/hooks/auth/useLogout', () => ({ useLogout: vi.fn(), })); // Test component that uses the auth context const TestConsumer = () => { const auth = useAuth(); return (
{auth.session ? 'has-session' : 'no-session'}
{auth.loading ? 'loading' : 'not-loading'}
); }; describe('AuthContext', () => { let mockRouter: any; let mockRefetch: any; let mockMutateAsync: any; beforeEach(() => { vi.clearAllMocks(); mockRouter = { push: vi.fn(), refresh: vi.fn(), }; mockRefetch = vi.fn(); mockMutateAsync = vi.fn().mockResolvedValue(undefined); (useRouter as any).mockReturnValue(mockRouter); (useCurrentSession as any).mockReturnValue({ data: null, isLoading: false, refetch: mockRefetch, }); (useLogout as any).mockReturnValue({ mutateAsync: mockMutateAsync, }); }); describe('AuthProvider', () => { it('should provide default context values', () => { render( ); expect(screen.getByTestId('session')).toHaveTextContent('no-session'); expect(screen.getByTestId('loading')).toHaveTextContent('not-loading'); }); it('should provide loading state', () => { (useCurrentSession as any).mockReturnValue({ data: null, isLoading: true, refetch: mockRefetch, }); render( ); expect(screen.getByTestId('loading')).toHaveTextContent('loading'); }); it('should provide session data', () => { const mockSession = { user: { id: '123', name: 'Test User' } }; (useCurrentSession as any).mockReturnValue({ data: mockSession, isLoading: false, refetch: mockRefetch, }); render( ); expect(screen.getByTestId('session')).toHaveTextContent('has-session'); }); it('should provide initial session data', () => { const mockSession = { user: { id: '123', name: 'Test User' } }; render( ); expect(screen.getByTestId('session')).toHaveTextContent('has-session'); }); }); describe('useAuth hook', () => { it('should throw error when used outside AuthProvider', () => { // Suppress console.error for this test const consoleSpy = vi.spyOn(console, 'error').mockImplementation(() => {}); expect(() => { render(); }).toThrow('useAuth must be used within an AuthProvider'); consoleSpy.mockRestore(); }); it('should provide login function', async () => { render( ); const loginButton = screen.getByText('Login'); loginButton.click(); await waitFor(() => { expect(mockRouter.push).toHaveBeenCalledWith('/auth/login'); }); }); it('should provide login function with returnTo parameter', async () => { const TestConsumerWithReturnTo = () => { const auth = useAuth(); return ( ); }; render( ); const loginButton = screen.getByText('Login with Return'); loginButton.click(); await waitFor(() => { expect(mockRouter.push).toHaveBeenCalledWith('/auth/login?returnTo=%2Fdashboard'); }); }); it('should provide logout function', async () => { render( ); const logoutButton = screen.getByText('Logout'); logoutButton.click(); await waitFor(() => { expect(mockMutateAsync).toHaveBeenCalled(); expect(mockRouter.push).toHaveBeenCalledWith('/'); expect(mockRouter.refresh).toHaveBeenCalled(); }); }); it('should handle logout failure gracefully', async () => { const consoleSpy = vi.spyOn(console, 'error').mockImplementation(() => {}); mockMutateAsync.mockRejectedValue(new Error('Logout failed')); render( ); const logoutButton = screen.getByText('Logout'); logoutButton.click(); await waitFor(() => { expect(mockMutateAsync).toHaveBeenCalled(); expect(mockRouter.push).toHaveBeenCalledWith('/'); }); consoleSpy.mockRestore(); }); it('should provide refreshSession function', async () => { render( ); const refreshButton = screen.getByText('Refresh'); refreshButton.click(); await waitFor(() => { expect(mockRefetch).toHaveBeenCalled(); }); }); }); describe('edge cases', () => { it('should handle null initial session', () => { render( ); expect(screen.getByTestId('session')).toHaveTextContent('no-session'); }); it('should handle undefined initial session', () => { render( ); expect(screen.getByTestId('session')).toHaveTextContent('no-session'); }); it('should handle multiple consumers', () => { render( ); const consumers = screen.getAllByTestId('auth-consumer'); expect(consumers).toHaveLength(2); }); }); });