title: How to wait until React component completely finished updating in Jest and/or Enzyme?
body: <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>