import { render, screen, waitFor } from '@testing-library/react'; import { describe, it, expect, vi, beforeEach } from 'vitest'; import userEvent from '@testing-library/user-event'; import { BrowserRouter } from 'react-router-dom'; import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; import { ToastProvider } from '@/components/feedback/ToastProvider'; import { ProfileForm } from './ProfileForm'; // Mock useTranslation vi.mock('@/hooks/useTranslation', () => ({ useTranslation: () => ({ t: (key: string) => key, i18n: { changeLanguage: vi.fn() }, language: 'fr', changeLanguage: vi.fn(), isReady: true, }), })); const mockUser = { id: '1', username: 'testuser', email: 'test@example.com', first_name: 'Test', last_name: 'User', bio: 'Test bio', }; vi.mock('@/features/auth/hooks/useUser', () => ({ useUser: () => ({ data: mockUser, isLoading: false, error: null, }), })); // Mock useUIStore vi.mock('@/stores/ui', () => ({ useUIStore: () => ({ addNotification: vi.fn(), }), })); // Mock apiClient vi.mock('@/services/api/client', () => ({ apiClient: { put: vi.fn().mockResolvedValue({ data: { id: 1, username: 'testuser', email: 'test@example.com', first_name: 'Test', last_name: 'User', bio: 'Test bio', }, }), }, })); const createTestQueryClient = () => new QueryClient({ defaultOptions: { queries: { retry: false }, mutations: { retry: false }, }, }); const TestWrapper = ({ children }: { children: React.ReactNode }) => { const queryClient = createTestQueryClient(); return ( {children} ); }; describe('ProfileForm Component', () => { beforeEach(() => { vi.clearAllMocks(); }); it('renders profile form correctly', () => { render( , ); expect(screen.getByText('profile.title')).toBeInTheDocument(); expect(screen.getByText('Personal Information')).toBeInTheDocument(); }); it('displays user information', () => { render( , ); expect(screen.getByDisplayValue('testuser')).toBeInTheDocument(); expect(screen.getByDisplayValue('test@example.com')).toBeInTheDocument(); expect(screen.getByDisplayValue('Test')).toBeInTheDocument(); expect(screen.getByDisplayValue('User')).toBeInTheDocument(); }); it('enables editing mode when edit button is clicked', async () => { const user = userEvent.setup(); render( , ); const editButton = screen.getByText('profile.edit'); await user.click(editButton); // Les champs devraient être éditables const usernameInput = screen.getByDisplayValue('testuser'); expect(usernameInput).not.toBeDisabled(); }); it('validates form fields', async () => { const user = userEvent.setup(); render( , ); const editButton = screen.getByText('profile.edit'); await user.click(editButton); // Vider le champ username const usernameInput = screen.getByDisplayValue('testuser'); await user.clear(usernameInput); await user.type(usernameInput, 'ab'); // Trop court // Vider le champ email const emailInput = screen.getByDisplayValue('test@example.com'); await user.clear(emailInput); await user.type(emailInput, 'invalid-email'); // Soumettre le formulaire const saveButton = screen.getByText('profile.save'); await user.click(saveButton); // Attendre que les erreurs de validation apparaissent await waitFor(() => { expect( screen.getByText( /Le nom d'utilisateur doit contenir au moins 3 caractères/, ), ).toBeInTheDocument(); }); }); it('allows form submission with valid data', async () => { const user = userEvent.setup(); render( , ); const editButton = screen.getByText('profile.edit'); await user.click(editButton); const usernameInput = screen.getByDisplayValue('testuser'); expect(usernameInput).not.toBeDisabled(); await user.clear(usernameInput); await user.type(usernameInput, 'newusername'); const saveButton = screen.getByText('profile.save'); expect(saveButton).toBeInTheDocument(); expect(saveButton).not.toBeDisabled(); }); it('cancels editing and resets form', async () => { const user = userEvent.setup(); render( , ); const editButton = screen.getByText('profile.edit'); await user.click(editButton); const usernameInput = screen.getByDisplayValue('testuser'); await user.clear(usernameInput); await user.type(usernameInput, 'modified'); const cancelButton = screen.getByText('profile.cancel'); await user.click(cancelButton); // Le formulaire devrait être réinitialisé await waitFor(() => { expect(screen.getByDisplayValue('testuser')).toBeInTheDocument(); }); // Les champs devraient être désactivés expect(usernameInput).toBeDisabled(); }); it('handles avatar upload', async () => { const user = userEvent.setup(); render( , ); const editButton = screen.getByText('profile.edit'); await user.click(editButton); // Trouver le bouton d'upload d'avatar const avatarButton = screen.getByText('profile.avatar.changePhoto'); expect(avatarButton).toBeInTheDocument(); }); });