Skip to content

Commit 8cf788f

Browse files
authored
[py][bidi]: add unhandled_prompt_behavior param for create_user_context (#16112)
1 parent 7407515 commit 8cf788f

File tree

3 files changed

+123
-3
lines changed

3 files changed

+123
-3
lines changed

py/selenium/webdriver/common/bidi/browser.py

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,10 @@
1616
# under the License.
1717

1818

19-
from typing import Optional
19+
from typing import Any, Optional
2020

2121
from selenium.webdriver.common.bidi.common import command_builder
22+
from selenium.webdriver.common.bidi.session import UserPromptHandler
2223
from selenium.webdriver.common.proxy import Proxy
2324

2425

@@ -185,26 +186,35 @@ class Browser:
185186
def __init__(self, conn):
186187
self.conn = conn
187188

188-
def create_user_context(self, accept_insecure_certs: Optional[bool] = None, proxy: Optional[Proxy] = None) -> str:
189+
def create_user_context(
190+
self,
191+
accept_insecure_certs: Optional[bool] = None,
192+
proxy: Optional[Proxy] = None,
193+
unhandled_prompt_behavior: Optional[UserPromptHandler] = None,
194+
) -> str:
189195
"""Creates a new user context.
190196
191197
Parameters:
192198
-----------
193199
accept_insecure_certs: Optional flag to accept insecure TLS certificates
194200
proxy: Optional proxy configuration for the user context
201+
unhandled_prompt_behavior: Optional configuration for handling user prompts
195202
196203
Returns:
197204
-------
198205
str: The ID of the created user context.
199206
"""
200-
params = {}
207+
params: dict[str, Any] = {}
201208

202209
if accept_insecure_certs is not None:
203210
params["acceptInsecureCerts"] = accept_insecure_certs
204211

205212
if proxy is not None:
206213
params["proxy"] = proxy.to_bidi_dict()
207214

215+
if unhandled_prompt_behavior is not None:
216+
params["unhandledPromptBehavior"] = unhandled_prompt_behavior.to_dict()
217+
208218
result = self.conn.execute(command_builder("browser.createUserContext", params))
209219
return result["userContext"]
210220

py/selenium/webdriver/common/bidi/session.py

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,92 @@
1515
# specific language governing permissions and limitations
1616
# under the License.
1717

18+
from typing import Dict, Optional
19+
1820
from selenium.webdriver.common.bidi.common import command_builder
1921

2022

23+
class UserPromptHandlerType:
24+
"""Represents the behavior of the user prompt handler."""
25+
26+
ACCEPT = "accept"
27+
DISMISS = "dismiss"
28+
IGNORE = "ignore"
29+
30+
VALID_TYPES = {ACCEPT, DISMISS, IGNORE}
31+
32+
33+
class UserPromptHandler:
34+
"""Represents the configuration of the user prompt handler."""
35+
36+
def __init__(
37+
self,
38+
alert: Optional[str] = None,
39+
before_unload: Optional[str] = None,
40+
confirm: Optional[str] = None,
41+
default: Optional[str] = None,
42+
file: Optional[str] = None,
43+
prompt: Optional[str] = None,
44+
):
45+
"""Initialize UserPromptHandler.
46+
47+
Parameters:
48+
-----------
49+
alert: Handler type for alert prompts
50+
before_unload: Handler type for beforeUnload prompts
51+
confirm: Handler type for confirm prompts
52+
default: Default handler type for all prompts
53+
file: Handler type for file picker prompts
54+
prompt: Handler type for prompt dialogs
55+
56+
Raises:
57+
------
58+
ValueError: If any handler type is not valid
59+
"""
60+
for field_name, value in [
61+
("alert", alert),
62+
("before_unload", before_unload),
63+
("confirm", confirm),
64+
("default", default),
65+
("file", file),
66+
("prompt", prompt),
67+
]:
68+
if value is not None and value not in UserPromptHandlerType.VALID_TYPES:
69+
raise ValueError(
70+
f"Invalid {field_name} handler type: {value}. Must be one of {UserPromptHandlerType.VALID_TYPES}"
71+
)
72+
73+
self.alert = alert
74+
self.before_unload = before_unload
75+
self.confirm = confirm
76+
self.default = default
77+
self.file = file
78+
self.prompt = prompt
79+
80+
def to_dict(self) -> Dict[str, str]:
81+
"""Convert the UserPromptHandler to a dictionary for BiDi protocol.
82+
83+
Returns:
84+
-------
85+
Dict[str, str]: Dictionary representation suitable for BiDi protocol
86+
"""
87+
field_mapping = {
88+
"alert": "alert",
89+
"before_unload": "beforeUnload",
90+
"confirm": "confirm",
91+
"default": "default",
92+
"file": "file",
93+
"prompt": "prompt",
94+
}
95+
96+
result = {}
97+
for attr_name, dict_key in field_mapping.items():
98+
value = getattr(self, attr_name)
99+
if value is not None:
100+
result[dict_key] = value
101+
return result
102+
103+
21104
class Session:
22105
def __init__(self, conn):
23106
self.conn = conn

py/test/selenium/webdriver/common/bidi_browser_tests.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import pytest
2323

2424
from selenium.webdriver.common.bidi.browser import ClientWindowInfo, ClientWindowState
25+
from selenium.webdriver.common.bidi.session import UserPromptHandler, UserPromptHandlerType
2526
from selenium.webdriver.common.by import By
2627
from selenium.webdriver.common.proxy import Proxy, ProxyType
2728
from selenium.webdriver.common.utils import free_port
@@ -235,3 +236,29 @@ def test_create_user_context_with_proxy_and_accept_insecure_certs(driver):
235236
driver.browser.remove_user_context(user_context)
236237
fake_proxy_server.shutdown()
237238
fake_proxy_server.server_close()
239+
240+
241+
def test_create_user_context_with_unhandled_prompt_behavior(driver, pages):
242+
"""Test creating a user context with unhandled prompt behavior configuration."""
243+
prompt_handler = UserPromptHandler(
244+
alert=UserPromptHandlerType.DISMISS, default=UserPromptHandlerType.DISMISS, prompt=UserPromptHandlerType.DISMISS
245+
)
246+
247+
user_context = driver.browser.create_user_context(unhandled_prompt_behavior=prompt_handler)
248+
assert user_context is not None
249+
250+
# create a new browsing context with the user context
251+
bc = driver.browsing_context.create(type=WindowTypes.WINDOW, user_context=user_context)
252+
assert bc is not None
253+
254+
driver.switch_to.window(bc)
255+
pages.load("alerts.html")
256+
257+
# TODO: trigger an alert and test that it is dismissed automatically, currently not working,
258+
# conftest.py unhandled_prompt_behavior set to IGNORE, see if it is related
259+
# driver.find_element(By.ID, "alert").click()
260+
# # accessing title should be possible since alert is auto handled
261+
# assert driver.title == "Testing Alerts"
262+
263+
# Clean up
264+
driver.browser.remove_user_context(user_context)

0 commit comments

Comments
 (0)