react-testing-library version: 5.2.3react version: 16.7.0-alpha.2node version: unknpm (or yarn) version: unkhttps://codesandbox.io/s/lll3rl5q0q
Attempted to create a test for a basic form with a disabled submit button and yup for validation
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
https://codesandbox.io/s/lll3rl5q0q
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.
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()
})
Thanks for the investigation @weyert
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();
});
...
});
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)
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();
});
});
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'
Most helpful comment
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: