fullstack-form-app-sinclqir
Version:
Application de gestion des utilisateurs avec authentification JWT - Frontend React + Backend Python FastAPI
211 lines (159 loc) • 6.72 kB
JSX
import { render, screen, waitFor, fireEvent } from '@testing-library/react';
import UsersList from '../pages/Home/components/UsersList';
import axios from 'axios';
process.env.VITE_API_URL = 'http://localhost:8000';
jest.mock('axios');
describe('UsersList', () => {
const mockUsers = [
{
id: 1,
email: 'user1@test.com',
first_name: 'John',
last_name: 'Doe',
role: 'user',
birth_date: '1990-01-01',
city: 'Paris',
postal_code: '75001',
created_at: '2024-01-01T00:00:00Z'
},
{
id: 2,
email: 'user2@test.com',
first_name: 'Jane',
last_name: 'Smith',
role: 'admin',
birth_date: '1985-05-15',
city: 'Lyon',
postal_code: '69001',
created_at: '2024-01-02T00:00:00Z'
}
];
const mockCurrentUser = {
id: 3,
email: 'admin@test.com',
role: 'admin'
};
beforeEach(() => {
axios.get.mockClear();
axios.delete.mockClear();
});
it('should render users list for admin', async () => {
axios.get.mockResolvedValueOnce({ data: mockUsers });
render(<UsersList currentUser={mockCurrentUser} token="mock-token" />);
await waitFor(() => {
expect(screen.getByText('Gestion des utilisateurs')).toBeInTheDocument();
});
expect(screen.getByText('user1@test.com')).toBeInTheDocument();
expect(screen.getByText('user2@test.com')).toBeInTheDocument();
expect(screen.getByText('2 utilisateurs')).toBeInTheDocument();
});
it('should show delete buttons for admin', async () => {
axios.get.mockResolvedValueOnce({ data: mockUsers });
render(<UsersList currentUser={mockCurrentUser} token="mock-token" />);
await waitFor(() => {
expect(screen.getByText('Gestion des utilisateurs')).toBeInTheDocument();
});
const deleteButtons = screen.getAllByText(/supprimer/i);
expect(deleteButtons.length).toBeGreaterThan(0);
});
it('should not show delete buttons for non-admin users', async () => {
const nonAdminUser = { ...mockCurrentUser, role: 'user' };
axios.get.mockResolvedValueOnce({ data: mockUsers });
render(<UsersList currentUser={nonAdminUser} token="mock-token" />);
await waitFor(() => {
expect(screen.getByText('Gestion des utilisateurs')).toBeInTheDocument();
});
const deleteButtons = screen.queryAllByText(/supprimer/i);
expect(deleteButtons.length).toBe(0);
});
it('should handle user deletion', async () => {
axios.get.mockResolvedValueOnce({ data: mockUsers });
axios.delete.mockResolvedValueOnce({ status: 200 });
// Mock window.confirm
window.confirm = jest.fn(() => true);
render(<UsersList currentUser={mockCurrentUser} token="mock-token" />);
await waitFor(() => {
expect(screen.getByText('Gestion des utilisateurs')).toBeInTheDocument();
});
const deleteButtons = screen.getAllByText(/supprimer/i);
fireEvent.click(deleteButtons[0]);
expect(window.confirm).toHaveBeenCalled();
expect(axios.delete).toHaveBeenCalledWith(
expect.stringContaining('/users/1'),
expect.objectContaining({
headers: { Authorization: 'Bearer mock-token' }
})
);
});
it('should handle loading state', () => {
axios.get.mockImplementation(() => new Promise(() => {})); // Never resolves
render(<UsersList currentUser={mockCurrentUser} token="mock-token" />);
expect(screen.getByText('Chargement en cours...')).toBeInTheDocument();
});
it('should handle error state', async () => {
axios.get.mockRejectedValueOnce(new Error('Network error'));
render(<UsersList currentUser={mockCurrentUser} token="mock-token" />);
await waitFor(() => {
expect(screen.getByText(/erreur/i)).toBeInTheDocument();
});
});
it('should not allow deletion for non-admin users', async () => {
const nonAdminUser = { ...mockCurrentUser, role: 'user' };
axios.get.mockResolvedValueOnce({ data: mockUsers });
render(<UsersList currentUser={nonAdminUser} token="mock-token" />);
await waitFor(() => {
expect(screen.getByText('Gestion des utilisateurs')).toBeInTheDocument();
});
// Simuler une tentative de suppression (ne devrait rien faire)
const component = screen.getByText('Gestion des utilisateurs').closest('.users-list');
// Cette ligne teste le cas où isAdmin est false dans handleDeleteUser
expect(component).toBeInTheDocument();
});
it('should handle deletion cancellation', async () => {
axios.get.mockResolvedValueOnce({ data: mockUsers });
// Mock window.confirm to return false
window.confirm = jest.fn(() => false);
render(<UsersList currentUser={mockCurrentUser} token="mock-token" />);
await waitFor(() => {
expect(screen.getByText('Gestion des utilisateurs')).toBeInTheDocument();
});
const deleteButtons = screen.getAllByText(/supprimer/i);
fireEvent.click(deleteButtons[0]);
expect(window.confirm).toHaveBeenCalled();
expect(axios.delete).not.toHaveBeenCalled();
});
it('should handle deletion error', async () => {
axios.get.mockResolvedValueOnce({ data: mockUsers });
axios.delete.mockRejectedValueOnce({
response: { data: { detail: 'Erreur de suppression' } }
});
// Mock window.confirm and alert
window.confirm = jest.fn(() => true);
window.alert = jest.fn();
render(<UsersList currentUser={mockCurrentUser} token="mock-token" />);
await waitFor(() => {
expect(screen.getByText('Gestion des utilisateurs')).toBeInTheDocument();
});
const deleteButtons = screen.getAllByText(/supprimer/i);
fireEvent.click(deleteButtons[0]);
await waitFor(() => {
expect(window.alert).toHaveBeenCalledWith('Erreur de suppression');
});
});
it('should handle deletion error without response detail', async () => {
axios.get.mockResolvedValueOnce({ data: mockUsers });
axios.delete.mockRejectedValueOnce(new Error('Network error'));
// Mock window.confirm and alert
window.confirm = jest.fn(() => true);
window.alert = jest.fn();
render(<UsersList currentUser={mockCurrentUser} token="mock-token" />);
await waitFor(() => {
expect(screen.getByText('Gestion des utilisateurs')).toBeInTheDocument();
});
const deleteButtons = screen.getAllByText(/supprimer/i);
fireEvent.click(deleteButtons[0]);
await waitFor(() => {
expect(window.alert).toHaveBeenCalledWith('Erreur lors de la suppression');
});
});
});