'Formik doesn't update errors while testing with jest and enzyme
I have a Formik signup form that is validated with yup. When validation schema isn't fulfilled i want to show error component. Everything works in browser, but when i do my tests, even though there should be errors already jest and enzyme behaves like there was no error. Can someone tell me what am I doing wrong? It's strange because when I put console.log(errors.email) in Formik's return function i see that there is 'It does not seem to be a valid email address.' error in my test console. From the other hand when i put erros.email in Formik's return function, in test it looks like it doesn't exist.
// SignUp.tsx
const SignUp: React.FC = () => {
const { register, errorMessage } = React.useContext(AuthContext);
const initialValues = {
email: '',
password: '',
passwordRepeat: '',
};
const hasErrors = (errors: FormikErrors<typeof initialValues>) => {
return Object.keys(errors).length !== 0 || errorMessage;
};
const allFieldsWereTouched = (touched: FormikTouched<typeof initialValues>) => {
return Array.from(Object.values(touched)).filter((wasTouched) => wasTouched).length === Object.keys(initialValues).length;
};
const signUpValidationSchema = Yup.object().shape({
email: Yup.string().email('It does not seem to be a valid email address.'),
password: Yup.string().min(5, 'Password must have at least 5 characters.').max(15, 'Password must not have more than 15 characters.'),
passwordRepeat: Yup.string().oneOf([Yup.ref('password')], 'Both passwords must be equal.'),
});
const submitForm = (values: typeof initialValues) => {
register(values.email, values.password);
};
return (
<AuthWrapper>
<h3 className={classes.authModalTitle} data-test='signup-modal-title'>
Sign Up
</h3>
<Formik initialValues={initialValues} onSubmit={submitForm} validationSchema={signUpValidationSchema}>
{({ errors, touched }) => {
return (
<Form>
<FormikTextInput type='email' name='email' description='E-mail address' as={Input} />
<FormikTextInput type='password' name='password' description='Password' as={Input} />
<FormikTextInput type='password' name='passwordRepeat' description='Password repeat' as={Input} />
{errors.email && <Error message={errors.email || errors.password || errors.passwordRepeat || errorMessage} />}
<Button className={classes.buttonAdditional} type='submit' dataTest='signup-button'>
Open account
</Button>
</Form>
);
}}
</Formik>
<FormInfo question='Already have an account?' answer='Sign in' path='SignIn' />
</AuthWrapper>
);
};
export default SignUp;
// SignUp.test.tsx
const setup = () => {
return mount(
<MemoryRouter>
<AuthContextProvider>
<SignUp />
</AuthContextProvider>
</MemoryRouter>
);
};
describe('<SignUp />', () => {
let wrapper: ReactWrapper;
beforeEach(() => {
wrapper = setup();
});
afterEach(() => {
wrapper.unmount();
});
describe('showing errors', () => {
const simulateTyping = async (name: string, value: string | number) => {
const formField = formikFindByInputName(wrapper, name);
formField.simulate('change', { target: { name, value } });
formField.simulate('blur');
};
const checkErrorExistance = (wrapper: ReactWrapper, condition: boolean) => {
const error = findByTestAttr(wrapper, 'error');
expect(error.exists()).toBe(condition);
};
it('does not show error when email input value is wrong but not all inputs were touched', () => {
simulateTyping('email', 'test');
checkErrorExistance(wrapper, true);
});
});
});
Solution 1:[1]
I had the same issue and had to run validateForm myself, so something like:
<Formik>{({..., validateForm}) =>
<Button onClick={async () => {const newErrors = await validateForm?.()}} />
Then check the newErrors.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 |
