diff --git a/README.md b/README.md
index aca6755bc..92cd726ab 100644
--- a/README.md
+++ b/README.md
@@ -4,7 +4,7 @@ Playwright is a Python library to automate [Chromium](https://www.chromium.org/H
| | Linux | macOS | Windows |
| :--- | :---: | :---: | :---: |
-| Chromium 127.0.6533.5 | ✅ | ✅ | ✅ |
+| Chromium 127.0.6533.17 | ✅ | ✅ | ✅ |
| WebKit 17.4 | ✅ | ✅ | ✅ |
| Firefox 127.0 | ✅ | ✅ | ✅ |
diff --git a/playwright/_impl/_clock.py b/playwright/_impl/_clock.py
index 11c230b92..d8bb58718 100644
--- a/playwright/_impl/_clock.py
+++ b/playwright/_impl/_clock.py
@@ -25,7 +25,7 @@ def __init__(self, browser_context: "BrowserContext") -> None:
self._loop = browser_context._loop
self._dispatcher_fiber = browser_context._dispatcher_fiber
- async def install(self, time: Union[int, str, datetime.datetime] = None) -> None:
+ async def install(self, time: Union[float, str, datetime.datetime] = None) -> None:
await self._browser_context._channel.send(
"clockInstall", parse_time(time) if time is not None else {}
)
@@ -40,7 +40,7 @@ async def fast_forward(
async def pause_at(
self,
- time: Union[int, str, datetime.datetime],
+ time: Union[float, str, datetime.datetime],
) -> None:
await self._browser_context._channel.send("clockPauseAt", parse_time(time))
@@ -57,25 +57,27 @@ async def run_for(
async def set_fixed_time(
self,
- time: Union[int, str, datetime.datetime],
+ time: Union[float, str, datetime.datetime],
) -> None:
await self._browser_context._channel.send("clockSetFixedTime", parse_time(time))
async def set_system_time(
self,
- time: Union[int, str, datetime.datetime],
+ time: Union[float, str, datetime.datetime],
) -> None:
await self._browser_context._channel.send(
"clockSetSystemTime", parse_time(time)
)
-def parse_time(time: Union[int, str, datetime.datetime]) -> Dict[str, Union[int, str]]:
- if isinstance(time, int):
- return {"timeNumber": time}
+def parse_time(
+ time: Union[float, str, datetime.datetime]
+) -> Dict[str, Union[int, str]]:
+ if isinstance(time, (float, int)):
+ return {"timeNumber": int(time * 1_000)}
if isinstance(time, str):
return {"timeString": time}
- return {"timeNumber": int(time.timestamp())}
+ return {"timeNumber": int(time.timestamp() * 1_000)}
def parse_ticks(ticks: Union[int, str]) -> Dict[str, Union[int, str]]:
diff --git a/playwright/async_api/_generated.py b/playwright/async_api/_generated.py
index 5afc93a7b..0a866ef75 100644
--- a/playwright/async_api/_generated.py
+++ b/playwright/async_api/_generated.py
@@ -6664,7 +6664,9 @@ def set_test_id_attribute(self, attribute_name: str) -> None:
class Clock(AsyncBase):
async def install(
- self, *, time: typing.Optional[typing.Union[int, str, datetime.datetime]] = None
+ self,
+ *,
+ time: typing.Optional[typing.Union[float, str, datetime.datetime]] = None
) -> None:
"""Clock.install
@@ -6686,7 +6688,7 @@ async def install(
Parameters
----------
- time : Union[datetime.datetime, int, str, None]
+ time : Union[datetime.datetime, float, str, None]
Time to initialize with, current system time by default.
"""
@@ -6714,7 +6716,7 @@ async def fast_forward(self, ticks: typing.Union[int, str]) -> None:
return mapping.from_maybe_impl(await self._impl_obj.fast_forward(ticks=ticks))
- async def pause_at(self, time: typing.Union[int, str, datetime.datetime]) -> None:
+ async def pause_at(self, time: typing.Union[float, str, datetime.datetime]) -> None:
"""Clock.pause_at
Advance the clock by jumping forward in time and pause the time. Once this method is called, no timers are fired
@@ -6733,7 +6735,8 @@ async def pause_at(self, time: typing.Union[int, str, datetime.datetime]) -> Non
Parameters
----------
- time : Union[datetime.datetime, int, str]
+ time : Union[datetime.datetime, float, str]
+ Time to pause at.
"""
return mapping.from_maybe_impl(await self._impl_obj.pause_at(time=time))
@@ -6768,7 +6771,7 @@ async def run_for(self, ticks: typing.Union[int, str]) -> None:
return mapping.from_maybe_impl(await self._impl_obj.run_for(ticks=ticks))
async def set_fixed_time(
- self, time: typing.Union[int, str, datetime.datetime]
+ self, time: typing.Union[float, str, datetime.datetime]
) -> None:
"""Clock.set_fixed_time
@@ -6784,14 +6787,14 @@ async def set_fixed_time(
Parameters
----------
- time : Union[datetime.datetime, int, str]
+ time : Union[datetime.datetime, float, str]
Time to be set.
"""
return mapping.from_maybe_impl(await self._impl_obj.set_fixed_time(time=time))
async def set_system_time(
- self, time: typing.Union[int, str, datetime.datetime]
+ self, time: typing.Union[float, str, datetime.datetime]
) -> None:
"""Clock.set_system_time
@@ -6807,7 +6810,8 @@ async def set_system_time(
Parameters
----------
- time : Union[datetime.datetime, int, str]
+ time : Union[datetime.datetime, float, str]
+ Time to be set.
"""
return mapping.from_maybe_impl(await self._impl_obj.set_system_time(time=time))
@@ -8662,22 +8666,6 @@ async def main():
asyncio.run(main())
```
- An example of passing an element handle:
-
- ```py
- async def print(source, element):
- print(await element.text_content())
-
- await page.expose_binding(\"clicked\", print, handle=true)
- await page.set_content(\"\"\"
-
-
Click me
- Or click me
- \"\"\")
- ```
-
Parameters
----------
name : str
@@ -8687,6 +8675,7 @@ async def print(source, element):
handle : Union[bool, None]
Whether to pass the argument as a handle, instead of passing by value. When passing a handle, only one argument is
supported. When passing by value, multiple arguments are supported.
+ Deprecated: This option will be removed in the future.
"""
return mapping.from_maybe_impl(
@@ -12849,22 +12838,6 @@ async def main():
asyncio.run(main())
```
- An example of passing an element handle:
-
- ```py
- async def print(source, element):
- print(await element.text_content())
-
- await context.expose_binding(\"clicked\", print, handle=true)
- await page.set_content(\"\"\"
-
- Click me
- Or click me
- \"\"\")
- ```
-
Parameters
----------
name : str
@@ -12874,6 +12847,7 @@ async def print(source, element):
handle : Union[bool, None]
Whether to pass the argument as a handle, instead of passing by value. When passing a handle, only one argument is
supported. When passing by value, multiple arguments are supported.
+ Deprecated: This option will be removed in the future.
"""
return mapping.from_maybe_impl(
diff --git a/playwright/sync_api/_generated.py b/playwright/sync_api/_generated.py
index 6dfe26ee8..2f28abbb9 100644
--- a/playwright/sync_api/_generated.py
+++ b/playwright/sync_api/_generated.py
@@ -6774,7 +6774,9 @@ def set_test_id_attribute(self, attribute_name: str) -> None:
class Clock(SyncBase):
def install(
- self, *, time: typing.Optional[typing.Union[int, str, datetime.datetime]] = None
+ self,
+ *,
+ time: typing.Optional[typing.Union[float, str, datetime.datetime]] = None
) -> None:
"""Clock.install
@@ -6796,7 +6798,7 @@ def install(
Parameters
----------
- time : Union[datetime.datetime, int, str, None]
+ time : Union[datetime.datetime, float, str, None]
Time to initialize with, current system time by default.
"""
@@ -6826,7 +6828,7 @@ def fast_forward(self, ticks: typing.Union[int, str]) -> None:
self._sync(self._impl_obj.fast_forward(ticks=ticks))
)
- def pause_at(self, time: typing.Union[int, str, datetime.datetime]) -> None:
+ def pause_at(self, time: typing.Union[float, str, datetime.datetime]) -> None:
"""Clock.pause_at
Advance the clock by jumping forward in time and pause the time. Once this method is called, no timers are fired
@@ -6845,7 +6847,8 @@ def pause_at(self, time: typing.Union[int, str, datetime.datetime]) -> None:
Parameters
----------
- time : Union[datetime.datetime, int, str]
+ time : Union[datetime.datetime, float, str]
+ Time to pause at.
"""
return mapping.from_maybe_impl(self._sync(self._impl_obj.pause_at(time=time)))
@@ -6879,7 +6882,7 @@ def run_for(self, ticks: typing.Union[int, str]) -> None:
return mapping.from_maybe_impl(self._sync(self._impl_obj.run_for(ticks=ticks)))
- def set_fixed_time(self, time: typing.Union[int, str, datetime.datetime]) -> None:
+ def set_fixed_time(self, time: typing.Union[float, str, datetime.datetime]) -> None:
"""Clock.set_fixed_time
Makes `Date.now` and `new Date()` return fixed fake time at all times, keeps all the timers running.
@@ -6894,7 +6897,7 @@ def set_fixed_time(self, time: typing.Union[int, str, datetime.datetime]) -> Non
Parameters
----------
- time : Union[datetime.datetime, int, str]
+ time : Union[datetime.datetime, float, str]
Time to be set.
"""
@@ -6902,7 +6905,9 @@ def set_fixed_time(self, time: typing.Union[int, str, datetime.datetime]) -> Non
self._sync(self._impl_obj.set_fixed_time(time=time))
)
- def set_system_time(self, time: typing.Union[int, str, datetime.datetime]) -> None:
+ def set_system_time(
+ self, time: typing.Union[float, str, datetime.datetime]
+ ) -> None:
"""Clock.set_system_time
Sets current system time but does not trigger any timers.
@@ -6917,7 +6922,8 @@ def set_system_time(self, time: typing.Union[int, str, datetime.datetime]) -> No
Parameters
----------
- time : Union[datetime.datetime, int, str]
+ time : Union[datetime.datetime, float, str]
+ Time to be set.
"""
return mapping.from_maybe_impl(
@@ -8689,22 +8695,6 @@ def run(playwright: Playwright):
run(playwright)
```
- An example of passing an element handle:
-
- ```py
- def print(source, element):
- print(element.text_content())
-
- page.expose_binding(\"clicked\", print, handle=true)
- page.set_content(\"\"\"
-
- Click me
- Or click me
- \"\"\")
- ```
-
Parameters
----------
name : str
@@ -8714,6 +8704,7 @@ def print(source, element):
handle : Union[bool, None]
Whether to pass the argument as a handle, instead of passing by value. When passing a handle, only one argument is
supported. When passing by value, multiple arguments are supported.
+ Deprecated: This option will be removed in the future.
"""
return mapping.from_maybe_impl(
@@ -12871,22 +12862,6 @@ def run(playwright: Playwright):
run(playwright)
```
- An example of passing an element handle:
-
- ```py
- def print(source, element):
- print(element.text_content())
-
- context.expose_binding(\"clicked\", print, handle=true)
- page.set_content(\"\"\"
-
- Click me
- Or click me
- \"\"\")
- ```
-
Parameters
----------
name : str
@@ -12896,6 +12871,7 @@ def print(source, element):
handle : Union[bool, None]
Whether to pass the argument as a handle, instead of passing by value. When passing a handle, only one argument is
supported. When passing by value, multiple arguments are supported.
+ Deprecated: This option will be removed in the future.
"""
return mapping.from_maybe_impl(
diff --git a/scripts/documentation_provider.py b/scripts/documentation_provider.py
index f76509443..82e3f4bb6 100644
--- a/scripts/documentation_provider.py
+++ b/scripts/documentation_provider.py
@@ -481,6 +481,8 @@ def inner_serialize_doc_type(self, type: Any, direction: str) -> str:
return f"{{{', '.join(items)}}}"
if type_name == "boolean":
return "bool"
+ if type_name == "long":
+ return "int"
if type_name.lower() == "string":
return "str"
if type_name == "any" or type_name == "Serializable":
diff --git a/setup.py b/setup.py
index 46d323f17..2a0454820 100644
--- a/setup.py
+++ b/setup.py
@@ -30,7 +30,7 @@
InWheel = None
from wheel.bdist_wheel import bdist_wheel as BDistWheelCommand
-driver_version = "1.45.0-alpha-2024-06-14"
+driver_version = "1.45.1-beta-1719996498000"
def extractall(zip: zipfile.ZipFile, path: str) -> None:
diff --git a/tests/async/test_page_clock.py b/tests/async/test_page_clock.py
index 1339efaae..0676ee581 100644
--- a/tests/async/test_page_clock.py
+++ b/tests/async/test_page_clock.py
@@ -151,7 +151,7 @@ class TestFastForward:
@pytest.fixture(autouse=True)
async def before_each(self, page: Page) -> AsyncGenerator[None, None]:
await page.clock.install(time=0)
- await page.clock.pause_at(1000)
+ await page.clock.pause_at(1)
yield
async def test_ignores_timers_which_wouldnt_be_run(
@@ -184,11 +184,11 @@ class TestStubTimers:
@pytest.fixture(autouse=True)
async def before_each(self, page: Page) -> AsyncGenerator[None, None]:
await page.clock.install(time=0)
- await page.clock.pause_at(1000)
+ await page.clock.pause_at(1)
yield
async def test_sets_initial_timestamp(self, page: Page) -> None:
- await page.clock.set_system_time(1400)
+ await page.clock.set_system_time(1.4)
assert await page.evaluate("Date.now()") == 1400
async def test_replaces_global_setTimeout(
@@ -255,8 +255,8 @@ async def test_fakes_Date_constructor(self, page: Page) -> None:
class TestStubTimersPerformance:
async def test_replaces_global_performance_time_origin(self, page: Page) -> None:
- await page.clock.install(time=1000)
- await page.clock.pause_at(2000)
+ await page.clock.install(time=1)
+ await page.clock.pause_at(2)
promise = asyncio.create_task(
page.evaluate(
"""async () => {
@@ -282,10 +282,10 @@ async def test_should_tick_after_popup(self, page: Page) -> None:
page.wait_for_event("popup"), page.evaluate("window.open('about:blank')")
)
popup_time = await popup.evaluate("Date.now()")
- assert popup_time == now.timestamp()
+ assert popup_time == now.timestamp() * 1000
await page.clock.run_for(1000)
popup_time_after = await popup.evaluate("Date.now()")
- assert popup_time_after == now.timestamp() + 1000
+ assert popup_time_after == now.timestamp() * 1000 + 1000
async def test_should_tick_before_popup(self, page: Page) -> None:
await page.clock.install(time=0)
@@ -296,7 +296,8 @@ async def test_should_tick_before_popup(self, page: Page) -> None:
page.wait_for_event("popup"), page.evaluate("window.open('about:blank')")
)
popup_time = await popup.evaluate("Date.now()")
- assert popup_time == int(now.timestamp() + 1000)
+ assert popup_time == int(now.timestamp() * 1000 + 1000)
+ assert datetime.datetime.fromtimestamp(popup_time / 1_000).year == 2015
async def test_should_run_time_before_popup(
self, page: Page, server: Server
@@ -331,7 +332,7 @@ async def test_should_not_run_time_before_popup_on_pause(
),
)
await page.clock.install(time=0)
- await page.clock.pause_at(1000)
+ await page.clock.pause_at(1)
await page.goto(server.EMPTY_PAGE)
# Wait for 2 second in real life to check that it is past in popup.
await page.wait_for_timeout(2000)
@@ -350,15 +351,15 @@ async def test_does_not_fake_methods(self, page: Page) -> None:
await page.evaluate("new Promise(f => setTimeout(f, 1))")
async def test_allows_setting_time_multiple_times(self, page: Page) -> None:
- await page.clock.set_fixed_time(100)
+ await page.clock.set_fixed_time(0.1)
assert await page.evaluate("Date.now()") == 100
- await page.clock.set_fixed_time(200)
+ await page.clock.set_fixed_time(0.2)
assert await page.evaluate("Date.now()") == 200
async def test_fixed_time_is_not_affected_by_clock_manipulation(
self, page: Page
) -> None:
- await page.clock.set_fixed_time(100)
+ await page.clock.set_fixed_time(0.1)
assert await page.evaluate("Date.now()") == 100
await page.clock.fast_forward(20)
assert await page.evaluate("Date.now()") == 100
@@ -366,9 +367,9 @@ async def test_fixed_time_is_not_affected_by_clock_manipulation(
async def test_allows_installing_fake_timers_after_setting_time(
self, page: Page, calls: List[Any]
) -> None:
- await page.clock.set_fixed_time(100)
+ await page.clock.set_fixed_time(0.1)
assert await page.evaluate("Date.now()") == 100
- await page.clock.set_fixed_time(200)
+ await page.clock.set_fixed_time(0.2)
await page.evaluate("setTimeout(() => window.stub(Date.now()))")
await page.clock.run_for(0)
assert calls == [[200]]
@@ -406,7 +407,7 @@ async def test_should_fast_forward_to(self, page: Page) -> None:
async def test_should_pause(self, page: Page) -> None:
await page.clock.install(time=0)
await page.goto("data:text/html,")
- await page.clock.pause_at(1000)
+ await page.clock.pause_at(1)
await page.wait_for_timeout(1000)
await page.clock.resume()
now = await page.evaluate("Date.now()")
@@ -415,7 +416,7 @@ async def test_should_pause(self, page: Page) -> None:
async def test_should_pause_and_fast_forward(self, page: Page) -> None:
await page.clock.install(time=0)
await page.goto("data:text/html,")
- await page.clock.pause_at(1000)
+ await page.clock.pause_at(1)
await page.clock.fast_forward(1000)
now = await page.evaluate("Date.now()")
assert now == 2000
@@ -423,7 +424,7 @@ async def test_should_pause_and_fast_forward(self, page: Page) -> None:
async def test_should_set_system_time_on_pause(self, page: Page) -> None:
await page.clock.install(time=0)
await page.goto("data:text/html,")
- await page.clock.pause_at(1000)
+ await page.clock.pause_at(1)
now = await page.evaluate("Date.now()")
assert now == 1000
diff --git a/tests/sync/test_page_clock.py b/tests/sync/test_page_clock.py
index 8759ec49d..025133b57 100644
--- a/tests/sync/test_page_clock.py
+++ b/tests/sync/test_page_clock.py
@@ -146,7 +146,7 @@ class TestFastForward:
@pytest.fixture(autouse=True)
def before_each(self, page: Page) -> Generator[None, None, None]:
page.clock.install(time=0)
- page.clock.pause_at(1000)
+ page.clock.pause_at(1)
yield
def test_ignores_timers_which_wouldnt_be_run(
@@ -177,11 +177,11 @@ class TestStubTimers:
@pytest.fixture(autouse=True)
def before_each(self, page: Page) -> Generator[None, None, None]:
page.clock.install(time=0)
- page.clock.pause_at(1000)
+ page.clock.pause_at(1)
yield
def test_sets_initial_timestamp(self, page: Page) -> None:
- page.clock.set_system_time(1400)
+ page.clock.set_system_time(1.4)
assert page.evaluate("Date.now()") == 1400
def test_replaces_global_setTimeout(self, page: Page, calls: List[Any]) -> None:
@@ -239,8 +239,8 @@ def test_fakes_Date_constructor(self, page: Page) -> None:
class TestStubTimersPerformance:
def test_replaces_global_performance_time_origin(self, page: Page) -> None:
- page.clock.install(time=1000)
- page.clock.pause_at(2000)
+ page.clock.install(time=1)
+ page.clock.pause_at(2)
page.evaluate(
"""() => {
window.waitForPromise = new Promise(async resolve => {
@@ -265,10 +265,10 @@ def test_should_tick_after_popup(self, page: Page) -> None:
page.evaluate("window.open('about:blank')")
popup = popup_info.value
popup_time = popup.evaluate("Date.now()")
- assert popup_time == now.timestamp()
+ assert popup_time == now.timestamp() * 1000
page.clock.run_for(1000)
popup_time_after = popup.evaluate("Date.now()")
- assert popup_time_after == now.timestamp() + 1000
+ assert popup_time_after == now.timestamp() * 1000 + 1000
def test_should_tick_before_popup(self, page: Page) -> None:
page.clock.install(time=0)
@@ -279,7 +279,8 @@ def test_should_tick_before_popup(self, page: Page) -> None:
page.evaluate("window.open('about:blank')")
popup = popup_info.value
popup_time = popup.evaluate("Date.now()")
- assert popup_time == int(now.timestamp() + 1000)
+ assert popup_time == int(now.timestamp() * 1_000 + 1000)
+ assert datetime.datetime.fromtimestamp(popup_time / 1_000).year == 2015
def test_should_run_time_before_popup(self, page: Page, server: Server) -> None:
server.set_route(
@@ -311,7 +312,7 @@ def test_should_not_run_time_before_popup_on_pause(
),
)
page.clock.install(time=0)
- page.clock.pause_at(1000)
+ page.clock.pause_at(1)
page.goto(server.EMPTY_PAGE)
# Wait for 2 second in real life to check that it is past in popup.
page.wait_for_timeout(2000)
@@ -323,19 +324,25 @@ def test_should_not_run_time_before_popup_on_pause(
class TestSetFixedTime:
+ def test_allows_passing_as_int(self, page: Page) -> None:
+ page.clock.set_fixed_time(1)
+ assert page.evaluate("Date.now()") == 1000
+ page.clock.set_fixed_time(int(2))
+ assert page.evaluate("Date.now()") == 2000
+
def test_does_not_fake_methods(self, page: Page) -> None:
page.clock.set_fixed_time(0)
# Should not stall.
page.evaluate("new Promise(f => setTimeout(f, 1))")
def test_allows_setting_time_multiple_times(self, page: Page) -> None:
- page.clock.set_fixed_time(100)
+ page.clock.set_fixed_time(0.1)
assert page.evaluate("Date.now()") == 100
- page.clock.set_fixed_time(200)
+ page.clock.set_fixed_time(0.2)
assert page.evaluate("Date.now()") == 200
def test_fixed_time_is_not_affected_by_clock_manipulation(self, page: Page) -> None:
- page.clock.set_fixed_time(100)
+ page.clock.set_fixed_time(0.1)
assert page.evaluate("Date.now()") == 100
page.clock.fast_forward(20)
assert page.evaluate("Date.now()") == 100
@@ -343,9 +350,9 @@ def test_fixed_time_is_not_affected_by_clock_manipulation(self, page: Page) -> N
def test_allows_installing_fake_timers_after_setting_time(
self, page: Page, calls: List[Any]
) -> None:
- page.clock.set_fixed_time(100)
+ page.clock.set_fixed_time(0.1)
assert page.evaluate("Date.now()") == 100
- page.clock.set_fixed_time(200)
+ page.clock.set_fixed_time(0.2)
page.evaluate("setTimeout(() => window.stub(Date.now()))")
page.clock.run_for(0)
assert calls == [[200]]
@@ -383,7 +390,7 @@ def test_should_fast_forward_to(self, page: Page) -> None:
def test_should_pause(self, page: Page) -> None:
page.clock.install(time=0)
page.goto("data:text/html,")
- page.clock.pause_at(1000)
+ page.clock.pause_at(1)
page.wait_for_timeout(1000)
page.clock.resume()
now = page.evaluate("Date.now()")
@@ -392,7 +399,7 @@ def test_should_pause(self, page: Page) -> None:
def test_should_pause_and_fast_forward(self, page: Page) -> None:
page.clock.install(time=0)
page.goto("data:text/html,")
- page.clock.pause_at(1000)
+ page.clock.pause_at(1)
page.clock.fast_forward(1000)
now = page.evaluate("Date.now()")
assert now == 2000
@@ -400,7 +407,7 @@ def test_should_pause_and_fast_forward(self, page: Page) -> None:
def test_should_set_system_time_on_pause(self, page: Page) -> None:
page.clock.install(time=0)
page.goto("data:text/html,")
- page.clock.pause_at(1000)
+ page.clock.pause_at(1)
now = page.evaluate("Date.now()")
assert now == 1000