Skip to content

Commit 1870817

Browse files
authored
test: add async dispatch event tests (#130)
1 parent 5938297 commit 1870817

File tree

4 files changed

+218
-2
lines changed

4 files changed

+218
-2
lines changed

playwright/element_handle.py

+3-1
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,9 @@ async def innerHTML(self) -> str:
6666
return await self._channel.send("innerHTML")
6767

6868
async def dispatchEvent(self, type: str, eventInit: Dict = None) -> None:
69-
await self._channel.send("dispatchEvent", dict(type=type, eventInit=eventInit))
69+
await self._channel.send(
70+
"dispatchEvent", dict(type=type, eventInit=serialize_argument(eventInit))
71+
)
7072

7173
async def scrollIntoViewIfNeeded(self, timeout: int = None) -> None:
7274
await self._channel.send("scrollIntoViewIfNeeded", locals_to_params(locals()))

playwright/frame.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -238,7 +238,8 @@ async def dispatchEvent(
238238
self, selector: str, type: str, eventInit: Dict = None, timeout: int = None
239239
) -> None:
240240
await self._channel.send(
241-
"dispatchEvent", dict(selector=selector, type=type, eventInit=eventInit)
241+
"dispatchEvent",
242+
dict(selector=selector, type=type, eventInit=serialize_argument(eventInit)),
242243
)
243244

244245
async def evalOnSelector(

tests/assets/drag-n-drop.html

+41
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
<style>
2+
div:not(.mouse-helper) {
3+
margin: 0em;
4+
padding: 2em;
5+
}
6+
#source {
7+
color: blue;
8+
border: 1px solid black;
9+
}
10+
#target {
11+
border: 1px solid black;
12+
}
13+
</style>
14+
15+
<script>
16+
17+
function dragstart_handler(ev) {
18+
ev.currentTarget.style.border = "dashed";
19+
ev.dataTransfer.setData("text/plain", ev.target.id);
20+
}
21+
22+
function dragover_handler(ev) {
23+
ev.preventDefault();
24+
}
25+
26+
function drop_handler(ev) {
27+
console.log("Drop");
28+
ev.preventDefault();
29+
var data = ev.dataTransfer.getData("text");
30+
ev.target.appendChild(document.getElementById(data));
31+
ev.dataTransfer.clearData();
32+
}
33+
</script>
34+
35+
<body>
36+
<div>
37+
<p id="source" ondragstart="dragstart_handler(event);" draggable="true">
38+
Select this element, drag it to the Drop Zone and then release the selection to move the element.</p>
39+
</div>
40+
<div id="target" ondrop="drop_handler(event);" ondragover="dragover_handler(event);">Drop Zone</div>
41+
</body>

tests/async/test_dispatch_event.py

