import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest'; import { render, screen, waitFor } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import { CommentForm } from './CommentForm'; import { useToast } from '@/hooks/useToast'; // Mock dependencies vi.mock('@/hooks/useToast'); describe('CommentForm', () => { const mockToast = { success: vi.fn(), error: vi.fn(), warning: vi.fn(), info: vi.fn(), toast: vi.fn(), }; const mockOnSubmit = vi.fn(); beforeEach(() => { vi.clearAllMocks(); vi.mocked(useToast).mockReturnValue(mockToast); }); afterEach(() => { vi.restoreAllMocks(); }); it('should render comment form', () => { render(); expect( screen.getByPlaceholderText('Écrivez un commentaire...'), ).toBeInTheDocument(); expect( screen.getByRole('button', { name: /commenter/i }), ).toBeInTheDocument(); }); it('should submit comment', async () => { const user = userEvent.setup(); mockOnSubmit.mockResolvedValue(undefined); render(); const textarea = screen.getByPlaceholderText('Écrivez un commentaire...'); await user.type(textarea, 'Test comment'); const submitButton = screen.getByRole('button', { name: /commenter/i }); await user.click(submitButton); await waitFor(() => { expect(mockOnSubmit).toHaveBeenCalledWith('Test comment', undefined); }); }); it('should submit reply comment', async () => { const user = userEvent.setup(); mockOnSubmit.mockResolvedValue(undefined); render(); const textarea = screen.getByPlaceholderText('Écrivez un commentaire...'); await user.type(textarea, 'Test reply'); const submitButton = screen.getByRole('button', { name: /répondre/i }); await user.click(submitButton); await waitFor(() => { expect(mockOnSubmit).toHaveBeenCalledWith('Test reply', 1); }); }); it('should show error for empty comment', async () => { const user = userEvent.setup(); render(); const submitButton = screen.getByRole('button', { name: /commenter/i }); await user.click(submitButton); await waitFor(() => { expect(mockToast.error).toHaveBeenCalledWith( 'Le commentaire ne peut pas être vide', ); expect(mockOnSubmit).not.toHaveBeenCalled(); }); }); it('should show error for comment too long', async () => { const user = userEvent.setup(); const longContent = 'a'.repeat(5001); render(); const textarea = screen.getByPlaceholderText('Écrivez un commentaire...'); await user.type(textarea, longContent); const submitButton = screen.getByRole('button', { name: /commenter/i }); await user.click(submitButton); await waitFor(() => { expect(mockToast.error).toHaveBeenCalledWith( 'Le commentaire ne peut pas dépasser 5000 caractères', ); expect(mockOnSubmit).not.toHaveBeenCalled(); }); }); it('should display character count', async () => { const user = userEvent.setup(); render(); const textarea = screen.getByPlaceholderText('Écrivez un commentaire...'); await user.type(textarea, 'Test'); expect(screen.getByText('4/5000')).toBeInTheDocument(); }); it('should call onCancel when cancel button is clicked', async () => { const user = userEvent.setup(); const mockOnCancel = vi.fn(); render(); const cancelButton = screen.getByRole('button', { name: /annuler/i }); await user.click(cancelButton); expect(mockOnCancel).toHaveBeenCalled(); }); it('should clear form after successful submit', async () => { const user = userEvent.setup(); mockOnSubmit.mockResolvedValue(undefined); render(); const textarea = screen.getByPlaceholderText( 'Écrivez un commentaire...', ) as HTMLTextAreaElement; await user.type(textarea, 'Test comment'); const submitButton = screen.getByRole('button', { name: /commenter/i }); await user.click(submitButton); await waitFor(() => { expect(textarea.value).toBe(''); }); }); it('should show loading state during submit', async () => { const user = userEvent.setup(); mockOnSubmit.mockImplementation( () => new Promise((resolve) => { setTimeout(() => resolve(undefined), 100); }), ); render(); const textarea = screen.getByPlaceholderText('Écrivez un commentaire...'); await user.type(textarea, 'Test comment'); const submitButton = screen.getByRole('button', { name: /commenter/i }); await user.click(submitButton); await waitFor(() => { expect(screen.getByText(/envoi/i)).toBeInTheDocument(); expect(submitButton).toBeDisabled(); }); }); it('should handle submit error', async () => { const user = userEvent.setup(); const error = new Error('Failed to create comment'); mockOnSubmit.mockRejectedValue(error); render(); const textarea = screen.getByPlaceholderText('Écrivez un commentaire...'); await user.type(textarea, 'Test comment'); const submitButton = screen.getByRole('button', { name: /commenter/i }); await user.click(submitButton); await waitFor(() => { expect(mockToast.error).toHaveBeenCalledWith('Failed to create comment'); }); }); });