Time-dependent UI is hard to test in real time: a "5 minutes ago" label takes 5 minutes to verify, and a session-timeout warning sits idle for 14 minutes before firing. The clock steps wrap Playwright's page.clock API in BDD phrasings so scenarios can freeze and advance virtual time at full speed - scheduled emails, expirations, countdowns, and relative timestamps are all covered without slowing down CI with real waits.
Once a fake clock is installed, Date.now() inside the page returns the fake time, and pending setTimeout / setInterval callbacks queue but do not fire until you advance the clock. Each advance then fires every timer scheduled within the new interval, in order, instantly. Because the clock lives on the page, you must have a page open (for example via Given I am on "/path") before installing it - the steps raise a friendly error with that hint if you forget.
Reach for these steps together with wait steps and web-first assertions: instead of waiting a real 30 seconds for a countdown, install the clock, advance it 30 seconds, and assert the new state immediately.
Quick reference
| Step | What it does |
|---|---|
Given the system time is "2026-05-08T10:00:00Z" | Install a fake clock anchored at an ISO 8601 instant. |
When I advance the clock by 500 ms | Advance the fake clock forward by N milliseconds. |
When I advance the clock by 30 seconds | Advance the fake clock forward by N seconds. |
When I advance the clock by 5 minutes | Advance the fake clock forward by N minutes. |
When I pause the clock | Pause the fake clock at its current value. |
When I resume the clock | Resume the paused fake clock. |
When I set the system time to "2026-05-08T12:30:00Z" | Jump the fake clock to a specific time without firing skipped timers. |
Steps in detail
Given the system time is "<ISO 8601>"
Installs a fake clock anchored at the given instant via page.clock.install(). The parameter must be a valid ISO 8601 date such as 2026-05-08T10:00:00Z; timezone offsets like 2026-07-04T12:00:00-04:00 work too. An unparseable date fails immediately with a hint showing the expected format, and installing without an open page fails with a hint to navigate first.
Install the clock before loading the page under test if you need its scripts to see the fake time on their first execution.
Given I am on "/date.html"
And the system time is "2026-05-08T10:00:00Z"
Then I should see ""
When I advance the clock by <N> ms / seconds / minutes
Three unit variants of the same operation: they call page.clock.runFor() with the interval converted to milliseconds. Every timer scheduled within the advanced window fires, in order, instantly - so a 15-minute session timer completes in a fraction of a second. Singular forms (1 second, 1 minute) and the we pronoun are accepted. If no fake clock is installed yet, the step fails with a hint to run Given the system time is "..." first.
When I advance the clock by 500 ms
And I advance the clock by 30 seconds
And I advance the clock by 5 minutes
Then "<.timestamp>" should have text "5 minutes ago"
When I pause the clock / When I resume the clock
pause freezes time at the current value (page.clock.pauseAt() with the page's current Date.now()), which is useful for asserting a countdown mid-flight without it ticking away underneath the assertion. resume lets time flow again; it expects a previously paused clock and hints accordingly if there is none.
When I pause the clock
Then the element ".countdown" should be displayed
When I resume the clock
When I set the system time to "<ISO 8601>"
Jumps the fake clock to a new instant via page.clock.setSystemTime() without firing the timers scheduled in between - use an advance step instead if you want them to fire. Like the install step, it validates the ISO 8601 format up front and requires the fake clock to already be installed.
Given the system time is "2026-12-31T23:59:55Z"
When I set the system time to "2027-01-01T00:00:00Z"
Then I should see "Happy New Year"
Complete example
Feature: Session timeout warning
Scenario: Idle warning fires at 14 minutes
Given the system time is "2026-05-08T10:00:00Z"
And I restore the auth state from "tests/auth/admin.json"
And I am on "/dashboard"
When I advance the clock by 14 minutes
Then "<#session-warning>" should be visible
Scenario: "5 minutes ago" updates as time passes
Given the system time is "2026-05-08T10:00:00Z"
And I am on "/feed"
And "<.timestamp>" should have text "just now"
When I advance the clock by 5 minutes
Then "<.timestamp>" should have text "5 minutes ago"
Tips
requestAnimationFrameandMutationObserverare not on the fake clock - animations driven byrAFkeep playing in real time.- The
Dateconstructor reads the fake clock, but server timestamps embedded in the HTML at page load do not change. - Install the clock before navigating if page scripts must see the fake time on first execution.
set the system timeskips intermediate timers;advance the clockfires them.