import { render, screen } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import React from 'react'; import { describe, expect, it, vi } from 'vitest'; import { MdInput } from '../MdInput'; describe('MdInput', () => { describe('rendering', () => { it('renders an input element', () => { render(); expect(screen.getByRole('textbox')).toBeInTheDocument(); }); it('renders with label', () => { render(); expect(screen.getByLabelText('Username')).toBeInTheDocument(); }); it('renders with placeholder', () => { render(); expect(screen.getByPlaceholderText('Enter text')).toBeInTheDocument(); }); it('renders with suffix', () => { const { container } = render(); expect(container.querySelector('.md-input--has-suffix')).toBeInTheDocument(); }); it('renders with prefix icon', () => { const { container } = render(} />); expect(container.querySelector('.md-input--has-prefix')).toBeInTheDocument(); }); }); describe('states', () => { it('can be disabled', () => { render(); expect(screen.getByRole('textbox')).toBeDisabled(); }); it('applies disabled class', () => { const { container } = render(); expect(container.querySelector('.md-input--disabled')).toBeInTheDocument(); }); it('can be readonly', () => { render(); expect(screen.getByRole('textbox')).toHaveAttribute('readonly'); }); it('applies readonly class', () => { const { container } = render(); expect(container.querySelector('.md-input--readonly')).toBeInTheDocument(); }); it('shows error state', () => { const { container } = render(); expect(container.querySelector('.md-input--error')).toBeInTheDocument(); }); it('shows error text when error is true', () => { render(); expect(screen.getByText('This field is required')).toBeInTheDocument(); }); it('shows support text', () => { render(); expect(screen.getByText('Helper message')).toBeInTheDocument(); }); }); describe('modes', () => { it('applies small mode class', () => { const { container } = render(); expect(container.querySelector('.md-input--small')).toBeInTheDocument(); }); it('applies large mode class', () => { const { container } = render(); expect(container.querySelector('.md-input--large')).toBeInTheDocument(); }); }); describe('interactions', () => { it('handles typing', async () => { const user = userEvent.setup(); const onChange = vi.fn(); render(); await user.type(screen.getByRole('textbox'), 'hello'); expect(onChange).toHaveBeenCalled(); }); it('handles focus', async () => { const user = userEvent.setup(); const onFocus = vi.fn(); render(); await user.click(screen.getByRole('textbox')); expect(onFocus).toHaveBeenCalled(); }); it('handles blur', async () => { const user = userEvent.setup(); const onBlur = vi.fn(); render(); await user.click(screen.getByRole('textbox')); await user.tab(); expect(onBlur).toHaveBeenCalled(); }); }); describe('help text', () => { it('renders help button when helpText is provided', () => { render(); expect(screen.getByRole('button')).toBeInTheDocument(); }); it('shows help text when help button is clicked', async () => { const user = userEvent.setup(); render(); await user.click(screen.getByRole('button')); expect(screen.getByText('Help information')).toBeInTheDocument(); }); }); describe('props forwarding', () => { it('forwards id', () => { render(); expect(screen.getByRole('textbox')).toHaveAttribute('id', 'my-input'); }); it('forwards name', () => { render(); expect(screen.getByRole('textbox')).toHaveAttribute('name', 'username'); }); it('forwards type', () => { render(); expect(screen.getByRole('textbox')).toHaveAttribute('type', 'email'); }); it('merges custom className', () => { const { container } = render(); expect(container.querySelector('.md-input')).toHaveClass('custom-class'); }); }); describe('accessibility', () => { it('associates label with input', () => { render(); const input = screen.getByRole('textbox'); expect(input).toHaveAttribute('id', 'email'); expect(screen.getByLabelText('Email')).toBe(input); }); it('sets aria-describedby for error text', () => { render(); const input = screen.getByRole('textbox'); expect(input).toHaveAttribute('aria-describedby'); }); }); describe('ref forwarding', () => { it('forwards ref to input element', () => { const ref = React.createRef(); render(); expect(ref.current).toBeInstanceOf(HTMLInputElement); }); }); });