import { fireEvent, render, screen } from '@testing-library/react' import { describe, expect, it, vi } from 'vitest' import TextInput from './TextInput' describe('TextInput Component', () => { const defaultProps = { value: '', callout: vi.fn< (stateName: string | number | undefined, value: string | number) => void >(), labelText: 'Test Input', stateName: 'test', } it('renders basic text input with label', () => { render() const container = screen.getByTestId('text-input-container') const label = screen.getByTestId('form-label') const input = screen.getByTestId('text-input-field') expect(container).toBeInTheDocument() expect(label).toBeInTheDocument() expect(input).toBeInTheDocument() expect(label).toHaveTextContent('Test Input') }) it('handles text input changes', () => { render() const input = screen.getByTestId('text-input-field') fireEvent.change(input, { target: { value: 'test value' } }) expect(input).toHaveValue('test value') expect(defaultProps.callout).toHaveBeenCalledWith('test', 'test value') }) it('renders textarea when type is textarea', () => { render() const textarea = screen.getByTestId('text-input-textarea') expect(textarea).toBeInTheDocument() }) it('handles password visibility toggle', () => { render() const input = screen.getByTestId('text-input-field') expect(input).toHaveAttribute('type', 'password') const toggleButton = screen.getByRole('button') fireEvent.click(toggleButton) expect(input).toHaveAttribute('type', 'text') }) it('shows error state and message', () => { const errorText = 'This field is required' render( , ) const error = screen.getByTestId('text-input-error') expect(error).toBeInTheDocument() expect(error).toHaveTextContent(errorText) }) it('handles currency input format', () => { render( , ) const currencySymbol = screen.getByTestId('text-input-currency') expect(currencySymbol).toBeInTheDocument() expect(currencySymbol).toHaveTextContent('$') }) it('handles disabled state', () => { render() const input = screen.getByTestId('text-input-field') expect(input).toBeDisabled() }) it('handles required state', () => { render() const input = screen.getByTestId('text-input-field') expect(input).toBeRequired() }) it('handles clear button functionality', () => { const clearCallout = vi.fn<() => void>() render( , ) const xIcon = screen.getByTestId('icon-x') expect(xIcon).toBeInTheDocument() fireEvent.click(xIcon) expect(clearCallout).toHaveBeenCalled() }) it('handles input with end text', () => { render() const endText = screen.getByTestId('text-input-end-text') expect(endText).toBeInTheDocument() expect(endText).toHaveValue('%') }) it('handles number input with min/max constraints', () => { render( , ) const input = screen.getByTestId('text-input-field') fireEvent.change(input, { target: { value: '150' } }) expect(input).toHaveValue(100) }) it('handles debounced input', async () => { vi.useFakeTimers() render() defaultProps.callout.mockClear() // this is needed to avoid the initial callout when the input is rendered const input = screen.getByTestId('text-input-field') fireEvent.change(input, { target: { value: 'test' } }) expect(defaultProps.callout).not.toHaveBeenCalled() vi.advanceTimersByTime(500) expect(defaultProps.callout).toHaveBeenCalledTimes(1) expect(defaultProps.callout).toHaveBeenCalledWith('test', 'test') vi.useRealTimers() }) it('handles auto-resize textarea', () => { render() const textarea = screen.getByTestId('text-input-textarea') expect(textarea).toHaveClass('textareaAutoResize') }) it('handles input with suffix label', () => { render() const suffix = screen.getByTestId('text-input-suffix') expect(suffix).toBeInTheDocument() expect(suffix).toHaveTextContent('kg') }) it('handles onBlur callback', () => { const onBlurCallout = vi.fn< (stateName: string | number | undefined, value: string | number) => void >() render() const input = screen.getByTestId('text-input-field') fireEvent.blur(input) expect(onBlurCallout).toHaveBeenCalledWith('test', '') }) it('handles onReturn callback', () => { const onReturnCallout = vi.fn<() => void>() render() const input = screen.getByTestId('text-input-field') fireEvent.keyDown(input, { key: 'Enter' }) expect(onReturnCallout).toHaveBeenCalled() }) })