import { describe, it, expect, vi } from 'vitest'; import { render, screen } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import { AuthInput } from './AuthInput'; import { AuthButton } from './AuthButton'; import { AuthFormField } from './AuthFormField'; import { AuthErrorMessage } from './AuthErrorMessage'; describe('AuthInput', () => { it('should render input with label', () => { render(); expect(screen.getByLabelText('Email')).toBeInTheDocument(); }); it('should display error message when error prop is provided', () => { render(); expect(screen.getByText('Invalid email')).toBeInTheDocument(); expect(screen.getByRole('alert')).toBeInTheDocument(); }); it('should have aria-invalid when error is present', () => { render(); const input = screen.getByRole('textbox'); expect(input).toHaveAttribute('aria-invalid', 'true'); }); it('should apply error styles when error is present', () => { render(); const input = screen.getByRole('textbox'); expect(input.className).toContain('border-red-500'); }); it('should handle user input', async () => { const user = userEvent.setup(); const handleChange = vi.fn(); render( , ); const input = screen.getByLabelText('Email'); await user.type(input, 'test@example.com'); expect(handleChange).toHaveBeenCalled(); expect(input).toHaveValue('test@example.com'); }); it('should support all standard input props', () => { render( , ); const input = screen.getByLabelText('Password'); expect(input).toHaveAttribute('type', 'password'); expect(input).toHaveAttribute('placeholder', 'Enter password'); expect(input).toBeRequired(); }); }); describe('AuthButton', () => { it('should render button with children', () => { render(Submit); expect(screen.getByRole('button', { name: 'Submit' })).toBeInTheDocument(); }); it('should show loading state', () => { render(Submit); expect(screen.getByText('Chargement...')).toBeInTheDocument(); expect(screen.getByRole('button')).toBeDisabled(); expect(screen.getByRole('button')).toHaveAttribute('aria-busy', 'true'); }); it('should be disabled when loading', () => { render(Submit); expect(screen.getByRole('button')).toBeDisabled(); }); it('should be disabled when disabled prop is true', () => { render(Submit); expect(screen.getByRole('button')).toBeDisabled(); }); it('should apply primary variant styles by default', () => { render(Submit); const button = screen.getByRole('button'); expect(button.className).toContain('bg-blue-600'); }); it('should apply secondary variant styles', () => { render(Cancel); const button = screen.getByRole('button'); expect(button.className).toContain('bg-gray-200'); }); it('should handle click events', async () => { const user = userEvent.setup(); const handleClick = vi.fn(); render(Click me); const button = screen.getByRole('button'); await user.click(button); expect(handleClick).toHaveBeenCalledTimes(1); }); it('should not trigger click when disabled', async () => { const user = userEvent.setup(); const handleClick = vi.fn(); render( Click me , ); const button = screen.getByRole('button'); await user.click(button); expect(handleClick).not.toHaveBeenCalled(); }); }); describe('AuthFormField', () => { it('should render label and children', () => { render( , ); expect(screen.getByText('Email')).toBeInTheDocument(); }); it('should show required indicator', () => { render( , ); const label = screen.getByText('Email'); expect(label.textContent).toContain('*'); }); it('should display error message', () => { render( , ); expect(screen.getByText('Invalid email')).toBeInTheDocument(); expect(screen.getByRole('alert')).toBeInTheDocument(); }); it('should display help text when no error', () => { render( , ); expect(screen.getByText('Enter your email address')).toBeInTheDocument(); }); it('should not display help text when error is present', () => { render( , ); expect(screen.getByText('Invalid email')).toBeInTheDocument(); expect( screen.queryByText('Enter your email address'), ).not.toBeInTheDocument(); }); }); describe('AuthErrorMessage', () => { it('should render error message', () => { render(); expect(screen.getByText('An error occurred')).toBeInTheDocument(); expect(screen.getByRole('alert')).toBeInTheDocument(); }); it('should not render when message is empty', () => { const { container } = render(); expect(container.firstChild).toBeNull(); }); it('should have aria-live attribute', () => { render(); const alert = screen.getByRole('alert'); expect(alert).toHaveAttribute('aria-live', 'polite'); }); it('should apply custom className', () => { render(); const alert = screen.getByRole('alert'); expect(alert.className).toContain('custom-class'); }); it('should support custom id', () => { render(); const alert = screen.getByRole('alert'); expect(alert).toHaveAttribute('id', 'custom-error-id'); }); });