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 { 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,
}),
}));
// Mock useAuthStore
const mockUser = {
id: 1,
username: 'testuser',
email: 'test@example.com',
first_name: 'Test',
last_name: 'User',
bio: 'Test bio',
};
const mockRefreshUser = vi.fn();
vi.mock('@/stores/auth', () => ({
useAuthStore: () => ({
user: mockUser,
refreshUser: mockRefreshUser,
isAuthenticated: true,
}),
}));
// Mock useUIStore
vi.mock('@/stores/ui', () => ({
useUIStore: () => ({
addNotification: vi.fn(),
}),
}));
// Mock apiService
vi.mock('@/services/api', () => ({
apiService: {
updateUser: vi.fn().mockResolvedValue({
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('profile.personalInfo')).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();
});
});