title: How to test a React component having async functions with jest & enzyme
body: <p>I have a component:</p>
  
  <p><strong>RandomGif.js</strong></p>
  
  <pre><code>import React, { Component } from "react";
  import Gif from "./Gif";
  import Loader from "./library/Loader";
  import { fetchRandom } from "../resources/api";
  
  class RandomGif extends Component {
    constructor(props) {
      super(props);
  
      this.handleClick = this.handleClick.bind(this);
    }
  
    state = {
      loading: false,
      gif: null
    };
  
    componentDidMount() {
      this.handleClick();
    }
  
    async handleClick() {
      let gifContent = null;
  
      try {
        this.setState({
          loading: true
        });
  
        const result = await fetchRandom();
  
        if (!!result &amp;&amp; result.data) {
          gifContent = {
            id: result.data.id,
            imageUrl: result.data.images.downsized_large.url,
            staticImageUrl: result.data.images.downsized_still.url,
            title: result.data.title
          };
        }
      } catch (e) {
        console.error(e);
      } finally {
        this.setState({
          loading: false,
          gif: gifContent
        });
      }
    }
  
    render() {
      const { gif, loading } = this.state;
  
      const showResults = gif &amp;&amp; !loading;
  
      return (
        &lt;div className="random"&gt;
          {!showResults &amp;&amp; &lt;Loader /&gt;}
  
          &lt;button className="btn" onClick={this.handleClick}&gt;
            RANDOMISE
          &lt;/button&gt;
  
          {showResults &amp;&amp; &lt;Gif data={gif} /&gt;}
        &lt;/div&gt;
      );
    }
  }
  
  export default RandomGif;
  </code></pre>
  
  <p>If I call methods directly from the instance of this component, I can successfully test that the state is being updated. However, If I simulate a button click, nothing gets updated and the test fails. I've tried <code>setImmediate</code> and <code>setTimeout</code> tricks but those are not working.</p>
  
  <p>So far I've not able to write a test case for:</p>
  
  <ul>
  <li>Simulating button click.</li>
  <li>Simulating lifecycle method.</li>
  </ul>
  
  <p>This is what I've come up with so far.</p>
  
  <p><strong>RandomGif.spec.js</strong></p>
  
  <pre><code>import React from "react";
  import { shallow, mount } from "enzyme";
  import RandomGif from "./RandomGif";
  
  describe("Generate Random Gif", () =&gt; {
    it("should render correctly.", () =&gt; {
      const wrapper = shallow(&lt;RandomGif /&gt;);
  
      expect(wrapper).toMatchSnapshot();
    });
  
    it("should load a random GIF on calling handleSearch fn.", async () =&gt; {
      const wrapper = mount(&lt;RandomGif /&gt;);
      const instance = wrapper.instance();
  
      expect(wrapper.state("gif")).toBe(null);
  
      await instance.handleClick();
  
      expect(wrapper.state("gif")).not.toBe(null);
    });
  
    it("THIS TEST FAILS!!!", () =&gt; {
      const wrapper = mount(&lt;RandomGif /&gt;);
  
      expect(wrapper.state("gif")).toBe(null);
  
      wrapper.find('button').simulate('click');
      wrapper.update()
  
      expect(wrapper.state("gif")).not.toBe(null);
    });
  });
  </code></pre>
  
  <p><strong>api.py</strong></p>
  
  <pre><code>export const fetchRandom = async () =&gt; {
    const url = `some_url`;
  
    try {
      const response = await fetch(url);
  
      return await response.json();
    } catch (e) {
      console.error(e);
    }
  
    return null;
  };
  </code></pre>
  
  <p>Please help me figure out the missing pieces of a puzzle called 'frontend testing'.</p>