'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