Mock dates and timers in Playwright
Use the Clock API to fix Date values or advance timers, with explicit time zones and clear browser-context boundaries.
In Playwright 1.45 and later, use page.clock for browser time control. setFixedTime() fixes the value returned by Date; install(), pauseAt(), and runFor() let you control timers as well. There is no clock.tick() method, and a duration string such as 01:30 means one minute and thirty seconds.
Although the API is reached through a page, the installed clock applies to the entire browser context, including its pages and iframes. It does not change the backend's clock.
Use the Clock API
These Playwright Test examples use an example page. Replace it with the application whose time-dependent behavior you need to verify:
import { test, expect } from '@playwright/test';
test('fixed browser date', async ({ page }) => {
await page.clock.setFixedTime(new Date('2026-06-21T13:00:00Z'));
await page.goto('https://example.com');
expect(await page.evaluate(() => Date.now()))
.toBe(Date.parse('2026-06-21T13:00:00Z'));
});
test('advance browser timers', async ({ page }) => {
await page.clock.install({ time: new Date('2026-06-21T12:00:00Z') });
await page.goto('https://example.com');
await page.clock.pauseAt(new Date('2026-06-21T13:00:00Z'));
await page.clock.runFor(90 * 60 * 1000);
});
setFixedTime() fixes Date values while ordinary timers continue running. runFor() advances the controlled clock and runs callbacks during that interval. fastForward() has different semantics: due timers fire at most once during the jump. With many timers, a long runFor() can take substantial time, but replacing it with fastForward() changes what you test.
Use an explicit Z or UTC offset so parsing does not depend on the machine's time zone. Date formatting may also depend on the browser context's configured time zone.
Older versions: a limited Date override
For a legacy suite, an initialization script can replace part of Date behavior before the page's scripts run:
test.beforeEach(async ({ page }) => {
const fakeNow = new Date('2026-06-21T13:00:00Z').valueOf();
await page.addInitScript(`{
Date = class extends Date {
constructor(...args) {
if (args.length === 0) { super(${fakeNow}); }
else { super(...args); }
}
}
Date.now = () => ${fakeNow};
}`);
});
The no-argument constructor and Date.now() return the fixed time; explicit constructor arguments are forwarded. This is not a complete Date replacement: calling Date() as a function no longer behaves normally. It does not control timers, backend time, worker time, or native clocks. Upgrade to the supported Clock API for more demanding scenarios.
Boundaries to account for
- Register the initialization script before navigation. For Clock-based timer control, call
install()beforegoto()so the page creates timers against the controlled implementation. - Backend timestamps remain real unless the server provides its own test-time mechanism. Coordinate both sides when testing time consistency across an API.
- The legacy override does not change
setTimeout(). Timer progression requires an installed clock and methods such asrunFor(). - Animation callbacks and a controlled clock can interact. Stabilize animations when they are irrelevant to the behavior under test.
Frequently asked questions
Why not change the operating system clock?
That affects unrelated processes, certificate validation, and logs, and may require privileges unavailable in CI. Clock emulation stays within a browser context. Playwright Test normally gives each test its own isolated context.
Can I combine Playwright Clock with Sinon fake timers?
Avoid installing both in the same page; the replacements can overwrite or interfere with each other. Choose one owner of time for that test layer.
How do I test an offer expiring?
Use separate tests with a fixed date before and after the deadline, or install a clock and advance it within one test. Assert the UI outcome, and remember that server-enforced expiry needs matching backend test data or time control.
References
Related reading
Contact us
Join the community
to join the community
Try Guance
Start online and pay only for what you use.
Get startedChoose a Guance plan