import { render, screen, fireEvent, waitFor } from '@testing-library/react'; import { describe, it, expect, vi, beforeEach } from 'vitest'; import { AvatarUpload } from './avatar-upload'; // Mock useToast const mockShowSuccess = vi.fn(); const mockShowError = vi.fn(); vi.mock('@/hooks/useToast', () => ({ useToast: () => ({ success: mockShowSuccess, error: mockShowError, }), })); // Mock avatarService vi.mock('@/features/profile/services/avatarService', () => ({ uploadAvatar: vi.fn().mockResolvedValue({ avatar_url: 'new-avatar.jpg' }), deleteAvatar: vi.fn().mockResolvedValue({}), })); describe('AvatarUpload Component', () => { beforeEach(() => { vi.clearAllMocks(); }); it('renders avatar upload component', () => { render(); expect(screen.getByRole('button', { name: /Cliquez pour uploader/i })).toBeInTheDocument(); }); it('renders current avatar when provided', () => { render(); const image = screen.getByAltText('Avatar preview'); expect(image).toBeInTheDocument(); expect(image).toHaveAttribute('src', 'avatar.jpg'); }); it('shows upload button when no avatar', () => { render(); expect(screen.getByText(/Cliquez pour uploader/i)).toBeInTheDocument(); }); it('shows change button when avatar exists', () => { render(); expect(screen.getByText(/Changer/i)).toBeInTheDocument(); }); it('handles file selection', async () => { const mockOnAvatarUpdated = vi.fn(); const file = new File(['test'], 'test.jpg', { type: 'image/jpeg' }); render(); const input = document.querySelector('input[type="file"]'); expect(input).toBeInTheDocument(); if (input) { Object.defineProperty(input, 'files', { value: [file], writable: false, }); fireEvent.change(input); await waitFor( () => { expect(mockOnAvatarUpdated).toHaveBeenCalled(); }, { timeout: 2000 }, ); } }); it('validates file type', async () => { const file = new File(['test'], 'test.txt', { type: 'text/plain' }); render(); const input = document.querySelector('input[type="file"]'); if (input) { Object.defineProperty(input, 'files', { value: [file], writable: false, }); fireEvent.change(input); await waitFor(() => { expect(mockShowError).toHaveBeenCalled(); }); } }); it('validates file size', async () => { const largeFile = new File(['x'.repeat(10 * 1024 * 1024)], 'large.jpg', { type: 'image/jpeg', }); render(); const input = document.querySelector('input[type="file"]'); if (input) { Object.defineProperty(input, 'files', { value: [largeFile], writable: false, }); fireEvent.change(input); await waitFor(() => { expect(mockShowError).toHaveBeenCalled(); }); } }); it('handles delete action', async () => { const mockOnAvatarDeleted = vi.fn(); render( , ); const deleteButton = screen.getByText(/Supprimer/i); fireEvent.click(deleteButton); await waitFor(() => { expect(mockOnAvatarDeleted).toHaveBeenCalled(); }); }); it('disables when disabled prop is true', () => { render(); const button = screen.getByText(/Cliquez pour uploader/i); expect(button).toBeDisabled(); }); });