Recipes for unit tests when working with date and time in React/JavaScript

Thomas Rutzer
3 min readNov 5, 2020

In one of our last major projects at my company, we had to deal with real-time flight data. This concluded into processing and calculating with a lot of date and time values. Tests helped, as always, to run everything smoothly and precisely. Now in the aftermath, I want to show you what helped us to write meaningful unit tests.

Tools

These tools help you, but it also important to bring in a proper mindset when testing date and time.

Mindset

  • handle only one format in your application. It doesn't really matter if you decide to work with JavaScript Date Objects (the value of new Date()) or its static method Date.now() which returns the number of milliseconds elapsed since January 1, 1970 00:00:00 UTC. Just stick to one and re-format when needed (with date-fns since moment stopped service)
  • always stub or mock real date and time functions. Never rely on any system time, this will get you into trouble, I promise.

Examples

Mock the date

No matter what you want to test, mock before you start. With jest, it often makes sense to use the beforeEach/All and afterEach/All hooks.

import mockdate from "mockdate"const mockdateInit = 1580782960 // 2020-02-04T02:22:40describe("yourTest", () => {
beforeEach(() => {
mockdate.set(mockdateInit)
})
afterAll(() => {
mockdate.reset()
})
})

As said before, we use mockdate here, which will for now always return mockdateInit for a new Date() call.

Sorting

If you now want to sort by date or time, let's say make groups of future or past dates, this is fairly easy. Just remember you are now in the time of mockdateInit. You can enhance the previous setup like this:


...
const anyOtherDate = 1580782970
...
...
it("should be in the future", () => {
const result = anyOtherDate > mockdateInit
expect(result).toBeTruthy()
})
...

Of course, any other calculation based tasks can be tested the same way.

Timelapse

Sometimes you want to test a timelapse. Let's say, you want to check a state now and any changes in the next 5 minutes. Like the flight data we processed. For that, since you don't really want to wait 5 minutes while your tests are running (and sincerely your co-workers or CI neither), Jests' timer mocks with their advanceTimersByTime method is here to help. Here is a unit test that utilizes the @testing-library/react-hooks and updateEveryMinute hook, which internally updates every full minute.


...
const mockDateInit = 1580782960 // 2020-02-04T02:22:40
const mockDateNextFullMinute = 1580782980 // 2020-02-04T02:23:00
const mockDateMinuteAfterNext = 1580783040 // 2020-02-04T02:24:00
const mockDateAfterAfter3Minutes = 1580783100 // 2020-02-04T02:25:00
...
...
jest.useFakeTimers() // make sure Jest uses them
...
it("should update every full minute after first update", () => {
const { result } = renderHook(() => useCurrentTime())
Mockdate.set(mockdateMinuteAfterNext)
act(() => jest.advanceTimersByTime(100000))
expect(result.current).toEqual(Math.floor(mockdateMinuteAfterNext / 1000)) Mockdate.set(mockdateAfterAfter3Minutes)
act(() => jest.advanceTimersByTime(60000))
expect(result.current).toEqual(Math.floor(mockdateAfterAfter3Minutes / 1000))
})

As you can see: We test and then update mockdate so it returns a new date mock it the next iteration.

Wrap it up

So I hope, that gave you some ideas, when you write unit tests for a JavaScript app that uses a date and time-relevant data.
If you have a relevant use case and don't know how to test it – leave a comment!

--

--

Thomas Rutzer

hay I’m Thomas, specialized in crafting unique interfaces & interactions for the browser platform. Meet me on twitter or github: @thomasrutzer