-
Notifications
You must be signed in to change notification settings - Fork 5.1k
Description
Version
1.57.0
Steps to reproduce
- Download this HTML file: test.html
- Run the following test using
pytest-playwright:
def test_bug_poc(page: Page):
path_to_test_html = "change-me"
page.goto(f"file:///{path_to_test_html}")
page.clock.set_fixed_time(datetime(2026, 1, 2, 10, 0, 0))
page.goto(f"file:///{path_to_test_html}")
- (Optional) Add a breakpoint on:
page.clock.set_fixed_time(datetime(2026, 1, 2, 10, 0, 0))
Expected behavior
The animation should behave identically before and after applying the clock patch, including after page navigation or refresh.
Actual behavior
After calling clock.set_fixed_time and navigating / refreshing the page, the animation no longer runs at the expected time. Instead, it starts several seconds later than it should.
Additional context
While writing tests that require mocking new Date(), I noticed flaky behavior in animations. After further investigation, I identified two related issues with the current clock implementation:
-
set_fixed_timeimplicitly callsinstall()and patches all time-related APIs
Theclock.set_fixed_timemethod internally callsinstall()and patches multiple time-related functions (see code here)).
In my use case, I only wanted to mockDate. Patching additional APIs such asperformance.now()and animation timing APIs introduces unintended side effects. It would be preferable ifset_fixed_timeonly patchedDate, unless explicitly requested otherwise. -
document.timeline.currentTimeis not patched
The clock patchesperformance.now(), but does not patchdocument.timeline.currentTime. This causes issues with animation libraries like motion, which rely on bothperformance.now()anddocument.timeline.currentTime()(example here).
As a result, after navigation or refresh:
- The browser’s native
performance.now()anddocument.timeline.currentTimeresets to 0 - The patched
performance.now()continues from the original patched offset document.timeline.currentTimecontinues to use the unpatched timeline
This mismatch causes animations to be delayed by the time elapsed between the original clock patch and the page navigation.
In the provided reproducer console, you can also observe that after a page refresh or navigation, the animation’s currentTime becomes negative, starting from the difference between the original time patch and the refresh/navigation.
This bug is difficult to notice because:
- It only appears when using Web Animations APIs
- The animation library must rely on both
performance.now()anddocument.timeline.currentTime() - A page refresh or navigation is required
When using set_fixed_time without navigation, the issue is often masked because the patched and unpatched performance.now() values remain close.
Proposed solutions
- When calling
clock.set_fixed_time, only patchDate()by default - For cases where full clock mocking is desired, also patch
document.timeline.currentTime - Provide a way to unpatch / restore patched time functions, for example via:
- a
clock.reset()/clock.uninstall()API, or - automatically restoring the original implementations on page navigation or reload.
Either approach would significantly improve reliability when testing animation-heavy applications, especially those using libraries like motion.
Environment
System:
OS: Windows 11 10.0.26200
CPU: (20) x64 13th Gen Intel(R) Core(TM) i9-13900H
Memory: 37.95 GB / 63.66 GB
Binaries:
Node: 22.16.0 - C:\Program Files\nodejs\node.EXE
npm: 11.4.2 - C:\Program Files\nodejs\npm.CMD
pnpm: 10.26.0 - C:\Users\xxx\AppData\Roaming\npm\pnpm.CMD
IDEs:
VSCode: 1.108.2 - C:\Users\xxx\AppData\Local\Programs\Microsoft VS Code\bin\code.CMD
Cursor: 1.7.17 - C:\Users\xxx\AppData\Local\Programs\cursor\resources\app\bin\cursor.CMD