import { render, screen, fireEvent } from '@testing-library/react' import { describe, it, expect, vi } from 'vitest' import { Search, Mail, Lock } from 'lucide-react' import { Input } from '../Input' describe('Input', () => { it('renders correctly with default props', () => { render() const input = screen.getByPlaceholderText('Enter text') expect(input).toBeInTheDocument() expect(input.tagName).toBe('INPUT') }) it('renders with label', () => { render() const label = screen.getByText('Email') expect(label).toBeInTheDocument() expect(label.tagName).toBe('LABEL') expect(label).toHaveAttribute('for', 'email-input') }) it('renders with error state and message', () => { render( ) const errorMessage = screen.getByTestId('input-error') expect(errorMessage).toBeInTheDocument() expect(errorMessage).toHaveTextContent('This field is required') expect(errorMessage).toHaveAttribute('role', 'alert') const input = screen.getByRole('textbox') expect(input).toHaveClass('border-error') }) it('renders with helper text', () => { render() expect(screen.getByText('Enter your email address')).toBeInTheDocument() }) it('does not show helper text when error is present', () => { render( ) expect(screen.getByText('Error message')).toBeInTheDocument() expect(screen.queryByText('Helper text')).not.toBeInTheDocument() }) it('renders with leftIcon', () => { render() const input = screen.getByRole('textbox') expect(input).toHaveClass('pl-10') // Icon should be rendered const container = input.parentElement const icon = container?.querySelector('svg') expect(icon).toBeInTheDocument() }) it('renders with rightIcon', () => { render() const input = screen.getByRole('textbox') expect(input).toHaveClass('pr-10') }) it('renders with both leftIcon and rightIcon', () => { render() const input = screen.getByRole('textbox') expect(input).toHaveClass('pl-10') expect(input).toHaveClass('pr-10') }) it('renders disabled state', () => { render() const input = screen.getByPlaceholderText('Disabled input') expect(input).toBeDisabled() expect(input).toHaveClass('disabled:cursor-not-allowed') expect(input).toHaveClass('disabled:opacity-50') }) it('applies custom className', () => { render() const input = screen.getByRole('textbox') expect(input).toHaveClass('custom-class') }) it('forwards ref correctly', () => { const ref = vi.fn() render() expect(ref).toHaveBeenCalled() expect(ref.mock.calls[0][0]).toBeInstanceOf(HTMLInputElement) }) it('handles password type with toggle visibility', () => { render() const input = screen.getByPlaceholderText('Enter password') expect(input).toHaveAttribute('type', 'password') // Toggle button should be present const toggleButton = screen.getByRole('button', { name: /show password/i }) expect(toggleButton).toBeInTheDocument() // Click to show password fireEvent.click(toggleButton) expect(input).toHaveAttribute('type', 'text') expect(screen.getByRole('button', { name: /hide password/i })).toBeInTheDocument() // Click again to hide fireEvent.click(screen.getByRole('button', { name: /hide password/i })) expect(input).toHaveAttribute('type', 'password') }) it('does not show password toggle for non-password types', () => { render() expect(screen.queryByRole('button', { name: /password/i })).not.toBeInTheDocument() }) it('handles value changes', () => { const handleChange = vi.fn() render() const input = screen.getByPlaceholderText('Input') fireEvent.change(input, { target: { value: 'test value' } }) expect(handleChange).toHaveBeenCalled() expect(input).toHaveValue('test value') }) it('renders password input with leftIcon', () => { render() const input = screen.getByPlaceholderText('Password') expect(input).toHaveClass('pl-10') expect(input).toHaveClass('pr-10') // Password toggle adds right padding }) it('prioritizes password toggle over rightIcon for password type', () => { render() // Should show password toggle, not the Mail icon expect(screen.getByRole('button', { name: /show password/i })).toBeInTheDocument() }) })