/* eslint-disable jest/require-top-level-describe */ import React from 'react'; import PropTypes from 'prop-types'; import { fireEvent, render } from '@testing-library/react'; import { renderWithUserEvent } from '../../../../test/lib/render-helpers'; import { Size } from '../../../helpers/constants/design-system'; import Box from '../../ui/box'; import { TextField } from './text-field'; describe('TextField', () => { it('should render correctly', () => { const { getByRole, container } = render(); expect(getByRole('textbox')).toBeDefined(); expect(container).toMatchSnapshot(); }); it('should render and be able to input text', () => { const { getByTestId } = render( , ); const textField = getByTestId('text-field'); expect(textField.value).toBe(''); // initial value is empty string fireEvent.change(textField, { target: { value: 'text value' } }); expect(textField.value).toBe('text value'); fireEvent.change(textField, { target: { value: '' } }); // reset value expect(textField.value).toBe(''); // value is empty string after reset }); it('should render with focused state when clicked', async () => { const { getByTestId, user } = renderWithUserEvent( , ); const textField = getByTestId('input'); await user.click(textField); expect(getByTestId('input')).toHaveFocus(); expect(getByTestId('text-field')).toHaveClass('mm-text-field--focused '); }); it('should render and fire onFocus and onBlur events', async () => { const onFocus = jest.fn(); const onBlur = jest.fn(); const { getByTestId, user } = renderWithUserEvent( , ); const textField = getByTestId('text-field'); await user.click(textField); expect(onFocus).toHaveBeenCalledTimes(1); fireEvent.blur(textField); expect(onBlur).toHaveBeenCalledTimes(1); }); it('should render and fire onChange event', async () => { const onChange = jest.fn(); const { getByTestId, user } = renderWithUserEvent( , ); const textField = getByTestId('text-field'); await user.type(textField, '123'); expect(textField).toHaveValue('123'); expect(onChange).toHaveBeenCalledTimes(3); }); it('should render and fire onClick event', async () => { const onClick = jest.fn(); const { getByTestId, user } = renderWithUserEvent( , ); const textField = getByTestId('text-field'); await user.click(textField); expect(onClick).toHaveBeenCalledTimes(1); }); it('should render with different size classes', () => { const { getByTestId } = render( <> , ); expect(getByTestId('sm')).toHaveClass('mm-text-field--size-sm'); expect(getByTestId('md')).toHaveClass('mm-text-field--size-md'); expect(getByTestId('lg')).toHaveClass('mm-text-field--size-lg'); }); it('should render with different types', () => { const { getByTestId } = render( <> , ); expect(getByTestId('text-field-text')).toHaveAttribute('type', 'text'); expect(getByTestId('text-field-number')).toHaveAttribute('type', 'number'); expect(getByTestId('text-field-password')).toHaveAttribute( 'type', 'password', ); }); it('should render with truncate class as true by default and remove it when truncate is false', () => { const { getByTestId } = render( <> , ); expect(getByTestId('truncate')).toHaveClass('mm-text-field--truncate'); expect(getByTestId('no-truncate')).not.toHaveClass( 'mm-text-field--truncate', ); }); it('should render with right and left accessories', () => { const { getByRole, getByText } = render( start accessory} endAccessory={
end accessory
} />, ); expect(getByRole('textbox')).toBeDefined(); expect(getByText('start accessory')).toBeDefined(); expect(getByText('end accessory')).toBeDefined(); }); it('should render with working ref using inputRef prop', () => { // Because the 'ref' attribute wont flow down to the DOM // I'm not exactly sure how to test this? const mockRef = jest.fn(); const { getByRole } = render(); expect(getByRole('textbox')).toBeDefined(); expect(mockRef).toHaveBeenCalledTimes(1); }); it('should render with autoComplete', () => { const { getByTestId } = render( , ); expect(getByTestId('text-field-auto-complete')).toHaveAttribute( 'autocomplete', 'on', ); }); it('should render with autoFocus', () => { const { getByRole } = render(); expect(getByRole('textbox')).toHaveFocus(); }); it('should render with a defaultValue', () => { const { getByRole } = render( , ); expect(getByRole('textbox').value).toBe('default value'); }); it('should render in disabled state and not focus or be clickable', async () => { const mockOnClick = jest.fn(); const mockOnFocus = jest.fn(); const { getByRole, getByTestId, user } = renderWithUserEvent( , ); const textField = getByTestId('text-field'); await user.click(textField); expect(getByRole('textbox')).toBeDisabled(); expect(mockOnClick).toHaveBeenCalledTimes(0); expect(mockOnFocus).toHaveBeenCalledTimes(0); }); it('should render with error className when error is true', () => { const { getByTestId } = render( , ); expect(getByTestId('text-field-error')).toHaveClass('mm-text-field--error'); }); it('should render with maxLength and not allow more than the set characters', async () => { const { getByRole, user } = renderWithUserEvent( , ); const textField = getByRole('textbox'); await user.type(textField, '1234567890'); expect(getByRole('textbox')).toBeDefined(); expect(textField.maxLength).toBe(5); expect(textField.value).toBe('12345'); expect(textField.value).toHaveLength(5); }); it('should render with readOnly attr when readOnly is true', async () => { const { getByTestId, getByRole, user } = renderWithUserEvent( , ); const textField = getByTestId('read-only'); await user.type(textField, '1234567890'); expect(getByRole('textbox').value).toBe(''); expect(getByRole('textbox')).toHaveAttribute('readonly', ''); }); it('should render with required attr when required is true', () => { const { getByTestId } = render( , ); expect(getByTestId('text-field-required')).toHaveAttribute('required', ''); }); it('should render with a custom input and still work', async () => { const CustomInputComponent = React.forwardRef( ({ disableStateStyles, ...props }, ref) => ( ), ); CustomInputComponent.propTypes = { disableStateStyles: PropTypes.bool, }; CustomInputComponent.displayName = 'CustomInputComponent'; // fixes eslint error const { getByTestId, user } = renderWithUserEvent( , ); const textField = getByTestId('text-field'); expect(textField.value).toBe(''); // initial value is empty string await user.type(textField, 'text value'); expect(textField.value).toBe('text value'); fireEvent.change(textField, { target: { value: '' } }); // reset value expect(textField.value).toBe(''); // value is empty string after reset }); it('should render the child Input with disableStateStyles to prevent multiple focus outlines', async () => { const { getByTestId, user } = renderWithUserEvent( , ); const InputComponent = getByTestId('input'); await user.click(InputComponent); expect(getByTestId('input')).toHaveFocus(); expect(getByTestId('input')).toHaveClass('mm-input--disable-state-styles'); }); });