test_runner: Add Date to the supported mock APIs by khaosdoctor · Pull Request #48638 · nodejs/node
This builds on top of @ErickWendel's #47775, I saw the next steps would be to implement the mock timers for Date.now (and thus, the Date object) and performance.now.
This PR implements the Date.now mock, I'll also work on performance.now on another PR to make it simpler to review. This one includes the Docs already updated and the added tests.
This heavily builds on Sinon's Fake Timers for the base edge cases
To-Do
- Refactor the code to make
setTimeactually call thetickmethod and pass the time - Make the initial time be 0 or accept an instance of
Date, or a specific number to make it's implementation be the same as fake-timers - Mock the Date object completely
- Allow
enableto accept multiple overloads
Next iterations
- Mock
performance.now - Mock
process.hrtime
New MockTimers API
// All that was before, with no changes MockTimers.reset() // clean up to the original state MockTimers.tick(100) // advance in time by 100ms MockTimers.runAll() // release all timers // Implementation changes MockTimers.enable({ timersToEnable: ['setInterval', 'setTimeout', 'Date' ], now: 1000 }) // enable fake timers with the initial timer set (optional) // New methods MockTimers.setTime(100) // sets Date.now to the desired value
It's also possible to omit the initial parameter and pass on only the initial epoch, which will enable all timers with that epoch set:
// All that was before, with no changes MockTimers.reset() // clean up to the original state MockTimers.tick(100) // advance in time by 100ms MockTimers.runAll() // release all timers // Implementation changes MockTimers.enable({ now: 1000 }) // enable fake timers with the initial timer set (optional) // New methods MockTimers.setTime(100) // sets Date.now to the desired value
Lastly, you can omit all parameters to enable all timers at the epoch 0:
// All that was before, with no changes MockTimers.reset() // clean up to the original state MockTimers.tick(100) // advance in time by 100ms MockTimers.runAll() // release all timers // Implementation changes MockTimers.enable() // New methods MockTimers.setTime(100) // sets Date.now to the desired value
Example usage
import assert from 'node:assert'; import { test } from 'node:test'; test('mocks Date.now to whatever value the user sets', (context) => { const now = Date.now() console.log(now) // not mocked, will print correct timestamp context.mock.timers.enable({ apis: ['Date'] }); // This will be roughly true. Just to take it as example assert.strictEqual(now, Date.now()) // if not set, will take the value of Date.now() as initial value context.mock.timers.setTime(1000) assert.strictEqual(Date.now(), 1000) // Date.now is 1000 });
import assert from 'node:assert'; import { test } from 'node:test'; test('mocks Date.now to whatever value the user sets', (context) => { const now = Date.now() console.log(now) // not mocked, will print correct timestamp context.mock.timers.enable({ apis: ['Date'], now: 1000 }); // This will be roughly true. Just to take it as example assert.strictEqual(Date.now(), 1000) // Date.now is 1000 due to being set in enable() });
All the remaining APIs are the same