Guillermo kuster
Guillermo kuster

Reputation: 175

Formik form no validated using Yup on test environment with jest

I'm trying to test if validation is raised when a required field is empty. In my example, I have an email input, which I set to empty, and when I simulate submit action, the onSubmit function is executed when in reality it shouldn't. I'm using validationSchema property using Yup to validate my form. I've added console.log() inside my submit function which is displayed in debug mode (and it shouldn't).

This is working in dev environment (validations raised, onSubmit function no executed) but for some reason, it doesn't work in test env.

It's worth mentioning that I'm full mounting the component to test it using Enzyme.

Thanks in advance.

I've tried with .update to check if at least the view is updated after simulating the action, but it still invokes the submit function.

Here's my code:

form.js

  render() {
    const { intl } = this.props;

    return (
      <div className="signupForm">
        <Formik
          initialValues={{ email: '', password: '', passwordConfirmation: '' }}
          onSubmit={this.submitForm}
          validationSchema={SignUpSchema}
          render={ formProps => (
            <Form>
              <p className="signupForm__message">{formProps.errors.general}</p>
              <FormControl margin="normal" fullWidth>
                <Field
                  type="text"
                  name="email"
                  component={TextField}
                  className='signupForm__input'
                  label={intl.formatMessage(messages.email)}
                />
              </FormControl>

              <FormControl margin="normal" fullWidth>
                <Field
                  type="password"
                  name="password"
                  component={TextField}
                  className='signupForm__input'
                  label={intl.formatMessage(messages.password)}
                  fullWidth
                />
              </FormControl>

              <FormControl margin="normal" fullWidth>
                <Field
                  type="password"
                  name="passwordConfirmation"
                  component={TextField}
                  className='signupForm__input'
                  label={intl.formatMessage(messages.passConfirmation)}
                  fullWidth
                />
              </FormControl>

              <Button
                type="submit"
                fullWidth
                variant="contained"
                className='signupForm__button'
                disabled={formProps.isSubmitting}
              >
                <FormattedMessage id="login.form.submit" />
              </Button>

              {formProps.isSubmitting && <Loading />}
            </Form>
           )
         }
        />
      </div>
    );
  }

test.js


  describe('submit with blank password', () => {
    beforeEach(() => {
      subject = mount(withStore(<SignUpPage />, store));
      // load invalid data to the form
      email.simulate('change', { target: { name: 'email', value: '[email protected]' } });
      password.simulate('change', { target: { name: 'password', value: '' } });
      passwordConfirmation.simulate('change', { target: { name: 'passwordConfirmation', value: 'password' } });
      form.simulate('submit');
    });

    it('should display an error in the password field', () => {
      subject.update();
      const passwordInput = subject.find('TextField').at(1);
      expect(passwordInput.props().error).toBeTruthy();
    });
  });

Upvotes: 1

Views: 2621

Answers (1)

Deeptha AS
Deeptha AS

Reputation: 47

Though Formik's handleSubmit is a sync function, validation with yup functions are called asynchronously.

The following worked for me.

 test("Formik validation", async () => {
    const tree = mount(<YourForm />);
    // Submit the form and wait for everything to resolve.
    tree.simulate('submit', {
       // Formik calls e.preventDefault() internally
       preventDefault: () => { }
    });
    await new Promise(resolve => setImmediate(resolve));
    tree.update();
    expect(yourPasswordInput.props().error).toBeTruthy();
});

Upvotes: 1

Related Questions