diff --git a/py/selenium/webdriver/common/bidi/emulation.py b/py/selenium/webdriver/common/bidi/emulation.py index c158ad5b936ae..15bfab1de5ebc 100644 --- a/py/selenium/webdriver/common/bidi/emulation.py +++ b/py/selenium/webdriver/common/bidi/emulation.py @@ -431,3 +431,41 @@ def set_user_agent_override( params["userContexts"] = user_contexts self.conn.execute(command_builder("emulation.setUserAgentOverride", params)) + + def set_network_conditions( + self, + offline: bool | None = None, + contexts: list[str] | None = None, + user_contexts: list[str] | None = None, + ) -> None: + """Set network conditions for the given contexts or user contexts. + + Args: + offline: True to emulate offline network conditions, False or None to disable. + contexts: List of browsing context IDs to apply the conditions to. + user_contexts: List of user context IDs to apply the conditions to. + + Raises: + ValueError: If both contexts and user_contexts are provided, or if neither + contexts nor user_contexts are provided. + """ + if contexts is not None and user_contexts is not None: + raise ValueError("Cannot specify both contexts and user_contexts") + + if contexts is None and user_contexts is None: + raise ValueError("Must specify either contexts or user_contexts") + + params: dict[str, Any] = {} + + if offline: + params["networkConditions"] = {"type": "offline"} + else: + # if offline is False or None, then clear the override + params["networkConditions"] = None + + if contexts is not None: + params["contexts"] = contexts + elif user_contexts is not None: + params["userContexts"] = user_contexts + + self.conn.execute(command_builder("emulation.setNetworkConditions", params)) diff --git a/py/test/selenium/webdriver/common/bidi_emulation_tests.py b/py/test/selenium/webdriver/common/bidi_emulation_tests.py index 60a56cdf6dbc1..f6bb3a56e33d8 100644 --- a/py/test/selenium/webdriver/common/bidi_emulation_tests.py +++ b/py/test/selenium/webdriver/common/bidi_emulation_tests.py @@ -107,6 +107,11 @@ def get_browser_user_agent(driver): return result.result["value"] +def is_online(driver, context_id): + result = driver.script._evaluate("navigator.onLine", {"context": context_id}, await_promise=False) + return result.result["value"] + + def test_emulation_initialized(driver): assert driver.emulation is not None assert isinstance(driver.emulation, Emulation) @@ -574,3 +579,46 @@ def test_set_user_agent_override_with_user_contexts(driver, pages): driver.browsing_context.close(context_id) finally: driver.browser.remove_user_context(user_context) + + +@pytest.mark.xfail_firefox +@pytest.mark.xfail_edge +def test_set_network_conditions_offline_with_context(driver, pages): + context_id = driver.current_window_handle + driver.browsing_context.navigate(context_id, pages.url("formPage.html"), wait="complete") + + assert is_online(driver, context_id) is True + + # Set offline + driver.emulation.set_network_conditions(offline=True, contexts=[context_id]) + assert is_online(driver, context_id) is False + + # Reset + driver.emulation.set_network_conditions(offline=None, contexts=[context_id]) + assert is_online(driver, context_id) is True + + +@pytest.mark.xfail_firefox +@pytest.mark.xfail_edge +def test_set_network_conditions_offline_with_user_context(driver, pages): + user_context = driver.browser.create_user_context() + try: + context_id = driver.browsing_context.create( + type=WindowTypes.TAB, + user_context=user_context, + ) + try: + driver.switch_to.window(context_id) + driver.browsing_context.navigate(context_id, pages.url("formPage.html"), wait="complete") + + assert is_online(driver, context_id) is True + + driver.emulation.set_network_conditions(offline=True, user_contexts=[user_context]) + assert is_online(driver, context_id) is False + + driver.emulation.set_network_conditions(offline=None, user_contexts=[user_context]) + assert is_online(driver, context_id) is True + finally: + driver.browsing_context.close(context_id) + finally: + driver.browser.remove_user_context(user_context)