How to wait until React component completely finished updating in Jest and/or Enzyme? : <p>In my create-react-app, I am trying to test a component that does multiple <code>setState</code>s when mounted.</p>

<pre><code>class MyComponent extends React.Component {

  state = {
    a: undefined,
    b: undefined,
    c: undefined,
  };

  fetchA() {
    // returns a promise
  }

  fetchB() {
    // returns a promise
  }

  fetchC() {
    // returns a promise
  }

  async componentDidMount() {
    const a = await fetchA();
    this.setState({ a });
  }

  async componentDidUpdate(prevProps, prevState) {
    if (prevState.a !== this.state.a) {
      const [b, c] = await Promise.all([
        this.fetchB(a);
        this.fetchC(a);
      ]);
      this.setState({ b, c });
    }
  }

  ...

}
</code></pre>

<p>In my test, I do something like this, trying to let the <code>setState</code> in <code>componentDidUpdate</code> to finish before making assertions.</p>

<pre><code>import { mount } from 'enzyme';

describe('MyComponent', () =&gt; {

  const fakeA = Promise.resolve('a');
  const fakeB = Promise.resolve('b');
  const fakeC = Promise.resolve('c');

  MyComponent.prototype.fetchA = jest.fn(() =&gt; fakeA);
  MyComponent.prototype.fetchB = jest.fn(() =&gt; fakeB);
  MyComponent.prototype.fetchC = jest.fn(() =&gt; fakeC);

  it('sets needed state', async () =&gt; {
    const wrapper = mount(&lt;MyComponent /&gt;);
    await Promise.all([ fakeA, fakeB, fakeC ]);
    expect(wrapper.state()).toEqual({
      a: 'a',
      b: 'b',
      c: 'c',
    });
  });

});
</code></pre>

<p>Here's the interesting part: My test above will fail because the last <code>setState</code> call (in <code>componentDidUpdate</code>) has not finished when the assertion is made. At that time, <code>state.a</code> is set, but <code>state.b</code> and <code>state.c</code> is not set yet.</p>

<p>The only way I could make it work is by wedging <code>await Promise.resolve(null)</code> right before the assertion to give the last <code>setState</code> that extra tick/cycle to complete. This looks too hacky.</p>

<p>Another thing I've tried is wrapping the assertion in <code>setImmediate()</code>, which works fine as long as the assertion passes. If it fails, it will terminate the whole test because of uncaught error.</p>

<p>Has anyone overcome this problem?</p>
