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.
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
}
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)
})
})
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
.