Skip to content

Commit 2d15bea

Browse files
[WebDriver BiDi] Add tests for browsingContext.close for promptUnload (#44004)
* [WebDriver BiDi] Add tests for `browsingContext.close` for `promptUnload` * fix * chore: address comments * chore: add more tests * chore: add safe to prevent file timeouts * chore: listen if the event is emitted * chore: fix python * chore: simplify * chore: fix * Update webdriver/tests/bidi/browsing_context/close/prompt_unload.py Co-authored-by: Henrik Skupin <[email protected]> * chore: format --------- Co-authored-by: Henrik Skupin <[email protected]>
1 parent 01d277c commit 2d15bea

File tree

3 files changed

+112
-2
lines changed

3 files changed

+112
-2
lines changed

tools/webdriver/webdriver/bidi/modules/browsing_context.py

+3-2
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
from ..undefined import UNDEFINED, Undefined
88

99

10-
1110
class ElementOptions(Dict[str, Any]):
1211
def __init__(self, element: Mapping[str, Any]):
1312
self["type"] = "element"
@@ -69,11 +68,13 @@ def _capture_screenshot(self, result: Mapping[str, Any]) -> bytes:
6968
return base64.b64decode(result["data"])
7069

7170
@command
72-
def close(self, context: Optional[str] = None) -> Mapping[str, Any]:
71+
def close(self, context: Optional[str] = None, prompt_unload: Optional[bool] = None) -> Mapping[str, Any]:
7372
params: MutableMapping[str, Any] = {}
7473

7574
if context is not None:
7675
params["context"] = context
76+
if prompt_unload is not None:
77+
params["promptUnload"] = prompt_unload
7778

7879
return params
7980

webdriver/tests/bidi/browsing_context/close/invalid.py

+6
Original file line numberDiff line numberDiff line change
@@ -29,3 +29,9 @@ async def test_child_context(bidi_session, test_page_same_origin_frame, top_cont
2929

3030
with pytest.raises(error.InvalidArgumentException):
3131
await bidi_session.browsing_context.close(context=child_info["context"])
32+
33+
34+
@pytest.mark.parametrize("value", ["", 42, {}, []])
35+
async def test_params_prompt_unload_invalid_type(bidi_session, top_context, value):
36+
with pytest.raises(error.InvalidArgumentException):
37+
await bidi_session.browsing_context.close(context=top_context["context"], prompt_unload=value)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
import pytest
2+
import asyncio
3+
4+
from webdriver.bidi.modules.script import ContextTarget
5+
6+
pytestmark = pytest.mark.asyncio
7+
8+
CONTEXT_DESTROYED_EVENT = "browsingContext.contextDestroyed"
9+
USER_PROMPT_OPENED_EVENT = "browsingContext.userPromptOpened"
10+
11+
12+
@pytest.mark.parametrize("type_hint", ["window", "tab"])
13+
@pytest.mark.parametrize("prompt_unload", [None, False])
14+
async def test_prompt_unload_not_triggering_dialog(
15+
bidi_session,
16+
subscribe_events,
17+
setup_beforeunload_page,
18+
wait_for_event,
19+
wait_for_future_safe,
20+
type_hint,
21+
prompt_unload,
22+
):
23+
24+
new_context = await bidi_session.browsing_context.create(type_hint=type_hint)
25+
26+
# Set up event listener to make sure the "beforeunload" event is not emitted
27+
await subscribe_events([USER_PROMPT_OPENED_EVENT, CONTEXT_DESTROYED_EVENT])
28+
# Track all received browsingContext.userPromptOpened events in the events array
29+
events = []
30+
31+
async def on_event(method, data):
32+
if method == USER_PROMPT_OPENED_EVENT:
33+
events.append(data)
34+
35+
remove_listener = bidi_session.add_event_listener(
36+
USER_PROMPT_OPENED_EVENT, on_event
37+
)
38+
39+
await setup_beforeunload_page(new_context)
40+
41+
on_context_destroyed = wait_for_event(CONTEXT_DESTROYED_EVENT)
42+
43+
await bidi_session.browsing_context.close(
44+
context=new_context["context"], prompt_unload=prompt_unload
45+
)
46+
47+
await wait_for_future_safe(on_context_destroyed)
48+
49+
assert events == []
50+
51+
remove_listener()
52+
53+
54+
@pytest.mark.parametrize("type_hint", ["window", "tab"])
55+
async def test_prompt_unload_triggering_dialog(
56+
bidi_session,
57+
setup_beforeunload_page,
58+
subscribe_events,
59+
wait_for_event,
60+
wait_for_future_safe,
61+
type_hint,
62+
):
63+
64+
new_context = await bidi_session.browsing_context.create(type_hint=type_hint)
65+
66+
# Set up event listener to make sure the "beforeunload" event is not emitted
67+
await subscribe_events([USER_PROMPT_OPENED_EVENT, CONTEXT_DESTROYED_EVENT])
68+
user_prompt_opened = wait_for_event(USER_PROMPT_OPENED_EVENT)
69+
70+
# Track all received browsingContext.contextDestroyed events in the events array
71+
events = []
72+
73+
async def on_event(_, data):
74+
if data["type"] == CONTEXT_DESTROYED_EVENT:
75+
events.append(data)
76+
77+
remove_listener = bidi_session.add_event_listener(
78+
CONTEXT_DESTROYED_EVENT, on_event)
79+
80+
await setup_beforeunload_page(new_context)
81+
82+
close_task = asyncio.create_task(
83+
bidi_session.browsing_context.close(
84+
context=new_context["context"], prompt_unload=True
85+
)
86+
)
87+
88+
await wait_for_future_safe(user_prompt_opened)
89+
90+
# Events that come after the handling are OK
91+
remove_listener()
92+
assert events == []
93+
94+
await bidi_session.browsing_context.handle_user_prompt(
95+
context=new_context["context"],
96+
)
97+
98+
await close_task
99+
100+
contexts = await bidi_session.browsing_context.get_tree()
101+
assert len(contexts) == 1
102+
103+
assert contexts[0]["context"] != new_context["context"]

0 commit comments

Comments
 (0)