import React from 'react' import { fireEvent, render, waitFor, act } from '@toptal/picasso-test-utils' import type { OmitInternalProps } from '@toptal/picasso-shared' import { Button } from '@toptal/picasso-button' import type { Props } from './Form' import { FormCompound as Form } from '../FormCompound' import { scrollTo } from '../utils/scroll-to' jest.mock('../utils', () => { const actualUtils = jest.requireActual('../utils') return { ...actualUtils, createScrollToErrorDecorator: jest.requireActual( '../utils/scroll-to-error-decorator' ).default, } }) jest.mock('../utils/scroll-to', () => ({ scrollTo: jest.fn(), })) const renderForm = ( props: OmitInternalProps & { mandatory?: boolean showValidState?: boolean } ) => { const { onSubmit, disableScrollOnError, mandatory, showValidState, validateOnBlur, } = props return render(
) } interface FormData { skills: { value: string; text: string }[] } const skillOptions = [ { value: '0', text: 'HTML' }, { value: '1', text: 'CSS' }, { value: '2', text: 'Javascript' }, ] const initialValues: FormData = { skills: [skillOptions[0]], } const renderTagSelectorWithInitialValue = ( onSubmit: (values: FormData) => void ) => { return render(
onSubmit(values)} initialValues={initialValues}> ) } const scrollToMock = scrollTo as jest.Mock describe('Form', () => { beforeEach(() => { scrollToMock.mockReset() }) it('renders', async () => { const { container, getByText } = renderForm({ onSubmit: () => {}, mandatory: false, }) await act(() => { fireEvent.click(getByText('Submit')) }) await waitFor(() => { expect(scrollToMock).toHaveBeenCalledTimes(0) expect(container).toMatchSnapshot() }) }) it('renders with an error', async () => { const { container, getByText } = renderForm({ onSubmit: () => Promise.resolve({ test: 'Some error' }), mandatory: true, }) await act(() => { fireEvent.click(getByText('Submit')) }) await waitFor(() => { expect(scrollToMock).toHaveBeenCalledTimes(1) expect(container).toMatchSnapshot() }) }) it('when `disableScrollOnError` is specified', async () => { const { getByText } = renderForm({ onSubmit: () => ({ test: 'Some error' }), disableScrollOnError: true, mandatory: true, }) await act(() => { fireEvent.click(getByText('Submit')) }) await waitFor(() => { expect(scrollToMock).not.toHaveBeenCalled() }) }) describe('when validateOnBlur is enabled', () => { it('validates only on blur', async () => { const { getByPlaceholderText, getByText, queryByText } = renderForm({ onSubmit: () => ({ test: 'Some error' }), disableScrollOnError: true, mandatory: true, validateOnBlur: true, }) const input = getByPlaceholderText('test input') fireEvent.blur(input) expect(getByText('Please complete this field.')).toBeInTheDocument() fireEvent.change(input, { target: { value: 'value' } }) expect(getByText('Please complete this field.')).toBeInTheDocument() fireEvent.blur(input) expect(queryByText('Please complete this field.')).not.toBeInTheDocument() }) describe('when showValidState is enabled', () => { it('shows validation success when form submitted on Enter', async () => { const { getByPlaceholderText, getByTestId } = renderForm({ onSubmit: () => {}, disableScrollOnError: false, mandatory: true, showValidState: true, validateOnBlur: true, }) const input = getByPlaceholderText('test input') await act(async () => { fireEvent.focus(input) fireEvent.change(input, { target: { value: 'value' } }) fireEvent.submit(input) }) await waitFor(() => { expect(getByTestId('valid-icon')).toBeInTheDocument() }) }) }) }) describe('when initial values provided to form', () => { it('fills TagSelector field with provided values', async () => { const onSubmit = jest.fn() const { getByText } = renderTagSelectorWithInitialValue(onSubmit) await act(() => { fireEvent.click(getByText('Submit')) }) expect(onSubmit).toHaveBeenCalledWith(initialValues) }) }) })