import React from 'react'; import {mount} from 'enzyme'; import {Provider} from 'react-redux'; import {createStore, applyMiddleware, combineReducers} from 'redux'; import ReduxThunkTester from 'redux-thunk-tester'; import FieldLevelValidation from './field-level-validation'; import {reducer} from '../../index'; interface IValues { firstName?: string; lastName?: string; age?: string; number?: string; } const renderComponent = (innerOnSubmit?) => { const reduxThunkTester = new ReduxThunkTester(); const store = createStore( combineReducers({reduxForm: reducer}), applyMiddleware(reduxThunkTester.createReduxThunkHistoryMiddleware()), ); const component = mount( , ); return { reduxThunkTester, getFormState: () => store.getState().reduxForm.simple as IReduxFormState, component, }; }; describe('', () => { test('Render field-level-validation form (inputs).', () => { const {component} = renderComponent(); expect(component.find('input')).toMatchSnapshot(); }); test('Register form and fields: store.', () => { const {getFormState} = renderComponent(); expect(getFormState()).toMatchSnapshot(); }); test('Focus field: actions history.', () => { const { reduxThunkTester: {getActionHistory, clearActionHistory}, component, } = renderComponent(); clearActionHistory(); component.find('input').at(0).simulate('focus'); expect(getActionHistory()).toMatchSnapshot(); }); test('Focus field: store', () => { const {getFormState, component} = renderComponent(); component.find('input').at(0).simulate('focus'); expect(getFormState()).toMatchSnapshot(); }); test('Change field (validate and warning): actions history (input 0).', () => { const { reduxThunkTester: {clearActionHistory, getActionHistoryStringify}, component, } = renderComponent(); component.find('input').at(0).simulate('focus'); clearActionHistory(); component.find('input').at(0).simulate('change', {target: {value: 't'}}); component.find('input').at(0).simulate('change', {target: {value: ''}}); expect(getActionHistoryStringify()).toMatchSnapshot(); }); test('Change field (validate and warning): actions history (input 1).', () => { const { reduxThunkTester: {clearActionHistory, getActionHistoryStringify}, component, } = renderComponent(); component.find('input').at(0).simulate('focus'); component.find('input').at(0).simulate('change', {target: {value: 't'}}); component.find('input').at(0).simulate('change', {target: {value: ''}}); clearActionHistory(); component.find('input').at(1).simulate('change', {target: {value: ''}}); component.find('input').at(1).simulate('change', {target: {value: 't'}}); component.find('input').at(1).simulate('change', {target: {value: 'te'}}); component.find('input').at(1).simulate('change', {target: {value: 'tes'}}); component.find('input').at(1).simulate('change', {target: {value: 'test'}}); component.find('input').at(1).simulate('change', {target: {value: 'tes'}}); component.find('input').at(1).simulate('change', {target: {value: 'te'}}); component.find('input').at(1).simulate('change', {target: {value: 't'}}); component.find('input').at(1).simulate('change', {target: {value: ''}}); expect(getActionHistoryStringify()).toMatchSnapshot(); }); test('Change field (validate and warning): actions history (input 2).', () => { const { reduxThunkTester: {clearActionHistory, getActionHistoryStringify}, component, } = renderComponent(); component.find('input').at(0).simulate('focus'); component.find('input').at(0).simulate('change', {target: {value: 't'}}); component.find('input').at(0).simulate('change', {target: {value: ''}}); clearActionHistory(); component.find('input').at(1).simulate('change', {target: {value: ''}}); component.find('input').at(1).simulate('change', {target: {value: 't'}}); component.find('input').at(1).simulate('change', {target: {value: 'te'}}); component.find('input').at(1).simulate('change', {target: {value: 'tes'}}); component.find('input').at(1).simulate('change', {target: {value: 'test'}}); component.find('input').at(1).simulate('change', {target: {value: 'tes'}}); component.find('input').at(1).simulate('change', {target: {value: 'te'}}); component.find('input').at(1).simulate('change', {target: {value: 't'}}); component.find('input').at(1).simulate('change', {target: {value: ''}}); clearActionHistory(); component.find('input').at(2).simulate('change', {target: {value: ''}}); component.find('input').at(2).simulate('change', {target: {value: '1'}}); component.find('input').at(2).simulate('change', {target: {value: '18'}}); component.find('input').at(2).simulate('change', {target: {value: '1'}}); component.find('input').at(2).simulate('change', {target: {value: '19'}}); component.find('input').at(2).simulate('change', {target: {value: '1'}}); component.find('input').at(2).simulate('change', {target: {value: ''}}); component.find('input').at(2).simulate('change', {target: {value: '0'}}); component.find('input').at(2).simulate('change', {target: {value: ''}}); expect(getActionHistoryStringify()).toMatchSnapshot(); }); test('Change field (validate and warning): actions history (input 3).', () => { const { reduxThunkTester: {clearActionHistory, getActionHistoryStringify}, component, } = renderComponent(); component.find('input').at(0).simulate('focus'); component.find('input').at(0).simulate('change', {target: {value: 't'}}); component.find('input').at(0).simulate('change', {target: {value: ''}}); component.find('input').at(1).simulate('change', {target: {value: ''}}); component.find('input').at(1).simulate('change', {target: {value: 't'}}); component.find('input').at(1).simulate('change', {target: {value: 'te'}}); component.find('input').at(1).simulate('change', {target: {value: 'tes'}}); component.find('input').at(1).simulate('change', {target: {value: 'test'}}); component.find('input').at(1).simulate('change', {target: {value: 'tes'}}); component.find('input').at(1).simulate('change', {target: {value: 'te'}}); component.find('input').at(1).simulate('change', {target: {value: 't'}}); component.find('input').at(1).simulate('change', {target: {value: ''}}); component.find('input').at(2).simulate('change', {target: {value: ''}}); component.find('input').at(2).simulate('change', {target: {value: '1'}}); component.find('input').at(2).simulate('change', {target: {value: '18'}}); component.find('input').at(2).simulate('change', {target: {value: '1'}}); component.find('input').at(2).simulate('change', {target: {value: '19'}}); component.find('input').at(2).simulate('change', {target: {value: '1'}}); component.find('input').at(2).simulate('change', {target: {value: ''}}); component.find('input').at(2).simulate('change', {target: {value: '0'}}); component.find('input').at(2).simulate('change', {target: {value: ''}}); clearActionHistory(); component.find('input').at(3).simulate('change', {target: {value: ''}}); component.find('input').at(3).simulate('change', {target: {value: '1'}}); component.find('input').at(3).simulate('change', {target: {value: ''}}); component.find('input').at(3).simulate('change', {target: {value: '5'}}); component.find('input').at(3).simulate('change', {target: {value: '50'}}); component.find('input').at(3).simulate('change', {target: {value: '500'}}); component.find('input').at(3).simulate('change', {target: {value: '50'}}); component.find('input').at(3).simulate('change', {target: {value: '5'}}); component.find('input').at(3).simulate('change', {target: {value: ''}}); component.find('input').at(3).simulate('change', {target: {value: '-1'}}); component.find('input').at(3).simulate('change', {target: {value: '-11'}}); component.find('input').at(3).simulate('change', {target: {value: '-11'}}); expect(getActionHistoryStringify()).toMatchSnapshot(); }); test('Changed field (validate and warning firstName: validate={validateIsRequired}): store', () => { const {component, getFormState} = renderComponent(); component.find('input').at(0).simulate('focus'); component.find('input').at(0).simulate('change', {target: {value: 't'}}); component.find('input').at(0).simulate('change', {target: {value: ''}}); expect(getFormState().form.errorsMap).toEqual({firstName: 'Field required.'}); expect(getFormState().form.warningsMap).toEqual({}); expect(getFormState().form.hasErrors).toEqual(true); expect(getFormState().form.hasWarnings).toEqual(false); expect(getFormState()).toMatchSnapshot(); component.find('input').at(0).simulate('change', {target: {value: 't'}}); expect(getFormState().form.errorsMap).toEqual({}); expect(getFormState().form.warningsMap).toEqual({}); expect(getFormState().form.hasErrors).toEqual(false); expect(getFormState().form.hasWarnings).toEqual(false); }); test('Changed field (validate and warning' + 'lastName: validate={[validateIsRequired, validateMinLength(2)]}): store', () => { const {component, getFormState} = renderComponent(); component.find('input').at(1).simulate('focus'); component.find('input').at(1).simulate('change', {target: {value: 't'}}); component.find('input').at(1).simulate('change', {target: {value: ''}}); expect(getFormState()).toMatchSnapshot(); expect(getFormState().form.errorsMap).toEqual({lastName: 'Field required.'}); expect(getFormState().form.warningsMap).toEqual({}); expect(getFormState().form.hasErrors).toEqual(true); expect(getFormState().form.hasWarnings).toEqual(false); component.find('input').at(1).simulate('change', {target: {value: 't'}}); expect(getFormState().form.errorsMap).toEqual( {lastName: 'Must be 2 characters or more.'}, ); expect(getFormState().form.warningsMap).toEqual({}); expect(getFormState().form.hasErrors).toEqual(true); expect(getFormState().form.hasWarnings).toEqual(false); component.find('input').at(1).simulate('change', {target: {value: 'te'}}); expect(getFormState().form.errorsMap).toEqual({}); expect(getFormState().form.warningsMap).toEqual({}); // @ts-ignore expect(getFormState().meta.lastName.error).toEqual(''); expect(getFormState().form.hasErrors).toEqual(false); expect(getFormState().form.hasWarnings).toEqual(false); }); test('Changed field (validate and warning ' + 'validate={validateIsRequired} warn={warnTooYang}): store', () => { const {component, getFormState} = renderComponent(); component.find('input').at(2).simulate('focus'); component.find('input').at(2).simulate('change', {target: {value: 't'}}); expect(getFormState().form.errorsMap).toEqual({}); expect(getFormState().form.warningsMap).toEqual({}); component.find('input').at(2).simulate('change', {target: {value: ''}}); expect(getFormState().form.errorsMap).toEqual({age: 'Field required.'}); expect(getFormState().form.warningsMap).toEqual({}); expect(getFormState().form.hasErrors).toEqual(true); expect(getFormState().form.hasWarnings).toEqual(false); component.find('input').at(2).simulate('change', {target: {value: '1'}}); expect(getFormState().form.errorsMap).toEqual({}); expect(getFormState().form.warningsMap).toEqual({age: 'Too yang.'}); // @ts-ignore expect(getFormState().meta.age.warning).toEqual('Too yang.'); expect(getFormState().form.hasErrors).toEqual(false); expect(getFormState().form.hasWarnings).toEqual(true); component.find('input').at(2).simulate('change', {target: {value: '18'}}); expect(getFormState().form.errorsMap).toEqual({}); expect(getFormState().form.warningsMap).toEqual({}); // @ts-ignore expect(getFormState().meta.age.warning).toEqual(''); expect(getFormState().form.hasErrors).toEqual(false); expect(getFormState().form.hasWarnings).toEqual(false); expect(getFormState()).toMatchSnapshot(); }); test('Changed field (validate and warning ' + 'warn={[warnTooSmall, warnTooLarge]}): store', () => { const {component, getFormState} = renderComponent(); component.find('input').at(3).simulate('focus'); component.find('input').at(3).simulate('change', {target: {value: 't'}}); expect(getFormState().form.errorsMap).toEqual({}); expect(getFormState().form.warningsMap).toEqual({}); expect(getFormState().form.hasErrors).toEqual(false); expect(getFormState().form.hasWarnings).toEqual(false); component.find('input').at(3).simulate('change', {target: {value: ''}}); expect(getFormState().form.errorsMap).toEqual({}); expect(getFormState().form.warningsMap).toEqual({}); expect(getFormState().form.hasErrors).toEqual(false); expect(getFormState().form.hasWarnings).toEqual(false); component.find('input').at(3).simulate('change', {target: {value: '0'}}); expect(getFormState().form.errorsMap).toEqual({}); expect(getFormState().form.warningsMap).toEqual({number: 'Too small.'}); // @ts-ignore expect(getFormState().meta.number.warning).toEqual('Too small.'); expect(getFormState().form.hasErrors).toEqual(false); expect(getFormState().form.hasWarnings).toEqual(true); component.find('input').at(3).simulate('change', {target: {value: '1'}}); expect(getFormState().form.errorsMap).toEqual({}); expect(getFormState().form.warningsMap).toEqual({}); // @ts-ignore expect(getFormState().meta.number.warning).toEqual(''); expect(getFormState().form.hasErrors).toEqual(false); expect(getFormState().form.hasWarnings).toEqual(false); component.find('input').at(3).simulate('change', {target: {value: '10'}}); expect(getFormState().form.errorsMap).toEqual({}); expect(getFormState().form.warningsMap).toEqual({}); // @ts-ignore expect(getFormState().meta.number.warning).toEqual(''); expect(getFormState().form.hasErrors).toEqual(false); expect(getFormState().form.hasWarnings).toEqual(false); component.find('input').at(3).simulate('change', {target: {value: '101'}}); expect(getFormState().form.errorsMap).toEqual({}); expect(getFormState().form.warningsMap).toEqual({number: 'Too large.'}); // @ts-ignore expect(getFormState().meta.number.warning).toEqual('Too large.'); expect(getFormState().form.hasErrors).toEqual(false); expect(getFormState().form.hasWarnings).toEqual(true); expect(getFormState()).toMatchSnapshot(); }); test('handleSubmit(onSubmit) inside form-component (valid)', () => { const innerOnSubmit = jest.fn(); const {component} = renderComponent(innerOnSubmit); component.find('input').at(0).simulate('focus'); component.find('input').at(0).simulate('change', {target: {value: 't'}}); component.find('input').at(0).simulate('change', {target: {value: 'te'}}); component.find('input').at(0).simulate('change', {target: {value: 'tes'}}); component.find('input').at(0).simulate('change', {target: {value: 'test'}}); component.find('input').at(0).simulate('blur'); component.find('input').at(1).simulate('focus'); component.find('input').at(1).simulate('change', {target: {value: 't'}}); component.find('input').at(1).simulate('change', {target: {value: 'te'}}); component.find('input').at(1).simulate('change', {target: {value: 'tes'}}); component.find('input').at(1).simulate('change', {target: {value: 'test'}}); component.find('input').at(1).simulate('blur'); component.find('input').at(2).simulate('focus'); component.find('input').at(2).simulate('change', {target: {value: '1'}}); component.find('input').at(2).simulate('change', {target: {value: '18'}}); component.find('input').at(2).simulate('blur'); component.find('input').at(3).simulate('focus'); component.find('input').at(3).simulate('change', {target: {value: '5'}}); component.find('input').at(3).simulate('change', {target: {value: '50'}}); component.find('input').at(3).simulate('blur'); expect(innerOnSubmit.mock.calls).toEqual([]); component.find('form').at(0).simulate('submit'); expect(innerOnSubmit.mock.calls.length).toEqual(1); const values = { firstName: 'test', lastName: 'test', age: '18', number: '50', }; expect(innerOnSubmit.mock.calls[0][0].values).toEqual(values); expect(innerOnSubmit.mock.calls[0][0].state).toMatchSnapshot(); }); test('handleSubmit(onSubmit) inside form-component (not valid): firstArg', () => { const innerOnSubmit = jest.fn(); const {component} = renderComponent(innerOnSubmit); component.find('input').at(0).simulate('focus'); component.find('input').at(0).simulate('change', {target: {value: 't'}}); component.find('input').at(0).simulate('change', {target: {value: ''}}); component.find('input').at(0).simulate('blur'); component.find('input').at(1).simulate('focus'); component.find('input').at(1).simulate('change', {target: {value: 't'}}); component.find('input').at(1).simulate('change', {target: {value: 't'}}); component.find('input').at(1).simulate('blur'); component.find('input').at(2).simulate('focus'); component.find('input').at(2).simulate('change', {target: {value: '1'}}); component.find('input').at(2).simulate('change', {target: {value: '12'}}); component.find('input').at(2).simulate('blur'); component.find('input').at(3).simulate('focus'); component.find('input').at(3).simulate('change', {target: {value: '1'}}); component.find('input').at(3).simulate('change', {target: {value: '10'}}); component.find('input').at(3).simulate('change', {target: {value: '105'}}); component.find('input').at(3).simulate('blur'); expect(innerOnSubmit.mock.calls).toEqual([]); component.find('form').at(0).simulate('submit'); expect(innerOnSubmit.mock.calls.length).toEqual(1); expect(innerOnSubmit.mock.calls[0][0].values).toMatchSnapshot(); }); test('handleSubmit(onSubmit) inside form-component (not valid): secondArg', () => { const innerOnSubmit = jest.fn(); const {component} = renderComponent(innerOnSubmit); component.find('input').at(0).simulate('focus'); component.find('input').at(0).simulate('change', {target: {value: 't'}}); component.find('input').at(0).simulate('change', {target: {value: ''}}); component.find('input').at(0).simulate('blur'); component.find('input').at(1).simulate('focus'); component.find('input').at(1).simulate('change', {target: {value: 't'}}); component.find('input').at(1).simulate('change', {target: {value: 't'}}); component.find('input').at(1).simulate('blur'); component.find('input').at(2).simulate('focus'); component.find('input').at(2).simulate('change', {target: {value: '1'}}); component.find('input').at(2).simulate('change', {target: {value: '12'}}); component.find('input').at(2).simulate('blur'); component.find('input').at(3).simulate('focus'); component.find('input').at(3).simulate('change', {target: {value: '1'}}); component.find('input').at(3).simulate('change', {target: {value: '10'}}); component.find('input').at(3).simulate('change', {target: {value: '105'}}); component.find('input').at(3).simulate('blur'); expect(innerOnSubmit.mock.calls).toEqual([]); component.find('form').at(0).simulate('submit'); expect(innerOnSubmit.mock.calls.length).toEqual(1); expect(innerOnSubmit.mock.calls[0][0].state).toMatchSnapshot(); }); test('handleSubmit(onSubmit) inside form-component (not valid): thirdArg', () => { const innerOnSubmit = jest.fn(); const {component} = renderComponent(innerOnSubmit); component.find('input').at(0).simulate('focus'); component.find('input').at(0).simulate('change', {target: {value: 't'}}); component.find('input').at(0).simulate('change', {target: {value: ''}}); component.find('input').at(0).simulate('blur'); component.find('input').at(1).simulate('focus'); component.find('input').at(1).simulate('change', {target: {value: 't'}}); component.find('input').at(1).simulate('change', {target: {value: 't'}}); component.find('input').at(1).simulate('blur'); component.find('input').at(2).simulate('focus'); component.find('input').at(2).simulate('change', {target: {value: '1'}}); component.find('input').at(2).simulate('change', {target: {value: '12'}}); component.find('input').at(2).simulate('blur'); component.find('input').at(3).simulate('focus'); component.find('input').at(3).simulate('change', {target: {value: '1'}}); component.find('input').at(3).simulate('change', {target: {value: '10'}}); component.find('input').at(3).simulate('change', {target: {value: '105'}}); component.find('input').at(3).simulate('blur'); expect(innerOnSubmit.mock.calls).toEqual([]); component.find('form').at(0).simulate('submit'); expect(innerOnSubmit.mock.calls.length).toEqual(1); expect(innerOnSubmit.mock.calls[0][0].actions).toMatchSnapshot(); }); test('Submit without touch inputs (not valid): store', () => { const {component, getFormState} = renderComponent(); component.find('form').at(0).simulate('submit'); expect(getFormState()).toMatchSnapshot(); }); });