diff --git a/py/selenium/webdriver/common/bidi/browsing_context.py b/py/selenium/webdriver/common/bidi/browsing_context.py index 403e10b87d539..696a4f73bbb5f 100644 --- a/py/selenium/webdriver/common/bidi/browsing_context.py +++ b/py/selenium/webdriver/common/bidi/browsing_context.py @@ -20,9 +20,13 @@ from dataclasses import dataclass from typing import Any +from typing_extensions import Sentinel + from selenium.webdriver.common.bidi.common import command_builder from selenium.webdriver.common.bidi.session import Session +UNDEFINED = Sentinel("UNDEFINED") + class ReadinessState: """Represents the stage of document loading at which a navigation command will return.""" @@ -980,30 +984,38 @@ def reload( def set_viewport( self, context: str | None = None, - viewport: dict | None = None, - device_pixel_ratio: float | None = None, + viewport: dict | None | UNDEFINED = UNDEFINED, + device_pixel_ratio: float | None | UNDEFINED = UNDEFINED, user_contexts: list[str] | None = None, ) -> None: """Modifies specific viewport characteristics on the given top-level traversable. Args: context: The browsing context ID. - viewport: The viewport parameters. - device_pixel_ratio: The device pixel ratio. + viewport: The viewport parameters - {"width": , "height": } (`None` resets to default). + device_pixel_ratio: The device pixel ratio (`None` resets to default). user_contexts: The user context IDs. Raises: - Exception: If the browsing context is not a top-level traversable. + Exception: If the browsing context is not a top-level traversable + ValueError: If neither `context` nor `user_contexts` is provided + ValueError: If both `context` and `user_contexts` are provided """ + if context is not None and user_contexts is not None: + raise ValueError("Cannot specify both context and user_contexts") + + if context is None and user_contexts is None: + raise ValueError("Must specify either context or user_contexts") + params: dict[str, Any] = {} if context is not None: params["context"] = context - if viewport is not None: + elif user_contexts is not None: + params["userContexts"] = user_contexts + if viewport is not UNDEFINED: params["viewport"] = viewport - if device_pixel_ratio is not None: + if device_pixel_ratio is not UNDEFINED: params["devicePixelRatio"] = device_pixel_ratio - if user_contexts is not None: - params["userContexts"] = user_contexts self.conn.execute(command_builder("browsingContext.setViewport", params)) diff --git a/py/test/selenium/webdriver/common/bidi_browsing_context_tests.py b/py/test/selenium/webdriver/common/bidi_browsing_context_tests.py index fb9941582a395..c5c9284418ba2 100644 --- a/py/test/selenium/webdriver/common/bidi_browsing_context_tests.py +++ b/py/test/selenium/webdriver/common/bidi_browsing_context_tests.py @@ -348,12 +348,15 @@ def test_set_viewport(driver, pages): context_id = driver.current_window_handle driver.get(pages.url("formPage.html")) - driver.browsing_context.set_viewport(context=context_id, viewport={"width": 250, "height": 300}) + try: + driver.browsing_context.set_viewport(context=context_id, viewport={"width": 251, "height": 301}) - viewport_size = driver.execute_script("return [window.innerWidth, window.innerHeight];") + viewport_size = driver.execute_script("return [window.innerWidth, window.innerHeight];") - assert viewport_size[0] == 250 - assert viewport_size[1] == 300 + assert viewport_size[0] == 251 + assert viewport_size[1] == 301 + finally: + driver.browsing_context.set_viewport(context=context_id, viewport=None, device_pixel_ratio=None) def test_set_viewport_with_device_pixel_ratio(driver, pages): @@ -361,18 +364,70 @@ def test_set_viewport_with_device_pixel_ratio(driver, pages): context_id = driver.current_window_handle driver.get(pages.url("formPage.html")) - driver.browsing_context.set_viewport( - context=context_id, viewport={"width": 250, "height": 300}, device_pixel_ratio=5 - ) + try: + driver.browsing_context.set_viewport( + context=context_id, viewport={"width": 252, "height": 302}, device_pixel_ratio=5 + ) + + viewport_size = driver.execute_script("return [window.innerWidth, window.innerHeight];") + + assert viewport_size[0] == 252 + assert viewport_size[1] == 302 + + device_pixel_ratio = driver.execute_script("return window.devicePixelRatio") + + assert device_pixel_ratio == 5 + finally: + driver.browsing_context.set_viewport(context=context_id, viewport=None, device_pixel_ratio=None) + + +def test_set_viewport_with_no_args_doesnt_change_values(driver, pages): + """Test setting the viewport with no args doesn't change viewport or device pixel ratio.""" + context_id = driver.current_window_handle + driver.get(pages.url("formPage.html")) + + try: + driver.browsing_context.set_viewport( + context=context_id, viewport={"width": 253, "height": 303}, device_pixel_ratio=6 + ) + + driver.browsing_context.set_viewport(context=context_id) + + viewport_size = driver.execute_script("return [window.innerWidth, window.innerHeight];") + + assert viewport_size[0] == 253 + assert viewport_size[1] == 303 + + device_pixel_ratio = driver.execute_script("return window.devicePixelRatio") + + assert device_pixel_ratio == 6 + finally: + driver.browsing_context.set_viewport(context=context_id, viewport=None, device_pixel_ratio=None) - viewport_size = driver.execute_script("return [window.innerWidth, window.innerHeight];") - assert viewport_size[0] == 250 - assert viewport_size[1] == 300 +def test_set_viewport_back_to_default(driver, pages): + """Test resetting the viewport and device pixel ratio to defaults.""" + context_id = driver.current_window_handle + driver.get(pages.url("formPage.html")) + + default_viewport_size = driver.execute_script("return [window.innerWidth, window.innerHeight];") + default_device_pixel_ratio = driver.execute_script("return window.devicePixelRatio") + + try: + driver.browsing_context.set_viewport( + context=context_id, viewport={"width": 254, "height": 304}, device_pixel_ratio=10 + ) + + driver.browsing_context.set_viewport(context=context_id, viewport=None, device_pixel_ratio=None) - device_pixel_ratio = driver.execute_script("return window.devicePixelRatio") + viewport_size = driver.execute_script("return [window.innerWidth, window.innerHeight];") + device_pixel_ratio = driver.execute_script("return window.devicePixelRatio") - assert device_pixel_ratio == 5 + assert viewport_size[0] == default_viewport_size[0] + assert viewport_size[1] == default_viewport_size[1] + assert device_pixel_ratio == default_device_pixel_ratio + finally: + driver.browsing_context.set_viewport(context=context_id, viewport=None, device_pixel_ratio=None) def test_print_page(driver, pages):