import React from 'react'; import { render, screen } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import { TextInput } from './'; describe('TextInput component', () => { const value = 'abc'; const onChange = vi.fn(); describe('given an `id` props', () => { it('adds the `id` from props Input component', () => { render(); expect(screen.getByRole('textbox')).toHaveAttribute('id', 'my-input'); }); }); describe('given a `isDisabled` props', () => { it('adds the `isDisabled` from props to the Input component', () => { render(); expect(screen.getByRole('textbox')).toBeDisabled(); }); }); describe('given a `name` props', () => { it('adds the `name` from props to the Input component', () => { render(); expect(screen.getByRole('textbox')).toHaveAttribute('name', 'first-name'); }); }); describe('given a `placeholder` props', () => { it('adds the `placeholder` from props to the Input component', () => { render( , ); expect(screen.getByPlaceholderText('Write something')).toBeVisible(); }); }); describe('given accessibility props', () => { it('can be accessible using aria-label', () => { render( , ); expect(screen.getByRole('textbox', { name: 'myLabel' })).toBeVisible(); }); it('can be accessible using aria-labelledby', () => { render(

myLabel

,
, ); expect(screen.getByRole('textbox', { name: 'myLabel' })).toBeVisible(); }); }); describe('Given event handler', () => { /** * Grapes returns a Synthetic Event and not the input value. If we mock an event handler function, * Vitest will read the event, preventing us from reading it again to make assertion. * The solution is to not make an assertion about how event handler are called but how * the component works with other. */ it('calls onChange and onKeyDown when user types', async () => { const Wrapper = () => { const [text, setText] = React.useState(''); return ( ) => setText(e.target.value) } onKeyDown={(e: React.KeyboardEvent) => { if (e.shiftKey) { setText('shift'); } }} /> ); }; render(); const textInput = screen.getByRole('textbox'); await userEvent.type(textInput, 'myname'); expect(textInput).toHaveValue('myname'); await userEvent.type(textInput, '{shift}'); expect(textInput).toHaveValue('shift'); }); it('calls onFocus and onBlur depending on user focus', async () => { const handleFocus = vi.fn(); const handleBlur = vi.fn(); render( , ); const textInput = screen.getByRole('textbox'); expect(textInput).not.toHaveFocus(); expect(handleFocus).toHaveBeenCalledTimes(0); await userEvent.tab(); // focus input expect(textInput).toHaveFocus(); expect(handleFocus).toHaveBeenCalledTimes(1); expect(handleBlur).toHaveBeenCalledTimes(0); await userEvent.tab(); // unfocus input expect(textInput).not.toHaveFocus(); expect(handleBlur).toHaveBeenCalledTimes(1); }); }); describe('Given a ref', () => { it('foward the ref to the input (uncontrolled component)', async () => { const ref = React.createRef(); render(); const textInput = screen.getByRole('textbox'); await userEvent.type(textInput, 'world'); expect(ref.current?.value).toBe('helloworld'); }); }); });