Jest provides utilites to test the timeout functions like setTimeout and setInterval. We will look into testing the above two functions. If you want to understand testing async functions like http call (axios or fetch library), then checkout the following blog post - Testing asynchronous code axios or fetch library in react using enzyme.

Case 1 - settimeout function

Suppose that we have a timeout of 5 seconds inside a function, and at the end of 5 seconds, we are going to change the state to true. So the value of timeout state is false at first, then at the end of 5 seconds its true. Lets see the code and test it.

import React, { Component } from 'react';

class App extends Component {
  constructor(){
    super()
    this.state = {
      timeout: false
    }
    this.timeoutFn = this.timeoutFn.bind(this);
  }
  
  timeoutFn(){
    setTimeout(()=>{
      this.setState({
        timeout: true
      })
    },5000)
  }
  
  render() {
    return (
      <div>
      </div>
    );
  }
}

export default App;

In order to test the above function, we will use the done callback. React will wait for the done callback to be called to complete the test. So we can easily test the timeout value is true or not at the end of 5 seconds.

  it('should check timeout fn', (done)=>{
    // so the main point to note is done
    // by calling done, it will wait for the function to complete
    const app = shallow(<App />);
    expect(app.state('timeout')).toBeFalsy();
    app.instance().timeoutFn()
    setTimeout(()=>{
      expect(app.state('timeout')).toBeTruthy();
      done()
    }, 5001)
  })

We are getting the done callback from the anonymous function that we pass. So you can see that we have a timeout of 5 seconds in the test, after which we test whether the timeout is true or not.

Case 2 - Testing settimeout with fake timers

Jest provides methods to use fake timers, and it can easily run all timers without actually waiting for it. So we will use fake timers by

jest.useFakeTimers();

Then we will call the instance function timeoutFn. So this will call the set timeout. But because we are using fake timers, we can easily run it quickly using

jest.runAllTimers();

So this will run the set timeout function and call the set state. Then we can easily check if the timeout is truthy or not.

it('should check timeout fn - timeout',()=>{
    jest.useFakeTimers();
    const app = shallow(<App />);
    expect(app.state('timeout')).toBeFalsy();
    app.instance().timeoutFn();
    jest.runAllTimers();
    expect(app.state('timeout')).toBeTruthy();
    jest.useRealTimers();
})

This works with setInterval too. You can advance the timers by certain time using jest.advanceTimersByTime .

React component containing setInterval function

```
import React, { Component } from 'react';

class App extends Component {
  constructor(){
    super()
    this.state = {
      index: 0
    }
    this.intervalFn = this.intervalFn.bind(this);
  }
  
  intervalFn(){
    setTimeout(()=>{
      this.setState({
        index: this.state.index+1
      })
    },5000)
  }
  
  render() {
    return (
      <div>
      </div>
    );
  }
}

export default App;

```

Testing interval function for react component above.

  it('should test interval functions', ()=>{
    jest.useFakeTimers();
    const app = shallow(<App />);
    expect(app.state('index')).toEqual(0);
    app.instance().intervalFn();
    jest.advanceTimersByTime(5000);
    expect(app.state('index')).toEqual(1);
    jest.useRealTimers();
  })

We discussed about testing settimeout and setinterval. Wondering how to unit the asynchronous code like http call using axios and fetch api in React using enzyme? Checkout the link to understand more - Testing asynchronous code axios or fetch library in react using enzyme