@storyshots/web-api-mocks
Replaces Date, timers, and local storage with their testable counterparts
through an invasive method.
install
Replaces non-deterministic browser APIs. Returns a Clock.
import { install } from '@storyshots/web-api-mocks';
// Freezes time on the page at 13.01.2024 12:00
export const clock = install({ now: new Date(2024, 0, 13, 12) });
Must be called before any other code on the page executes.
clock
Time control object.
Operates under the following rules:
- The date remains fixed and does not change over time.
- Timers (
setTimeout,setInterval) on the page execute normally.
clock is available on the global window object, making it usable in exec.
tick
Advances time forward by the specified number of ms.
Consider the following behavior:
// Notification closes after 5 seconds
setTimeout(() => closeNotification(), 5_000);
To avoid waiting for 5 seconds in the history, use the special tick method:
it('closes notification', {
act: (actor) =>
actor
.screenshot('NotificationShown')
// Fast-forward 5 seconds
.exec(() => window.clock.tick(5_000))
.screenshot('NotificationHidden'),
});
The method affects only timers; the current date remains unchanged. See unfreeze
setSystemTime
Sets the current date:
it('...', {
arrange: (externals) => {
// For this story, the date will be set to 13.01.2024
clock.setSystemTime(new Date(2024, 0, 13));
return externals;
},
});
The method affects only the current date; timers are not recalculated.
unfreeze
Unfreezes the current date:
it('...', {
arrange: (externals) => {
// For this story, the date will change over time
clock.unfreeze();
return externals;
},
});
The unfreeze function effectively restores natural time flow on the page, partially undoing the effects
of @storyshots/web-api-mocks.
Use only in rare cases, for example when using debounce.
Otherwise, it is not recommended.
State
@storyshots/web-api-mocks also replaces local storage with in-memory storage that persists data temporally.
// This write will be automatically cleared when a new story runs
localStorage.setItem('token', '...');
IndexedDB is not replaced by this module.