Files
btpxpress-frontend/contexts/__tests__/AuthContext.test.tsx
2025-10-13 05:29:32 +02:00

223 lines
6.3 KiB
TypeScript

import React from 'react'
import { render, screen, waitFor } from '../../test-utils'
import { AuthProvider, useAuthContext } from '../AuthContext'
import { UserRole } from '../../types/auth'
import authService from '../../services/auth'
// Mock du service d'authentification
jest.mock('../../services/auth')
const mockAuthService = authService as jest.Mocked<typeof authService>
// Composant de test pour utiliser le contexte
const TestComponent = () => {
const auth = useAuthContext()
return (
<div>
<div data-testid="loading">{auth.loading ? 'Loading' : 'Not Loading'}</div>
<div data-testid="authenticated">{auth.isAuthenticated ? 'Authenticated' : 'Not Authenticated'}</div>
<div data-testid="user">{auth.user ? `User: ${auth.user.email}` : 'No User'}</div>
<div data-testid="error">{auth.error || 'No Error'}</div>
<button onClick={() => auth.login({ email: 'test@test.com', password: 'password' })}>
Login
</button>
<button onClick={() => auth.logout()}>Logout</button>
<button onClick={() => auth.clearError()}>Clear Error</button>
</div>
)
}
describe('AuthContext', () => {
beforeEach(() => {
jest.clearAllMocks()
mockAuthService.getToken.mockReturnValue(null)
mockAuthService.getCurrentUserFromStorage.mockReturnValue(null)
})
it('devrait initialiser avec un état par défaut', async () => {
render(
<AuthProvider>
<TestComponent />
</AuthProvider>
)
await waitFor(() => {
expect(screen.getByTestId('loading')).toHaveTextContent('Not Loading')
expect(screen.getByTestId('authenticated')).toHaveTextContent('Not Authenticated')
expect(screen.getByTestId('user')).toHaveTextContent('No User')
expect(screen.getByTestId('error')).toHaveTextContent('No Error')
})
})
it('devrait initialiser avec un utilisateur connecté si token valide', async () => {
const mockUser = {
id: '1',
email: 'test@test.com',
nom: 'Test',
prenom: 'User',
role: UserRole.ADMIN,
telephone: '0612345678',
adresse: '123 rue Test',
codePostal: '75001',
ville: 'Paris'
}
mockAuthService.getToken.mockReturnValue('valid-token')
mockAuthService.getCurrentUserFromStorage.mockReturnValue(mockUser)
mockAuthService.getCurrentUser.mockResolvedValue(mockUser)
render(
<AuthProvider>
<TestComponent />
</AuthProvider>
)
await waitFor(() => {
expect(screen.getByTestId('authenticated')).toHaveTextContent('Authenticated')
expect(screen.getByTestId('user')).toHaveTextContent('User: test@test.com')
})
})
it('devrait nettoyer l\'état si le token est invalide', async () => {
const mockUser = {
id: '1',
email: 'test@test.com',
nom: 'Test',
prenom: 'User',
role: UserRole.ADMIN,
telephone: '0612345678',
adresse: '123 rue Test',
codePostal: '75001',
ville: 'Paris'
}
mockAuthService.getToken.mockReturnValue('invalid-token')
mockAuthService.getCurrentUserFromStorage.mockReturnValue(mockUser)
mockAuthService.getCurrentUser.mockResolvedValue(null)
mockAuthService.logout.mockResolvedValue()
render(
<AuthProvider>
<TestComponent />
</AuthProvider>
)
await waitFor(() => {
expect(screen.getByTestId('authenticated')).toHaveTextContent('Not Authenticated')
expect(screen.getByTestId('user')).toHaveTextContent('No User')
})
expect(mockAuthService.logout).toHaveBeenCalled()
})
it('devrait gérer les erreurs d\'initialisation', async () => {
mockAuthService.getToken.mockImplementation(() => {
throw new Error('Storage error')
})
render(
<AuthProvider>
<TestComponent />
</AuthProvider>
)
await waitFor(() => {
expect(screen.getByTestId('error')).toHaveTextContent('Erreur d\'initialisation')
expect(screen.getByTestId('authenticated')).toHaveTextContent('Not Authenticated')
})
})
it('devrait lancer une erreur si utilisé hors du provider', () => {
// Supprimer les erreurs de console pour ce test
const originalError = console.error
console.error = jest.fn()
expect(() => {
render(<TestComponent />)
}).toThrow('useAuthContext must be used within an AuthProvider')
console.error = originalError
})
it('devrait permettre d\'effacer les erreurs', async () => {
mockAuthService.getToken.mockImplementation(() => {
throw new Error('Storage error')
})
render(
<AuthProvider>
<TestComponent />
</AuthProvider>
)
await waitFor(() => {
expect(screen.getByTestId('error')).toHaveTextContent('Erreur d\'initialisation')
})
// Effacer l'erreur
screen.getByText('Clear Error').click()
await waitFor(() => {
expect(screen.getByTestId('error')).toHaveTextContent('No Error')
})
})
})
describe('AuthContext avec useAuth mock', () => {
const mockUseAuth = {
user: null,
token: null,
isAuthenticated: false,
loading: false,
error: null,
login: jest.fn(),
register: jest.fn(),
logout: jest.fn(),
clearError: jest.fn(),
hasPermission: jest.fn(),
hasRole: jest.fn(),
hasAnyRole: jest.fn(),
}
beforeEach(() => {
jest.clearAllMocks()
// Mock direct du hook useAuth
jest.doMock('../../hooks/useAuth', () => ({
__esModule: true,
default: jest.fn(() => mockUseAuth),
}))
})
afterEach(() => {
jest.dontMock('../../hooks/useAuth')
})
it('devrait fournir toutes les méthodes du contexte', () => {
const TestHookComponent = () => {
const auth = useAuthContext()
return (
<div>
<div data-testid="methods-available">
{typeof auth.login === 'function' &&
typeof auth.register === 'function' &&
typeof auth.logout === 'function' &&
typeof auth.clearError === 'function' &&
typeof auth.hasPermission === 'function' &&
typeof auth.hasRole === 'function' &&
typeof auth.hasAnyRole === 'function' ? 'All methods available' : 'Missing methods'}
</div>
</div>
)
}
render(
<AuthProvider>
<TestHookComponent />
</AuthProvider>
)
expect(screen.getByTestId('methods-available')).toHaveTextContent('All methods available')
})
})