d
Amit DhamuSoftware Engineer
 

Advance Timers in Jest

3 minute read 00000 views

Let's say we have a clock function which displays elapsed seconds and we wanted to add a unit test to ensure that after each second, the seconds actually updated.

We can use jest.advanceTimersByTime to do this.

Crude Clock Example

const formatTime = date =>
  [
    `00${date.getHours()}`.slice(-2),
    `00${date.getMinutes()}`.slice(-2),
    `00${date.getSeconds()}`.slice(-2),
  ].join(':')

export const clock = () => {
  let time = formatTime(new Date())

  setInterval(() => {
    time = formatTime(new Date())
  }, 1000)

  return time
}

Writing The Test

Firstly, we want to set Jest's useFakeTimers to modern and set the system time to something. In the example below, I'm using 2021-01-01 12:00:50 as it would be good to test what happens when we tick over 60 seconds.

import { clock } from './clock'

jest
  .useFakeTimers('modern')
  .setSystemTime(new Date('2021-01-01 12:00:50').getTime())

Secondly, we setup an .each where each test case is the expected time we want to assert after each second.

describe('Clock', () => {
  it.each([
    ['12:00:51'],
    ['12:00:52'],
    ['12:00:53'],
    ['12:00:54'],
    ['12:00:55'],
    ['12:00:56'],
    ['12:00:57'],
    ['12:00:58'],
    ['12:00:59'],
    ['12:01:00'],
  ])('updates the clock every second to %p', expected => {
    // Add our assertion here
  })
})

Finally, here's how we would assert the outcome.

describe('Clock', () => {
  it.each([
    ['12:00:51'],
    ['12:00:52'],
    ['12:00:53'],
    ['12:00:54'],
    ['12:00:55'],
    ['12:00:56'],
    ['12:00:57'],
    ['12:00:58'],
    ['12:00:59'],
    ['12:01:00'],
  ])('updates the clock every second to %p', expected => {
    jest.advanceTimersByTime(1000)

    expect(clock()).toEqual(expected)
  })
})

Explanation

jest.advanceTimersByTime(1000)

This is telling our test to increase the time by one second when executing each test case.

Remember, when we created the test file, we specifically set the system time to 2021-01-01 12:00:50 using Jest's fakeTimers so the first time this test runs, the time will be 12:00:51 (our first expectation in the each)

expect(clock()).toEqual(expected)

The expect here is of course the assertion where expected comes from the incoming array item in the each.