+172
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,172 @@
1+
# Copyright (c) Microsoft Corporation.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
import pytest
16+
17+
18+
async def test_should_dispatch_click_event(page, server):
19+
await page.goto(server.PREFIX + "/input/button.html")
20+
await page.dispatchEvent("button", "click")
21+
assert await page.evaluate("() => result") == "Clicked"
22+
23+
24+
async def test_should_dispatch_click_event_properties(page, server):
25+
await page.goto(server.PREFIX + "/input/button.html")
26+
await page.dispatchEvent("button", "click")
27+
assert await page.evaluate("() => bubbles")
28+
assert await page.evaluate("() => cancelable")
29+
assert await page.evaluate("() => composed")
30+
31+
32+
async def test_should_dispatch_click_svg(page):
33+
await page.setContent(
34+
"""
35+
<svg height="100" width="100">
36+
<circle onclick="javascript:window.__CLICKED=42" cx="50" cy="50" r="40" stroke="black" stroke-width="3" fill="red" />
37+
</svg>
38+
"""
39+
)
40+
await page.dispatchEvent("circle", "click")
41+
assert await page.evaluate("() => window.__CLICKED") == 42
42+
43+
44+
async def test_should_dispatch_click_on_a_span_with_an_inline_element_inside(page):
45+
await page.setContent(
46+
"""
47+
<style>
48+
span::before {
49+
content: 'q';
50+
}
51+
</style>
52+
<span onclick='javascript:window.CLICKED=42'></span>
53+
"""
54+
)
55+
await page.dispatchEvent("span", "click")
56+
assert await page.evaluate("() => window.CLICKED") == 42
57+
58+
59+
async def test_should_dispatch_click_after_navigation(page, server):
60+
await page.goto(server.PREFIX + "/input/button.html")
61+
await page.dispatchEvent("button", "click")
62+
await page.goto(server.PREFIX + "/input/button.html")
63+
await page.dispatchEvent("button", "click")
64+
assert await page.evaluate("() => result") == "Clicked"
65+
66+
67+
async def test_should_dispatch_click_after_a_cross_origin_navigation(page, server):
68+
await page.goto(server.PREFIX + "/input/button.html")
69+
await page.dispatchEvent("button", "click")
70+
await page.goto(server.CROSS_PROCESS_PREFIX + "/input/button.html")
71+
await page.dispatchEvent("button", "click")
72+
assert await page.evaluate("() => result") == "Clicked"
73+
74+
75+
async def test_should_not_fail_when_element_is_blocked_on_hover(page, server):
76+
await page.setContent(
77+
"""<style>
78+
container { display: block; position: relative; width: 200px; height: 50px; }
79+
div, button { position: absolute; left: 0; top: 0; bottom: 0; right: 0; }
80+
div { pointer-events: none; }
81+
container:hover div { pointer-events: auto; background: red; }
82+
</style>
83+
<container>
84+
<button onclick="window.clicked=true">Click me</button>
85+
<div></div>
86+
</container>"""
87+
)
88+
await page.dispatchEvent("button", "click")
89+
assert await page.evaluate("() => window.clicked")
90+
91+
92+
async def test_should_dispatch_click_when_node_is_added_in_shadow_dom(page, server):
93+
await page.goto(server.EMPTY_PAGE)
94+
watchdog = page.dispatchEvent("span", "click")
95+
await page.evaluate(
96+
"""() => {
97+
const div = document.createElement('div');
98+
div.attachShadow({mode: 'open'});
99+
document.body.appendChild(div);
100+
}"""
101+
)
102+
await page.evaluate("() => new Promise(f => setTimeout(f, 100))")
103+
await page.evaluate(
104+
"""() => {
105+
const span = document.createElement('span');
106+
span.textContent = 'Hello from shadow';
107+
span.addEventListener('click', () => window.clicked = true);
108+
document.querySelector('div').shadowRoot.appendChild(span);
109+
}"""
110+
)
111+
await watchdog
112+
assert await page.evaluate("() => window.clicked")
113+
114+
115+
async def test_should_be_atomic(selectors, page, utils):
116+
await utils.register_selector_engine(
117+
selectors,
118+
"dispatchEvent",
119+
"""{
120+
create(root, target) { },
121+
query(root, selector) {
122+
const result = root.querySelector(selector);
123+
if (result)
124+
Promise.resolve().then(() => result.onclick = "");
125+
return result;
126+
},
127+
queryAll(root, selector) {
128+
const result = Array.from(root.querySelectorAll(selector));
129+
for (const e of result)
130+
Promise.resolve().then(() => result.onclick = "");
131+
return result;
132+
}
133+
}""",
134+
)
135+
await page.setContent('<div onclick="window._clicked=true">Hello</div>')
136+
await page.dispatchEvent("dispatchEvent=div", "click")
137+
assert await page.evaluate("() => window._clicked")
138+
139+
140+
@pytest.mark.skip_browser("webkit")
141+
async def test_should_dispatch_drag_drop_events(page, server):
142+
await page.goto(server.PREFIX + "/drag-n-drop.html")
143+
dataTransfer = await page.evaluateHandle("() => new DataTransfer()")
144+
await page.dispatchEvent("#source", "dragstart", {"dataTransfer": dataTransfer})
145+
await page.dispatchEvent("#target", "drop", {"dataTransfer": dataTransfer})
146+
assert await page.evaluate(
147+
"""() => {
148+
return source.parentElement === target;
149+
}"""
150+
)
151+
152+
153+
@pytest.mark.skip_browser("webkit")
154+
async def test_should_dispatch_drag_and_drop_events_element_handle(page, server):
155+
await page.goto(server.PREFIX + "/drag-n-drop.html")
156+
dataTransfer = await page.evaluateHandle("() => new DataTransfer()")
157+
source = await page.querySelector("#source")
158+
await source.dispatchEvent("dragstart", {"dataTransfer": dataTransfer})
159+
target = await page.querySelector("#target")
160+
await target.dispatchEvent("drop", {"dataTransfer": dataTransfer})
161+
assert await page.evaluate(
162+
"""() => {
163+
return source.parentElement === target;
164+
}"""
165+
)
166+
167+
168+
async def test_should_dispatch_click_event_element_handle(page, server):
169+
await page.goto(server.PREFIX + "/input/button.html")
170+
button = await page.querySelector("button")
171+
await button.dispatchEvent("click")
172+
assert await page.evaluate("() => result") == "Clicked"

0 commit comments

Comments
 (0)