/* eslint-disable jest/require-top-level-describe */ import React from 'react'; import { fireEvent, render } from '@testing-library/react'; import { renderControlledInput, renderWithUserEvent, } from '../../../../test/lib/render-helpers'; import { SIZES } from '../../../helpers/constants/design-system'; import { FormTextField } from './form-text-field'; describe('FormTextField', () => { it('should render correctly', () => { const { getByRole, container } = render(); expect(getByRole('textbox')).toBeDefined(); expect(container).toMatchSnapshot(); }); // autoComplete it('should render with autoComplete', () => { const { getByTestId } = render( , ); expect(getByTestId('form-text-field-auto-complete')).toHaveAttribute( 'autocomplete', 'on', ); }); // autoFocus it('should render with autoFocus', () => { const { getByRole } = render(); expect(getByRole('textbox')).toHaveFocus(); }); // className it('should render with custom className', () => { const { getByTestId } = render( , ); expect(getByTestId('form-text-field')).toHaveClass('test-class'); }); // defaultValue it('should render with a defaultValue', () => { const { getByRole } = render( , ); expect(getByRole('textbox').value).toBe('default value'); }); // disabled it('should render in disabled state and not focus or be clickable', async () => { const mockOnClick = jest.fn(); const mockOnFocus = jest.fn(); const { getByRole, user, getByLabelText } = renderWithUserEvent( , ); await user.click(getByLabelText('test label')); expect(mockOnFocus).toHaveBeenCalledTimes(0); await user.type(getByRole('textbox'), 'test value'); expect(getByRole('textbox')).not.toHaveValue('test value'); expect(getByRole('textbox')).toBeDisabled(); expect(mockOnClick).toHaveBeenCalledTimes(0); expect(mockOnFocus).toHaveBeenCalledTimes(0); }); // error it('should render with error classNames on TextField and HelpText components when error is true', () => { const { getByTestId, getByText } = render( , ); expect(getByTestId('text-field')).toHaveClass('mm-text-field-base--error'); expect(getByText('test help text')).toHaveClass( 'text--color-error-default', ); }); // helpText it('should render with helpText', () => { const { getByText } = render(); expect(getByText('test help text')).toBeDefined(); }); // helpTextProps it('should render with helpText and helpTextProps', () => { const { getByText, getByTestId } = render( , ); expect(getByText('test help text')).toBeDefined(); expect(getByTestId('help-text-test')).toBeDefined(); }); // id it('should render the FormTextField with an id and pass it to input and Label as htmlFor. When clicking on Label the input should have focus', async () => { const onFocus = jest.fn(); const { getByRole, getByLabelText, user } = renderWithUserEvent( , ); expect(getByRole('textbox')).toHaveAttribute('id', 'test-id'); await user.click(getByLabelText('test label')); expect(onFocus).toHaveBeenCalledTimes(1); expect(getByRole('textbox')).toHaveFocus(); }); // inputProps it('should render with inputProps', () => { const { getByTestId } = render( , ); expect(getByTestId('test-id')).toBeDefined(); }); // inputRef 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); }); // label it('should render with a label', () => { const { getByLabelText } = render( , ); expect(getByLabelText('test label')).toBeDefined(); }); // labelProps it('should render with a labelProps', () => { const { getByTestId, getByLabelText } = render( , ); expect(getByLabelText('test label')).toBeDefined(); expect(getByTestId('label-test-id')).toBeDefined(); }); // leftAccessory, // rightAccessory it('should render with right and left accessories', () => { const { getByRole, getByText } = render( left accessory} rightAccessory={
right accessory
} />, ); expect(getByRole('textbox')).toBeDefined(); expect(getByText('left accessory')).toBeDefined(); expect(getByText('right accessory')).toBeDefined(); }); // maxLength; it('should render with maxLength and not allow more than the set characters', async () => { const { getByRole, user } = renderWithUserEvent( , ); const formTextField = getByRole('textbox'); await user.type(formTextField, '1234567890'); expect(getByRole('textbox')).toBeDefined(); expect(formTextField.maxLength).toBe(5); expect(formTextField.value).toBe('12345'); expect(formTextField.value).toHaveLength(5); }); // name it('should render with name prop', () => { const { getByRole } = render(); expect(getByRole('textbox')).toHaveAttribute('name', 'test-name'); }); // onBlur, // onFocus it('should render and fire onFocus and onBlur events', async () => { const onFocus = jest.fn(); const onBlur = jest.fn(); const { getByTestId, user } = renderWithUserEvent( , ); const formTextField = getByTestId('form-text-field'); await user.click(formTextField); expect(onFocus).toHaveBeenCalledTimes(1); fireEvent.blur(formTextField); expect(onBlur).toHaveBeenCalledTimes(1); }); // onChange it('should render and fire onChange event', async () => { const onChange = jest.fn(); const { user, getByRole } = renderWithUserEvent( , ); await user.type(getByRole('textbox'), 'test'); expect(onChange).toHaveBeenCalledTimes(4); }); // placeholder it('should render with placeholder', () => { const { getByTestId } = render( , ); expect(getByTestId('form-text-field-auto-complete')).toHaveAttribute( 'placeholder', 'test placeholder', ); }); // readOnly it('should render with readOnly attr when readOnly is true', async () => { const { getByRole, user } = renderWithUserEvent( , ); await user.type(getByRole('textbox'), 'test'); expect(getByRole('textbox')).toHaveValue('test value'); expect(getByRole('textbox')).toHaveAttribute('readonly', ''); }); // required it('should render with required asterisk after Label', () => { const { getByTestId } = render( , ); expect(getByTestId('label-test-id')).toHaveTextContent('test label*'); }); // size = SIZES.MD it('should render with different size classes', () => { const { getByTestId } = render( <> , ); expect(getByTestId('sm')).toHaveClass('mm-text-field-base--size-sm'); expect(getByTestId('md')).toHaveClass('mm-text-field-base--size-md'); expect(getByTestId('lg')).toHaveClass('mm-text-field-base--size-lg'); }); // textFieldProps it('should render with textFieldProps', () => { const { getByTestId } = render( , ); expect(getByTestId('test-text-field')).toBeDefined(); }); // truncate 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-base--truncate'); expect(getByTestId('no-truncate')).not.toHaveClass( 'mm-text-field-base--truncate', ); }); // showClearButton it('should render showClearButton button when showClearButton is true and value exists', async () => { // As showClearButton is intended to be used with a controlled input we need to use renderControlledInput const { user, getByRole } = renderControlledInput(FormTextField, { showClearButton: true, }); await user.type(getByRole('textbox'), 'test value'); expect(getByRole('textbox')).toHaveValue('test value'); expect(getByRole('button', { name: /Clear/u })).toBeDefined(); }); // clearButtonOnClick it('should fire onClick event when passed to clearButtonOnClick when clear button is clicked', async () => { // As showClearButton is intended to be used with a controlled input we need to use renderControlledInput const fn = jest.fn(); const { user, getByRole } = renderControlledInput(FormTextField, { showClearButton: true, clearButtonOnClick: fn, }); await user.type(getByRole('textbox'), 'test value'); await user.click(getByRole('button', { name: /Clear/u })); expect(fn).toHaveBeenCalledTimes(1); }); // clearButtonProps, it('should fire onClick event when passed to clearButtonProps.onClick prop', async () => { // As showClearButton is intended to be used with a controlled input we need to use renderControlledInput const fn = jest.fn(); const { user, getByRole } = renderControlledInput(FormTextField, { showClearButton: true, clearButtonProps: { onClick: fn }, }); await user.type(getByRole('textbox'), 'test value'); await user.click(getByRole('button', { name: /Clear/u })); expect(fn).toHaveBeenCalledTimes(1); }); // type, it('should render with different types', () => { const { getByTestId } = render( <> , ); expect(getByTestId('form-text-field-text')).toHaveAttribute('type', 'text'); expect(getByTestId('form-text-field-number')).toHaveAttribute( 'type', 'number', ); expect(getByTestId('form-text-field-password')).toHaveAttribute( 'type', 'password', ); }); });