Vehicles Time Travel Utility
Vehicles is a JavaScript/TypeScript testing utility designed to manipulate the system's time, enabling developers to 'travel into the future' for deterministic testing of time-sensitive code. It achieves this by mocking and controlling internal timers, such as `setTimeout`, `setInterval`, and `Date.now()`, allowing tests to execute scenarios involving time progression without actual real-time waits. The current stable version is 10.0.23, with a release cadence that appears to be frequent, primarily consisting of patch releases. Its key differentiator lies in providing a controlled environment for asynchronous operations and date-based logic, ensuring test reliability and speed. The package explicitly targets Node.js environments, requiring version 18.2.0 or higher.
Common errors
-
TypeError: vehicles is not a function
cause Attempting to call the top-level 'vehicles' module as a function, or incorrectly destructuring a named export when a default export was expected (or vice-versa).fixCheck the import statement. Ensure you are importing the correct named function (e.g., `travel`) and not trying to call the module itself, for example: `import { travel } from 'vehicles';`. -
ERR_REQUIRE_ESM
cause Trying to `require()` the `vehicles` package, which is an ES Module, from a CommonJS context.fixUpdate your project to use ES Modules (by adding `"type": "module"` to `package.json`) and use `import` statements, or switch to dynamic `import('vehicles')` if mixing CJS and ESM. -
ReferenceError: setTimeout is not defined
cause This error typically indicates that the `vehicles` library, or another part of your test setup, is attempting to mock or interact with timers in an environment where the global `setTimeout` (or other timer functions) is not available or has been unexpectedly removed. This might occur if a test runner's environment is not correctly configured for Node.js globals.fixEnsure your test runner (e.g., Jest, Mocha) is configured to run in a Node.js environment or has access to Node.js global timers. Verify that no other library or setup is inadvertently removing global timer functions before `vehicles` initializes.
Warnings
- breaking The package requires Node.js version 18.2.0 or higher. Using it with older Node.js versions will result in runtime errors related to unsupported syntax or APIs, specifically ESM features.
- gotcha Vehicles primarily operates as an ES Module (ESM). Attempting to import it using CommonJS `require()` syntax in a pure CommonJS project might lead to errors like 'ERR_REQUIRE_ESM' or incorrect module resolution, even with bundlers, unless explicit interop is configured.
- gotcha Forgetting to call `reset()` between tests can lead to test pollution, where time mocks from a previous test affect subsequent tests, causing flaky or incorrect results.
Install
-
npm install vehicles -
yarn add vehicles -
pnpm add vehicles
Imports
- travel
const { travel } = require('vehicles');import { travel } from 'vehicles'; - reset
import reset from 'vehicles/reset';
import { reset } from 'vehicles'; - MockedDate
import { MockedDate } from 'vehicles';import type { MockedDate } from 'vehicles';
Quickstart
import { travel, reset } from 'vehicles';
describe('Time-sensitive feature', () => {
// Store original Date to restore after all tests
const originalDate = global.Date;
beforeEach(() => {
// Reset time mocks before each test to ensure isolation
reset();
});
afterAll(() => {
// Restore global Date object after all tests in the suite
global.Date = originalDate;
});
it('should trigger an event after a specific delay', async () => {
let eventTriggered = false;
setTimeout(() => {
eventTriggered = true;
}, 10000); // 10 seconds
// Initial state check
expect(eventTriggered).toBe(false);
// Travel 5 seconds into the future
await travel(5000);
expect(eventTriggered).toBe(false); // Should still be false
// Travel another 5 seconds (total 10) to trigger the event
await travel(5000);
expect(eventTriggered).toBe(true);
});
it('should mock current date correctly', async () => {
const initialDate = new Date();
await travel(60 * 60 * 1000); // Travel 1 hour into the future
const afterTravelDate = new Date();
expect(afterTravelDate.getTime()).toBe(initialDate.getTime() + 60 * 60 * 1000);
});
});