title: Test a React Component function with Jest
body: <h1>Original</h1>
  
  <p>First of all, I am following the <a href="https://github.com/facebook/flux" rel="noreferrer">Flux</a> architecture.</p>
  
  <p>I have an indicator that shows a number of seconds, ex: 30 seconds. Every one second it shows 1 second less, so 29, 28, 27 till 0. When arrives to 0, I clear the interval so it stops repeating. Moreover, I trigger an action. When this action gets dispatched, my store notifies me. So when this happens, I reset the interval to 30s and so on. Component looks like:</p>
  
  <pre><code>var Indicator = React.createClass({
  
    mixins: [SetIntervalMixin],
  
    getInitialState: function(){
      return{
        elapsed: this.props.rate
      };
    },
  
    getDefaultProps: function() {
      return {
        rate: 30
      };
    },
  
    propTypes: {
      rate: React.PropTypes.number.isRequired
    },
  
    componentDidMount: function() {
      MyStore.addChangeListener(this._onChange);
    },
  
    componentWillUnmount: function() {
      MyStore.removeChangeListener(this._onChange);
    },
  
    refresh: function(){
      this.setState({elapsed: this.state.elapsed-1})
  
      if(this.state.elapsed == 0){
        this.clearInterval();
        TriggerAnAction();
      }
    },
  
    render: function() {
      return (
        &lt;p&gt;{this.state.elapsed}s&lt;/p&gt;
      );
    },
  
    /**
     * Event handler for 'change' events coming from MyStore
     */
    _onChange: function() {
      this.setState({elapsed: this.props.rate}
      this.setInterval(this.refresh, 1000);
    }
  
  });
  
  module.exports = Indicator;
  </code></pre>
  
  <p>Component works as expected. Now, I want to test it with Jest. I know I can use renderIntoDocument, then I can setTimeout of 30s and check if my component.state.elapsed is equal to 0 (for example).</p>
  
  <p>But, what I want to test here are different things. I want to test <strong>if refresh function is called</strong> . Moreover, I'd like to test that when my elapsed state is 0, <strong>it triggers my TriggerAnAction()</strong>. Ok, for the first thing I tried to do:</p>
  
  <pre><code>jest.dontMock('../Indicator');
  
  describe('Indicator', function() {
    it('waits 1 second foreach tick', function() {
  
      var React = require('react/addons');
      var Indicator = require('../Indicator.js');
      var TestUtils = React.addons.TestUtils;
  
      var Indicator = TestUtils.renderIntoDocument(
        &lt;Indicator /&gt;
      );
  
      expect(Indicator.refresh).toBeCalled();
  
    });
  });
  </code></pre>
  
  <p>But I receive the following error when writing npm test:</p>
  
  <pre><code>Throws: Error: toBeCalled() should be used on a mock function
  </code></pre>
  
  <p>I saw from ReactTestUtils a <a href="http://facebook.github.io/react/docs/test-utils.html#mockcomponent" rel="noreferrer">mockComponent</a> function but given its explanation, I am not sure if it is what I need.</p>
  
  <p>Ok, in this point, I am stuck. Can anybody give me some light on how to test that two things I mentioned above?</p>
  
  <hr>
  
  <h1>Update 1, based on Ian answer</h1>
  
  <p>That's the test I am trying to run (see comments in some lines):</p>
  
  <pre><code>jest.dontMock('../Indicator');
  
  describe('Indicator', function() {
    it('waits 1 second foreach tick', function() {
  
      var React = require('react/addons');
      var Indicator = require('../Indicator.js');
      var TestUtils = React.addons.TestUtils;
  
      var refresh = jest.genMockFunction();
      Indicator.refresh = refresh;
  
      var onChange = jest.genMockFunction();
      Indicator._onChange = onChange;
  
      onChange(); //Is that the way to call it?
  
      expect(refresh).toBeCalled(); //Fails
      expect(setInterval.mock.calls.length).toBe(1); //Fails
  
      // I am trying to execute the 1 second timer till finishes (would be 60 seconds)
      jest.runAllTimers();
  
      expect(Indicator.state.elapsed).toBe(0); //Fails (I know is wrong but this is the idea)
      expect(clearInterval.mock.calls.length).toBe(1); //Fails (should call this function when time elapsed is 0)
  
    });
  });
  </code></pre>
  
  <p>I am still misunderstanding something...</p>