Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 35 additions & 0 deletions py/selenium/webdriver/common/bidi/emulation.py
Original file line number Diff line number Diff line change
Expand Up @@ -215,3 +215,38 @@ def set_geolocation_override(
params["userContexts"] = user_contexts

self.conn.execute(command_builder("emulation.setGeolocationOverride", params))

def set_timezone_override(
self,
timezone: Optional[str] = None,
contexts: Optional[list[str]] = None,
user_contexts: Optional[list[str]] = None,
) -> None:
"""Set timezone override for the given contexts or user contexts.

Parameters:
-----------
timezone: Timezone identifier (IANA timezone name or offset string like '+01:00'),
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.
"""
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] = {"timezone": timezone}

if contexts is not None:
params["contexts"] = contexts
elif user_contexts is not None:
params["userContexts"] = user_contexts

self.conn.execute(command_builder("emulation.setTimezoneOverride", params))
79 changes: 79 additions & 0 deletions py/test/selenium/webdriver/common/bidi_emulation_tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,22 @@
from selenium.webdriver.common.window import WindowTypes


def get_browser_timezone_string(driver):
result = driver.script._evaluate(
"Intl.DateTimeFormat().resolvedOptions().timeZone",
{"context": driver.current_window_handle},
await_promise=False,
)
return result.result["value"]


def get_browser_timezone_offset(driver):
result = driver.script._evaluate(
"new Date().getTimezoneOffset()", {"context": driver.current_window_handle}, await_promise=False
)
return result.result["value"]


def get_browser_geolocation(driver, user_context=None):
origin = driver.execute_script("return window.location.origin;")
driver.permissions.set_permission("geolocation", PermissionState.GRANTED, origin, user_context=user_context)
Expand Down Expand Up @@ -214,3 +230,66 @@ def test_set_geolocation_override_with_error(driver, pages):

result = get_browser_geolocation(driver)
assert "error" in result, f"Expected geolocation error, got: {result}"


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")

initial_timezone_string = get_browser_timezone_string(driver)

# Set timezone to Tokyo (UTC+9)
driver.emulation.set_timezone_override(timezone="Asia/Tokyo", contexts=[context_id])

timezone_offset = get_browser_timezone_offset(driver)
timezone_string = get_browser_timezone_string(driver)

# Tokyo is UTC+9, so the offset should be -540 minutes (negative because it's ahead of UTC)
assert timezone_offset == -540, f"Expected timezone offset -540, got: {timezone_offset}"
assert timezone_string == "Asia/Tokyo", f"Expected timezone 'Asia/Tokyo', got: {timezone_string}"

# Clear the timezone override
driver.emulation.set_timezone_override(timezone=None, contexts=[context_id])

# verify setting timezone to None clears the timezone override
timezone_after_clear_with_none = get_browser_timezone_string(driver)
assert timezone_after_clear_with_none == initial_timezone_string


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)

driver.switch_to.window(context_id)
pages.load("blank.html")

driver.emulation.set_timezone_override(timezone="America/New_York", user_contexts=[user_context])

timezone_string = get_browser_timezone_string(driver)
assert timezone_string == "America/New_York", f"Expected timezone 'America/New_York', got: {timezone_string}"

driver.emulation.set_timezone_override(timezone=None, user_contexts=[user_context])

driver.browsing_context.close(context_id)
driver.browser.remove_user_context(user_context)


@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")

# set timezone to India (UTC+05:30) using offset
driver.emulation.set_timezone_override(timezone="+05:30", contexts=[context_id])

timezone_offset = get_browser_timezone_offset(driver)
timezone_string = get_browser_timezone_string(driver)

# India is UTC+05:30, so the offset should be -330 minutes (negative because it's ahead of UTC)
assert timezone_offset == -330, f"Expected timezone offset -540, got: {timezone_offset}"
assert timezone_string == "+05:30", f"Expected timezone '+05:30', got: {timezone_string}"

driver.emulation.set_timezone_override(timezone=None, contexts=[context_id])