Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

react testing library with formik & yup validation not erroring as expected #224

Closed
gabriel403 opened this issue Nov 23, 2018 · 6 comments
Closed
Labels
help wanted Extra attention is needed needs investigation question Further information is requested

Comments

@gabriel403
Copy link

  • react-testing-library version: 5.2.3
  • react version: 16.7.0-alpha.2
  • node version: unk
  • npm (or yarn) version: unk

Relevant code or config:

https://codesandbox.io/s/lll3rl5q0q

What you did:

Attempted to create a test for a basic form with a disabled submit button and yup for validation

What happened:

Disabled submit button remains disabled in the ui until all fields are valid, but submit button becomes enabled after a single field becomes valid when tests are run

Reproduction:

https://codesandbox.io/s/lll3rl5q0q

Problem description:

As seen in the debug output of formik in the web after a single change has been made compared to the debug output from the test; the state of the validation seems very different.
codesandbox can be a little iffy with this so suggest it might be better running localy when examining.

@kentcdodds kentcdodds added help wanted Extra attention is needed question Further information is requested needs investigation labels Nov 23, 2018
@weyert
Copy link
Contributor

weyert commented Nov 26, 2018

If I remember correctly. The problem here is that you forgot that the Yup validation schema in Formik is an asynchronous call. To solve this problem, I wrapped it around a wait-statement like this:

        fireEvent.click(getByText('Post donation'))
        await wait(() => {
            expect(queryByText('You need to give the order a title')).not.toBeNull()
            expect(queryByText('You need to select a collection date')).not.toBeNull()
            expect(queryByText('You need to select a collection time')).not.toBeNull()
       })

@alexkrolick
Copy link
Collaborator

Thanks for the investigation @weyert

@gabriel403
Copy link
Author

Awesome, I've got this all working now, thanks @weyert and @kentcdodds

it('Form with valid entry', async () => {
  ...
  const givenNameInput = getByPlaceholderText('Name');
  fireEvent.change(givenNameInput, { target: { name: 'givenName', value: 'Foo Bar' } });
  expect(givenNameInput.value).toBe('Foo Bar');
  await wait(() => {
    expect(submitButton).toBeDisabled();
  });
...
});

@kylemh
Copy link

kylemh commented Apr 19, 2019

Out of curiosity.

How awful is it to simply do

describe('Input', () => {
it('displays an error message when a required field is touched', async () => {
    const validate = () => ({ test: 'Required' });

    const { container, getByText, getByLabelText } = render(
      <Formik validate={validate}>
        <form>
          <Field id="test" name="test" label={requiredProps.label} component={Input} />,
        </form>
      </Formik>
    );

    // blur past input
    const input = getByLabelText(requiredProps.label);
    fireEvent.blur(input);

    // Formik validations are async
    await wait();

    // Ensure error message shows
    expect(getByText('Required')).not.toBeNull();
    expect(container.querySelector('.ncss-error-msg')).not.toBeNull();
  });
});

namely, simply doing: await wait(); (without waiting for something specific/using a callback)

@kentcdodds
Copy link
Member

That's not a big deal honestly, but you could improve things a bit:

describe('Input', () => {
  it('displays an error message when a required field is touched', async () => {
    const validate = () => ({ test: 'Required' });

    const { container, getByText, getByLabelText } = render(
      <Formik validate={validate}>
        <form>
          <Field id="test" name="test" label={requiredProps.label} component={Input} />,
        </form>
      </Formik>
    );

    // blur past input
    const input = getByLabelText(requiredProps.label);
    fireEvent.blur(input);

    // Ensure error message shows
    expect(await findByText(/required/i)).not.toBeNull();
    expect(container.querySelector('.ncss-error-msg')).not.toBeNull();
  });
});

@dep
Copy link

dep commented Dec 9, 2020

I receive a typescript error with this:

await wait(() => {
    expect(wrapper.find('TagSelect').prop('itemId')).to.eq(1);
});

It reads

Argument of type '() => void' is not assignable to parameter of type 'number'

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
help wanted Extra attention is needed needs investigation question Further information is requested
Projects
None yet
Development

No branches or pull requests

6 participants