diff --git a/py/selenium/webdriver/common/bidi/emulation.py b/py/selenium/webdriver/common/bidi/emulation.py
index 85cd48422229b..9dbc585559aed 100644
--- a/py/selenium/webdriver/common/bidi/emulation.py
+++ b/py/selenium/webdriver/common/bidi/emulation.py
@@ -35,8 +35,7 @@ def __init__(
):
"""Initialize GeolocationCoordinates.
- Parameters:
- -----------
+ Args:
latitude: Latitude coordinate (-90.0 to 90.0).
longitude: Longitude coordinate (-180.0 to 180.0).
accuracy: Accuracy in meters (>= 0.0), defaults to 1.0.
@@ -46,7 +45,6 @@ def __init__(
speed: Speed in meters per second (>= 0.0) or None, defaults to None.
Raises:
- ------
ValueError: If coordinates are out of valid range or if altitude_accuracy is provided without altitude.
"""
self.latitude = latitude
@@ -180,18 +178,16 @@ def set_geolocation_override(
) -> None:
"""Set geolocation override for the given contexts or user contexts.
- Parameters:
- -----------
+ Args:
coordinates: Geolocation coordinates to emulate, or None.
error: Geolocation error to emulate, or None.
contexts: List of browsing context IDs to apply the override to.
user_contexts: List of user context IDs to apply the override to.
Raises:
- ------
ValueError: If both coordinates and error are provided, or if both contexts
- and user_contexts are provided, or if neither contexts nor
- user_contexts are provided.
+ and user_contexts are provided, or if neither contexts nor
+ user_contexts are provided.
"""
if coordinates is not None and error is not None:
raise ValueError("Cannot specify both coordinates and error")
@@ -224,17 +220,15 @@ def set_timezone_override(
) -> None:
"""Set timezone override for the given contexts or user contexts.
- Parameters:
- -----------
+ Args:
timezone: Timezone identifier (IANA timezone name or offset string like '+01:00'),
- or None to clear the override.
+ or None to clear the override.
contexts: List of browsing context IDs to apply the override to.
user_contexts: List of user context IDs to apply the override to.
Raises:
- ------
ValueError: If both contexts and user_contexts are provided, or if neither
- contexts nor user_contexts are provided.
+ 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")
@@ -259,16 +253,14 @@ def set_locale_override(
) -> None:
"""Set locale override for the given contexts or user contexts.
- Parameters:
- -----------
+ Args:
locale: Locale string as per BCP 47, or None to clear override.
contexts: List of browsing context IDs to apply the override to.
user_contexts: List of user context IDs to apply the override to.
Raises:
- ------
ValueError: If both contexts and user_contexts are provided, or if neither
- contexts nor user_contexts are provided, or if locale is invalid.
+ contexts nor user_contexts are provided, or if locale is invalid.
"""
if contexts is not None and user_contexts is not None:
raise ValueError("Cannot specify both contexts and userContexts")
@@ -284,3 +276,39 @@ def set_locale_override(
params["userContexts"] = user_contexts
self.conn.execute(command_builder("emulation.setLocaleOverride", params))
+
+ def set_scripting_enabled(
+ self,
+ enabled: Union[bool, None] = False,
+ contexts: Optional[list[str]] = None,
+ user_contexts: Optional[list[str]] = None,
+ ) -> None:
+ """Set scripting enabled override for the given contexts or user contexts.
+
+ Args:
+ enabled: False to disable scripting, None to clear the override.
+ Note: Only emulation of disabled JavaScript is supported.
+ contexts: List of browsing context IDs to apply the override to.
+ user_contexts: List of user context IDs to apply the override to.
+
+ Raises:
+ ValueError: If both contexts and user_contexts are provided, or if neither
+ contexts nor user_contexts are provided, or if enabled is True.
+ """
+ if enabled:
+ raise ValueError("Only emulation of disabled JavaScript is supported (enabled must be False or None)")
+
+ if contexts is not None and user_contexts is not None:
+ raise ValueError("Cannot specify both contexts and userContexts")
+
+ if contexts is None and user_contexts is None:
+ raise ValueError("Must specify either contexts or userContexts")
+
+ params: dict[str, Any] = {"enabled": enabled}
+
+ if contexts is not None:
+ params["contexts"] = contexts
+ elif user_contexts is not None:
+ params["userContexts"] = user_contexts
+
+ self.conn.execute(command_builder("emulation.setScriptingEnabled", params))
diff --git a/py/test/selenium/webdriver/common/bidi_emulation_tests.py b/py/test/selenium/webdriver/common/bidi_emulation_tests.py
index 01705b0ae3c6f..49c74ea9ec32a 100644
--- a/py/test/selenium/webdriver/common/bidi_emulation_tests.py
+++ b/py/test/selenium/webdriver/common/bidi_emulation_tests.py
@@ -74,13 +74,11 @@ def get_browser_locale(driver):
def test_emulation_initialized(driver):
- """Test that the emulation module is initialized properly."""
assert driver.emulation is not None
assert isinstance(driver.emulation, Emulation)
def test_set_geolocation_override_with_coordinates_in_context(driver, pages):
- """Test setting geolocation override with coordinates."""
context_id = driver.current_window_handle
pages.load("blank.html")
coords = GeolocationCoordinates(45.5, -122.4194, accuracy=10.0)
@@ -96,7 +94,6 @@ def test_set_geolocation_override_with_coordinates_in_context(driver, pages):
def test_set_geolocation_override_with_coordinates_in_user_context(driver, pages):
- """Test setting geolocation override with coordinates in a user context."""
# Create a user context
user_context = driver.browser.create_user_context()
@@ -121,7 +118,6 @@ def test_set_geolocation_override_with_coordinates_in_user_context(driver, pages
def test_set_geolocation_override_all_coords(driver, pages):
- """Test setting geolocation override with coordinates."""
context_id = driver.current_window_handle
pages.load("blank.html")
coords = GeolocationCoordinates(
@@ -147,7 +143,6 @@ def test_set_geolocation_override_all_coords(driver, pages):
def test_set_geolocation_override_with_multiple_contexts(driver, pages):
- """Test setting geolocation override with multiple browsing contexts."""
# Create two browsing contexts
context1_id = driver.browsing_context.create(type=WindowTypes.TAB)
context2_id = driver.browsing_context.create(type=WindowTypes.TAB)
@@ -181,7 +176,6 @@ def test_set_geolocation_override_with_multiple_contexts(driver, pages):
def test_set_geolocation_override_with_multiple_user_contexts(driver, pages):
- """Test setting geolocation override with multiple user contexts."""
# Create two user contexts
user_context1 = driver.browser.create_user_context()
user_context2 = driver.browser.create_user_context()
@@ -229,7 +223,6 @@ def test_set_geolocation_override_with_multiple_user_contexts(driver, pages):
@pytest.mark.xfail_firefox
def test_set_geolocation_override_with_error(driver, pages):
- """Test setting geolocation override with error."""
context_id = driver.current_window_handle
pages.load("blank.html")
@@ -242,7 +235,6 @@ def test_set_geolocation_override_with_error(driver, pages):
def test_set_timezone_override_with_context(driver, pages):
- """Test setting timezone override with a browsing context."""
context_id = driver.current_window_handle
pages.load("blank.html")
@@ -267,7 +259,6 @@ def test_set_timezone_override_with_context(driver, pages):
def test_set_timezone_override_with_user_context(driver, pages):
- """Test setting timezone override with a user context."""
user_context = driver.browser.create_user_context()
context_id = driver.browsing_context.create(type=WindowTypes.TAB, user_context=user_context)
@@ -287,7 +278,6 @@ def test_set_timezone_override_with_user_context(driver, pages):
@pytest.mark.xfail_firefox(reason="Firefox returns UTC as timezone string in case of offset.")
def test_set_timezone_override_using_offset(driver, pages):
- """Test setting timezone override using offset."""
context_id = driver.current_window_handle
pages.load("blank.html")
@@ -320,7 +310,6 @@ def test_set_timezone_override_using_offset(driver, pages):
],
)
def test_set_locale_override_with_contexts(driver, pages, locale, expected_locale):
- """Test setting locale override with browsing contexts."""
context_id = driver.current_window_handle
driver.emulation.set_locale_override(locale=locale, contexts=[context_id])
@@ -345,7 +334,6 @@ def test_set_locale_override_with_contexts(driver, pages, locale, expected_local
],
)
def test_set_locale_override_with_user_contexts(driver, pages, value):
- """Test setting locale override with user contexts."""
user_context = driver.browser.create_user_context()
try:
context_id = driver.browsing_context.create(type=WindowTypes.TAB, user_context=user_context)
@@ -362,3 +350,72 @@ def test_set_locale_override_with_user_contexts(driver, pages, value):
driver.browsing_context.close(context_id)
finally:
driver.browser.remove_user_context(user_context)
+
+
+@pytest.mark.xfail_firefox(reason="Not yet supported")
+def test_set_scripting_enabled_with_contexts(driver, pages):
+ context_id = driver.current_window_handle
+
+ # disable scripting
+ driver.emulation.set_scripting_enabled(enabled=False, contexts=[context_id])
+
+ driver.browsing_context.navigate(
+ context=context_id,
+ url="data:text/html,",
+ wait="complete",
+ )
+ result = driver.script._evaluate("'foo' in window", {"context": context_id}, await_promise=False)
+ assert result.result["value"] is False, "Page script should not have executed when scripting is disabled"
+
+ # clear override via None to restore JS
+ driver.emulation.set_scripting_enabled(enabled=None, contexts=[context_id])
+ driver.browsing_context.navigate(
+ context=context_id,
+ url="data:text/html,",
+ wait="complete",
+ )
+ result = driver.script._evaluate("'foo' in window", {"context": context_id}, await_promise=False)
+ assert result.result["value"] is True, "Page script should execute after clearing the override"
+
+
+@pytest.mark.xfail_firefox(reason="Not yet supported")
+def test_set_scripting_enabled_with_user_contexts(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.emulation.set_scripting_enabled(enabled=False, user_contexts=[user_context])
+
+ url = pages.url("javascriptPage.html")
+ driver.browsing_context.navigate(context_id, url, wait="complete")
+
+ # Check that inline event handlers don't work; this page has an onclick handler
+ click_field = driver.find_element("id", "clickField")
+ initial_value = click_field.get_attribute("value") # initial value is 'Hello'
+ click_field.click()
+
+ # Get the value after click, it should remain unchanged if scripting is disabled
+ result_value = driver.script._evaluate(
+ "document.getElementById('clickField').value", {"context": context_id}, await_promise=False
+ )
+ assert result_value.result["value"] == initial_value, (
+ "Inline onclick handler should not execute, i.e, value should not change to 'clicked'"
+ )
+
+ # Clear the scripting override
+ driver.emulation.set_scripting_enabled(enabled=None, user_contexts=[user_context])
+
+ driver.browsing_context.navigate(context_id, url, wait="complete")
+
+ # Click the element again, it should change to 'Clicked' now
+ driver.find_element("id", "clickField").click()
+ result_value = driver.script._evaluate(
+ "document.getElementById('clickField').value", {"context": context_id}, await_promise=False
+ )
+ assert result_value.result["value"] == "Clicked"
+ finally:
+ driver.browsing_context.close(context_id)
+ finally:
+ driver.browser.remove_user_context(user_context)