Date and time

You may be noticing a pattern here. I'm trying to keep mock definitions contained and use the hooks like beforeAll() and afterAll() to make sure no mocks are left once the tests are done (and, often, even between the tests).
Testing the getRelativeTime() function will be no exception:
beforeAll(() => {
  vi.useFakeTimers()
})

afterAll(() => {
  vi.useRealTimers()
})
Calling vi.useFakeTimers() detached this test from the real flow of time, and makes it rely on the internal fake date Vitest has. Correspondingly, the vi.useRealTimers() utility undoes that.
To fix date and time in test, I will call vi.useSystemTime() function and provide it with the date that I want to be treated as Date.now():
test('returns "Just now" for the current date', () => {
  vi.setSystemTime(new Date('2024-06-01 00:00:00.000Z'))
πŸ¦‰ vi.useSystemTime() only works in conjunction with vi.useFakeTimers().
In order to model the "Just now" scenario, the delta between the current time and the start time has to be 60 seconds or less. In this test, I will pass the exact same date to the getRelativeTime() function as the system time:
expect(getRelativeTime(new Date('2024-06-01 00:00:00.000Z'))).toBe('Just now')
This produces the time delta of 0ms, which results in the "Just now" string being returned from the function.
For the tests that feature an actual time difference, I have to use a slightly different setup. Firsts, the system time (which is Date.now()) should be set to the time that has already passed. Then, the getRelativeTime() function will accept the starting time as an argument.
test('returns "minute ago" for a date a minute ago', () => {
  vi.setSystemTime(new Date('2024-06-01 00:01:05.000Z'))
  expect(getRelativeTime(new Date('2024-06-01 00:00:00.000Z'))).toBe(
    '1 minute ago',
  )
})
Above, I'm setting the 1m 5s 0ms time difference because the system time is exactly that duration ahead of the starting time passed to getRelativeTime().
πŸ“œ It's worth mentioning that Vitest has a vi.advanceTimersByTime() method to help you advance the system time by a given amount in milliseconds. I am intentionally not using that method in this test for two reasons:
  1. Working with full dates is more convenient in this case. You can easily tell apart a 1m 5s difference. Using milliseconds, you'd have to compute that difference in your head every time you read the test.
  2. vi.advanceTimersByTime() advances the date in place. This means that as soon as I call it, the Date.now() will shift by the given amount. I would have to store the initial date separately because that's the date that has to be passed to the getRelativeTime() function (i.e. the start time).
You are free to explore the test suite to spot any additional test cases you might have missed to cover the function's behavior.

Access Denied

You must login or register for the workshop to view and run the tests.

Check out this video to see how the test tab works.