import React from 'react' import { FormState, DebouncedFieldState } from 'formstate-x' import { observer } from 'mobx-react' import { create, act } from 'react-test-renderer' import { Form, FormItem, useFormstateX } from '.' import { PasswordInput, TextInput } from './Input' const defaultDelay = 10 // ms function delay() { return new Promise(resolve => { setTimeout(() => resolve(), defaultDelay) }) } function mockEvent(target?: any) { return { target, preventDefault: () => undefined } } describe('react-icecream-form', () => { it('should work well', async () => { function createState(email = '') { return new FormState({ email: new DebouncedFieldState(email, defaultDelay).withValidator( v => (/.+@.+/.test(v) ? null : 'Invalid email') ), password: new DebouncedFieldState('', defaultDelay).withValidator( v => v.length < 6 && 'Too short' ) }) } let submitted: any const submit = jest.fn(v => { submitted = v }) interface MyFormProps { email?: string } const MyForm = observer(function MyForm({ email }: MyFormProps) { const state = useFormstateX(createState, [email]) return (
) }) const rendered = create() const form = () => rendered.root.findByType('form') const inputs = () => rendered.root.findAllByType('input') const emailInput = () => inputs()[0] const passwordInput = () => inputs()[1] expect(rendered.toJSON()).toMatchSnapshot('initialized') await act(async () => { emailInput().props.onChange(mockEvent({ value: 'foo' })) await delay() }) expect(rendered.toJSON()).toMatchSnapshot('invalid email') await act(async () => { passwordInput().props.onChange(mockEvent({ value: 'bar' })) await delay() }) expect(rendered.toJSON()).toMatchSnapshot('invalid email & password') act(() => { rendered.update() }) expect(rendered.toJSON()).toMatchSnapshot('initialized with email') await act(async () => { form().props.onSubmit(mockEvent()) await delay() }) expect(rendered.toJSON()).toMatchSnapshot('submit with invalid password') expect(submit).not.toHaveBeenCalled() await act(async () => { passwordInput().props.onChange(mockEvent({ value: '123456' })) await delay() }) expect(rendered.toJSON()).toMatchSnapshot('no error') await act(async () => { form().props.onSubmit(mockEvent()) await delay() }) expect(rendered.toJSON()).toMatchSnapshot('submit with no error') expect(submit).toBeCalledTimes(1) expect(submitted).toEqual({ email: 'icecream@form.com', password: '123456' }) }) })