title: Test React component that depends on a Promise with Jest
body: <p>I'm trying to learn a bit more about JS tests.</p>
  
  <p>I've got a basic React component that <code>fetch()</code>'s data when it mounts.</p>
  
  <p>When running the app, the component works as expected and gets the data.</p>
  
  <p>However when testing with Jest, I can see that the call has been made but the promise is always rejected?</p>
  
  <p>I've been following <a href="https://medium.com/@rishabhsrao/mocking-and-testing-fetch-with-jest-c4d670e2e167" rel="nofollow noreferrer">this example</a> to produce the tests below.</p>
  
  <p>Not sure about mocking promises with Jest, any pointers would be a huge help!</p>
  
  <h3>Component</h3>
  
  <p><div class="snippet" data-lang="js" data-hide="false" data-console="true" data-babel="false">
  <div class="snippet-code">
  <pre class="snippet-code-js lang-js prettyprint-override"><code>import React from 'react';
  import './App.scss';
  import * as Utils from './Functions';
  import Header from './components/Header';
  import Loader from './components/Loader';
  import Table from './components/Table';
  
  export default class App extends React.Component {
    constructor(props) {
      super(props);
      /*
      Initialise state:
        # Loading: true
      */
      this.state = {
        loading: true,
      };
    }
  
    /*
      When component mounts, 
      # Call function to get data
      # Set state with promise response
    */
    componentDidMount = () =&gt; {
      /* Function to grab data
        I've created a local express server to get around the cors issue
      */
      Utils.initData('http://localhost:8888/mock/all').then(data =&gt; {
        // Finally set state to reload component with new data
        this.setState({
          loading: false,
          teams: data,
        })
      })
    }  
  
    render() {
      const { loading, teams } = this.state;
      return (
        &lt;div id="app"&gt;
          &lt;Header /&gt;
          &lt;div className="table"&gt;
            {loading &amp;&amp; (&lt;Loader /&gt;)}
            {!loading &amp;&amp; (&lt;Table data={teams} loading={loading} /&gt;)}
          &lt;/div&gt;
        &lt;/div&gt;
      );
    }
  }</code></pre>
  </div>
  </div>
  </p>
  
  <h3>Functions</h3>
  
  <p><div class="snippet" data-lang="js" data-hide="false" data-console="true" data-babel="false">
  <div class="snippet-code">
  <pre class="snippet-code-js lang-js prettyprint-override"><code>export const initData = (dataURL) =&gt; {
    try {
      // Get data using the Fetch API
      return fetch(dataURL).then(
        response =&gt; response.json()
      )
        // Then sanitize the data
        .then(data =&gt; sanitizeData(data));
    } catch (error) {
      console.warn(error);
      return error;
    }
  }
  export const sanitizeData = (data) =&gt; {
    console.log(data)
    // Do loads of stuff with the data
  }</code></pre>
  </div>
  </div>
  </p>
  
  <h3>Test</h3>
  
  <p><div class="snippet" data-lang="js" data-hide="false" data-console="true" data-babel="false">
  <div class="snippet-code">
  <pre class="snippet-code-js lang-js prettyprint-override"><code>import React from 'react';
  import ReactDOM from 'react-dom';
  import { shallow, mount } from 'enzyme';
  import App from './App';
  import Table from './components/Table';
  import Header from './components/Header';
  import * as Utils from './Functions';
  
  import { configure } from 'enzyme';
  import Adapter from 'enzyme-adapter-react-16';
  configure({ adapter: new Adapter() });
  
  describe('App', () =&gt; {
    it('- Renders the header', () =&gt; {
      const div = document.createElement('div');
      ReactDOM.render(&lt;Header /&gt;, div);
      ReactDOM.unmountComponentAtNode(div);
    });
  
    it('- Renders the table', () =&gt; {
      const div = document.createElement('div');
      ReactDOM.render(&lt;Table /&gt;, div);
      ReactDOM.unmountComponentAtNode(div);
    });
  
    it('- Renders the full app', () =&gt; {
      const div = document.createElement('div');
      ReactDOM.render(&lt;App /&gt;, div);
      ReactDOM.unmountComponentAtNode(div);
    });
  });
  
  describe('Gets data', () =&gt; {
    it('fetches data from server when server returns a successful response', () =&gt; {
      const mockSuccessResponse = {};
      const mockJsonPromise = Promise.resolve(mockSuccessResponse);
      const mockFetchPromise = Promise.resolve({
        json: () =&gt; mockJsonPromise,
      });
      jest.spyOn(global, 'fetch').mockImplementation(() =&gt; mockFetchPromise); // 4
      const wrapper = shallow(&lt;App /&gt;);                      
      expect(global.fetch).toHaveBeenCalledTimes(1);
      expect(global.fetch).toHaveBeenCalledWith('http://localhost:8888/mock/all');
    });
  });</code></pre>
  </div>
  </div>
  </p>
  
  <h3>Error messages</h3>
  
  <p>I don't get any error in the app itself but while the test runs I get:</p>
  
  <pre><code>(node:4082) UnhandledPromiseRejectionWarning: TypeError: Cannot read property 'forEach' of undefined
  [1] (node:4082) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 1)
  [1] (node:4082) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
  </code></pre>
  
  <p>The forEach mentioned above is from the <code>sanitizeData()</code> function and is there because the <code>data</code> param is <code>{}</code> when testing...</p>