223 lines
6.3 KiB
TypeScript
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')
|
|
})
|
|
}) |