user2490003
user2490003

Reputation: 11890

How do I "wait" until a component has updated (re-rendered) with Enzyme and Jest?

I have a parent component that does the following:

  1. Generates a form with various input fields
  2. When the submit button is clicked, a POST request with the <form> data is made to the server using axios
  3. If an Error response is returned, an error message is rendered inside a <span> element on the form

I'm writing the following test for this scenario

import axios from 'axios';
import { expect } from 'chai';
import { mount } from 'enzyme';

jest.mock('axios');

it('displays an error when the submit fails', async () => {
  const wrapper = mount(<MyComponent />);

  // Fill in form input fields with text (not shown)
  // ....
  // ....

  // Mock the axios `POST` call to return an error
  const errorResponse = { response: { data: { errors: [{ title: 'Some error' }] } } }
  axios.post.mockImplementationOnce(() => Promise.reject(errorResponse));

  // Click Submit and wait on the axios Promise to complete
  const submit = wrapper.find('.my-component__submit-btn').first();
  await submit.simulate('click');

  // Check if error was rendered on the form
  wrapper.update();
  const error = wrapper.find('.my-component__submit-error').first();
  expect(error).to.have.text('Some error'); // This fails!
});

The last expect() fails - no error is set but I expect one to exist.

However if I add an artificial delay via setTimeout, it passes. So clearly it's an issue where the React component tree does not update before the expect() checks it.

Is there a clean way to "wait" on the React tree to re-render without using setTimeout?

I thought wrapper.update() would do this, but it doesn't seem to.

Thanks!

Upvotes: 3

Views: 5648

Answers (1)

Dmitriy
Dmitriy

Reputation: 551

There is a way to wait for all promises to resolve. Define:

const waitForPromises = () => new Promise(setImmediate);

Then, after the component has rendered, wait:

await waitForPromises()

This, though working in most cases, will still not work if the component is internally updating its state, without triggering these state updates from its properties.

I believe when the latter is the case, this is just an untestable pattern, and requires change in the application design approach, rather than the testing methods.

Upvotes: 1

Related Questions