Clock
Test trials, expiries and schedules without waiting, by moving the device's wall clock forward, to an instant or freezing it from a spec or a suite.
device.clock moves the wall clock the app reads with Date.now(), so a 14-day trial can expire in one step. The real time comes back when the test ends.
await device.clock.advance("15d");
await device.clock.set("2027-01-01T00:00:00Z", { frozen: true }); // iOS only
await device.clock.during("2027-01-01T00:00:00Z", async () => { /* ... */ });
await device.clock.reset();| Call | Does |
|---|---|
advance(duration) | move the clock forward from now |
set(instant, { frozen? }) | jump to an ISO instant; frozen holds it there (iOS only) |
during(instant, fn) | run fn at that instant, then restore |
reset() | back to the suite's conditions.clock, or real time without one |
Durations are milliseconds or "10s", "2m", "2d". The wall clock moves; monotonic clocks do not, so timers and animations keep running. On iOS the clock changes only for an app launched with the network dylib, as for the network.
Practice
- A large offset breaks TLS: certificates look expired or not yet valid, so HTTPS fails while the clock is far from real time. Do not make requests in a spec that advances the clock by weeks.
- A JS timer armed while the clock was ahead waits for the shifted time once the clock goes back. Re-read the time on demand (the example's clock card has a Refresh button) or relaunch the app after
reset().
In a suite
conditions: { clock: { offset: "2d" } },clock takes an ISO instant (it keeps running), { at, frozen? } or { offset: "2d" }. On iOS, declaring it launches every app with the dylib.
Per-platform behaviour and warden ui clock: Clock on a simulator.
Location
Test geofences, run trackers and location-gated screens with a GPS point, a route or a GPX file played at a speed, from a spec or a suite.
Biometrics
Test Face ID, Touch ID and Android fingerprint unlocks against the real system prompt from a spec - enroll, match, fail, and the biometrics config key.