Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
SeleniumHQ
GitHub Repository: SeleniumHQ/Selenium
Path: blob/trunk/py/test/selenium/webdriver/common/interactions_with_device_tests.py
4012 views
1
# Licensed to the Software Freedom Conservancy (SFC) under one
2
# or more contributor license agreements. See the NOTICE file
3
# distributed with this work for additional information
4
# regarding copyright ownership. The SFC licenses this file
5
# to you under the Apache License, Version 2.0 (the
6
# "License"); you may not use this file except in compliance
7
# with the License. You may obtain a copy of the License at
8
#
9
# http://www.apache.org/licenses/LICENSE-2.0
10
#
11
# Unless required by applicable law or agreed to in writing,
12
# software distributed under the License is distributed on an
13
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14
# KIND, either express or implied. See the License for the
15
# specific language governing permissions and limitations
16
# under the License.
17
18
"""Tests for advanced user interactions."""
19
20
import pytest
21
22
from selenium.common.exceptions import MoveTargetOutOfBoundsException
23
from selenium.webdriver.common.action_chains import ActionChains
24
from selenium.webdriver.common.actions import interaction
25
from selenium.webdriver.common.actions.key_input import KeyInput
26
from selenium.webdriver.common.actions.pointer_input import PointerInput
27
from selenium.webdriver.common.actions.wheel_input import ScrollOrigin, WheelInput
28
from selenium.webdriver.common.by import By
29
from selenium.webdriver.common.keys import Keys
30
from selenium.webdriver.support.ui import WebDriverWait
31
32
33
def _is_element_available(driver, id):
34
"""Copied from org.openqa.selenium.interactions.TestBasicMouseInterface."""
35
try:
36
driver.find_element(By.ID, id)
37
return True
38
except Exception:
39
return False
40
41
42
@pytest.mark.xfail_safari
43
@pytest.mark.xfail_chrome
44
def test_drag_and_drop_with_pointer(driver, pages):
45
"""Copied from org.openqa.selenium.interactions.TestBasicMouseInterface."""
46
element_available_timeout = 15
47
wait = WebDriverWait(driver, element_available_timeout)
48
pages.load("droppableItems.html")
49
wait.until(lambda dr: _is_element_available(driver, "draggable"))
50
51
if not _is_element_available(driver, "draggable"):
52
raise AssertionError("Could not find draggable element after 15 seconds.")
53
54
toDrag = driver.find_element(By.ID, "draggable")
55
dropInto = driver.find_element(By.ID, "droppable")
56
57
mouse = PointerInput(interaction.POINTER_MOUSE, "test mouse")
58
59
holdDrag = ActionChains(driver, devices=[mouse]).click_and_hold(toDrag)
60
move = ActionChains(driver, devices=[mouse]).move_to_element(dropInto)
61
drop = ActionChains(driver, devices=[mouse]).release(dropInto)
62
63
holdDrag.perform()
64
move.perform()
65
drop.perform()
66
67
dropInto = driver.find_element(By.ID, "droppable")
68
text = dropInto.find_element(By.TAG_NAME, "p").text
69
assert "Dropped!" == text
70
71
72
@pytest.mark.xfail_safari
73
def test_double_click_with_pointer(driver, pages):
74
"""Copied from org.openqa.selenium.interactions.TestBasicMouseInterface."""
75
pages.load("javascriptPage.html")
76
toDoubleClick = driver.find_element(By.ID, "doubleClickField")
77
78
mouse = PointerInput(interaction.POINTER_MOUSE, "test mouse")
79
80
dblClick = ActionChains(driver, devices=[mouse]).double_click(toDoubleClick)
81
dblClick.perform()
82
assert "DoubleClicked" == toDoubleClick.get_attribute("value")
83
84
85
def test_context_click_with_pointer(driver, pages):
86
"""Copied from org.openqa.selenium.interactions.TestBasicMouseInterface."""
87
pages.load("javascriptPage.html")
88
toContextClick = driver.find_element(By.ID, "doubleClickField")
89
90
mouse = PointerInput(interaction.POINTER_MOUSE, "test mouse")
91
92
contextClick = ActionChains(driver, devices=[mouse]).context_click(toContextClick)
93
contextClick.perform()
94
assert "ContextClicked" == toContextClick.get_attribute("value")
95
96
97
def test_move_and_click_with_pointer(driver, pages):
98
"""Copied from org.openqa.selenium.interactions.TestBasicMouseInterface."""
99
pages.load("javascriptPage.html")
100
toClick = driver.find_element(By.ID, "clickField")
101
102
mouse = PointerInput(interaction.POINTER_MOUSE, "test mouse")
103
104
click = ActionChains(driver, devices=[mouse]).move_to_element(toClick).click()
105
click.perform()
106
assert "Clicked" == toClick.get_attribute("value")
107
108
109
def test_cannot_move_to_anull_locator_with_pointer(driver, pages):
110
"""Copied from org.openqa.selenium.interactions.TestBasicMouseInterface."""
111
pages.load("javascriptPage.html")
112
mouse = PointerInput(interaction.POINTER_MOUSE, "test mouse")
113
114
with pytest.raises(AttributeError):
115
move = ActionChains(driver, devices=[mouse]).move_to_element(None)
116
move.perform()
117
118
119
@pytest.mark.xfail_safari
120
def test_clicking_on_form_elements_with_pointer(driver, pages):
121
"""Copied from org.openqa.selenium.interactions.CombinedInputActionsTest."""
122
pages.load("formSelectionPage.html")
123
options = driver.find_elements(By.TAG_NAME, "option")
124
mouse = PointerInput(interaction.POINTER_MOUSE, "test mouse")
125
126
selectThreeOptions = (
127
ActionChains(driver, devices=[mouse])
128
.click(options[1])
129
.key_down(Keys.SHIFT)
130
.click(options[3])
131
.key_up(Keys.SHIFT)
132
)
133
selectThreeOptions.perform()
134
135
showButton = driver.find_element(By.NAME, "showselected")
136
showButton.click()
137
138
resultElement = driver.find_element(By.ID, "result")
139
assert "roquefort parmigiano cheddar" == resultElement.text
140
141
142
@pytest.mark.xfail_firefox
143
@pytest.mark.xfail_safari
144
def test_selecting_multiple_items_with_devices(driver, pages):
145
"""Copied from org.openqa.selenium.interactions.CombinedInputActionsTest."""
146
pages.load("selectableItems.html")
147
reportingElement = driver.find_element(By.ID, "infodiv")
148
assert "no info" == reportingElement.text
149
150
mouse = PointerInput(interaction.POINTER_MOUSE, "test mouse")
151
key_board = KeyInput("test keyboard")
152
153
listItems = driver.find_elements(By.TAG_NAME, "li")
154
selectThreeItems = (
155
ActionChains(driver, devices=[mouse, key_board])
156
.key_down(Keys.CONTROL)
157
.click(listItems[1])
158
.click(listItems[3])
159
.click(listItems[5])
160
.key_up(Keys.CONTROL)
161
)
162
selectThreeItems.perform()
163
164
assert "#item2 #item4 #item6" == reportingElement.text
165
166
# Now click on another element, make sure that's the only one selected.
167
actionsBuilder = ActionChains(driver)
168
actionsBuilder.click(listItems[6]).perform()
169
assert "#item7" == reportingElement.text
170
171
172
@pytest.mark.xfail_safari
173
def test_sending_keys_to_active_element_with_modifier_with_keyboard(driver, pages):
174
pages.load("formPage.html")
175
e = driver.find_element(By.ID, "working")
176
e.click()
177
178
key_board = KeyInput("test keyboard")
179
180
ActionChains(driver, devices=[key_board]).key_down(Keys.SHIFT).send_keys("abc").key_up(Keys.SHIFT).perform()
181
182
assert "ABC" == e.get_attribute("value")
183
184
185
def test_sending_keys_to_element_with_keyboard(driver, pages):
186
pages.load("formPage.html")
187
e = driver.find_element(By.ID, "working")
188
189
key_board = KeyInput("test keyboard")
190
191
ActionChains(driver, devices=[key_board]).send_keys_to_element(e, "abc").perform()
192
193
assert "abc" == e.get_attribute("value")
194
195
196
def test_can_send_keys_between_clicks_with_keyboard(driver, pages):
197
"""Ensure W3C sends correct pause count to other input devices."""
198
pages.load("javascriptPage.html")
199
keyup = driver.find_element(By.ID, "keyUp")
200
keydown = driver.find_element(By.ID, "keyDown")
201
202
key_board = KeyInput("test keyboard")
203
204
ActionChains(driver, devices=[key_board]).click(keyup).send_keys("foobar").click(keydown).perform()
205
206
assert "foobar" == keyup.get_attribute("value")
207
208
209
def test_can_reset_interactions_with_devices(driver):
210
mouse = PointerInput(interaction.POINTER_MOUSE, "test mouse")
211
key_board = KeyInput("test keyboard")
212
actions = ActionChains(driver, devices=[mouse, key_board])
213
actions.click()
214
actions.key_down("A")
215
216
assert all(len(device.actions) >= 0 for device in actions.w3c_actions.devices if device.type != interaction.WHEEL)
217
218
actions.reset_actions()
219
220
assert all(len(device.actions) == 0 for device in actions.w3c_actions.devices)
221
222
223
def test_can_pause_with_pointer(driver, pages):
224
from time import time
225
226
pages.load("javascriptPage.html")
227
228
pause_time = 2
229
toClick = driver.find_element(By.ID, "clickField")
230
toDoubleClick = driver.find_element(By.ID, "doubleClickField")
231
232
mouse = PointerInput(interaction.POINTER_MOUSE, "test mouse")
233
234
pause = ActionChains(driver, devices=[mouse]).click(toClick).pause(pause_time).click(toDoubleClick)
235
236
start = time()
237
pause.perform()
238
end = time()
239
240
assert pause_time < end - start
241
assert "Clicked" == toClick.get_attribute("value")
242
assert "Clicked" == toDoubleClick.get_attribute("value")
243
244
245
@pytest.mark.xfail_firefox
246
@pytest.mark.xfail_remote
247
@pytest.mark.xfail_safari
248
def test_can_scroll_to_element_with_wheel(driver, pages):
249
pages.load("scrolling_tests/frame_with_nested_scrolling_frame_out_of_view.html")
250
iframe = driver.find_element(By.TAG_NAME, "iframe")
251
252
assert not _in_viewport(driver, iframe)
253
254
wheel = WheelInput("test wheel")
255
256
ActionChains(driver, devices=[wheel]).scroll_to_element(iframe).perform()
257
258
assert _in_viewport(driver, iframe)
259
260
261
@pytest.mark.xfail_firefox
262
@pytest.mark.xfail_remote
263
@pytest.mark.xfail_safari
264
def test_can_scroll_from_element_by_amount_with_wheel(driver, pages):
265
pages.load("scrolling_tests/frame_with_nested_scrolling_frame_out_of_view.html")
266
iframe = driver.find_element(By.TAG_NAME, "iframe")
267
scroll_origin = ScrollOrigin.from_element(iframe)
268
269
wheel = WheelInput("test wheel")
270
271
ActionChains(driver, devices=[wheel]).scroll_from_origin(scroll_origin, 0, 200).pause(0.2).perform()
272
273
driver.switch_to.frame(iframe)
274
checkbox = driver.find_element(By.NAME, "scroll_checkbox")
275
assert _in_viewport(driver, checkbox)
276
277
278
@pytest.mark.xfail_firefox
279
@pytest.mark.xfail_remote
280
@pytest.mark.xfail_safari
281
def test_can_scroll_from_element_with_offset_by_amount_with_wheel(driver, pages):
282
pages.load("scrolling_tests/frame_with_nested_scrolling_frame_out_of_view.html")
283
footer = driver.find_element(By.TAG_NAME, "footer")
284
scroll_origin = ScrollOrigin.from_element(footer, 0, -50)
285
286
wheel = WheelInput("test wheel")
287
288
ActionChains(driver, devices=[wheel]).scroll_from_origin(scroll_origin, 0, 200).pause(0.2).perform()
289
290
iframe = driver.find_element(By.TAG_NAME, "iframe")
291
driver.switch_to.frame(iframe)
292
checkbox = driver.find_element(By.NAME, "scroll_checkbox")
293
assert _in_viewport(driver, checkbox)
294
295
296
@pytest.mark.xfail_firefox
297
def test_errors_when_element_offset_not_in_viewport_with_wheel(driver, pages):
298
pages.load("scrolling_tests/frame_with_nested_scrolling_frame_out_of_view.html")
299
footer = driver.find_element(By.TAG_NAME, "footer")
300
scroll_origin = ScrollOrigin.from_element(footer, 0, 50)
301
302
wheel = WheelInput("test wheel")
303
304
with pytest.raises(MoveTargetOutOfBoundsException):
305
ActionChains(driver, devices=[wheel]).scroll_from_origin(scroll_origin, 0, 200).pause(0.2).perform()
306
307
308
@pytest.mark.xfail_firefox
309
@pytest.mark.xfail_remote
310
def test_can_scroll_from_viewport_by_amount_with_wheel(driver, pages):
311
pages.load("scrolling_tests/frame_with_nested_scrolling_frame_out_of_view.html")
312
footer = driver.find_element(By.TAG_NAME, "footer")
313
delta_y = footer.rect["y"]
314
315
wheel = WheelInput("test wheel")
316
317
ActionChains(driver, devices=[wheel]).scroll_by_amount(0, delta_y).pause(0.2).perform()
318
319
assert _in_viewport(driver, footer)
320
321
322
@pytest.mark.xfail_firefox
323
@pytest.mark.xfail_safari
324
def test_can_scroll_from_viewport_with_offset_by_amount_with_wheel(driver, pages):
325
pages.load("scrolling_tests/frame_with_nested_scrolling_frame.html")
326
scroll_origin = ScrollOrigin.from_viewport(10, 10)
327
328
wheel = WheelInput("test wheel")
329
330
ActionChains(driver, devices=[wheel]).scroll_from_origin(scroll_origin, 0, 200).pause(0.2).perform()
331
332
iframe = driver.find_element(By.TAG_NAME, "iframe")
333
driver.switch_to.frame(iframe)
334
checkbox = driver.find_element(By.NAME, "scroll_checkbox")
335
assert _in_viewport(driver, checkbox)
336
337
338
@pytest.mark.xfail_firefox
339
def test_errors_when_origin_offset_not_in_viewport_with_wheel(driver, pages):
340
pages.load("scrolling_tests/frame_with_nested_scrolling_frame.html")
341
scroll_origin = ScrollOrigin.from_viewport(-10, -10)
342
343
wheel = WheelInput("test wheel")
344
345
with pytest.raises(MoveTargetOutOfBoundsException):
346
ActionChains(driver, devices=[wheel]).scroll_from_origin(scroll_origin, 0, 200).pause(0.2).perform()
347
348
349
def _get_events(driver):
350
"""Return list of key events recorded in the test_keys_page fixture."""
351
events = driver.execute_script("return allEvents.events;") or []
352
# `key` values in `allEvents` may be escaped (see `escapeSurrogateHalf` in
353
# test_keys_wdspec.html), so this converts them back into unicode literals.
354
for e in events:
355
# example: turn "U+d83d" (6 chars) into u"\ud83d" (1 char)
356
if "key" in e and e["key"].startswith("U+"):
357
key = e["key"]
358
hex_suffix = key[key.index("+") + 1 :]
359
e["key"] = chr(int(hex_suffix, 16))
360
361
# WebKit sets code as 'Unidentified' for unidentified key codes, but
362
# tests expect ''.
363
if "code" in e and e["code"] == "Unidentified":
364
e["code"] = ""
365
return events
366
367
368
def _in_viewport(driver, element):
369
script = (
370
"for(var e=arguments[0],f=e.offsetTop,t=e.offsetLeft,o=e.offsetWidth,n=e.offsetHeight;\n"
371
"e.offsetParent;)f+=(e=e.offsetParent).offsetTop,t+=e.offsetLeft;\n"
372
"return f<window.pageYOffset+window.innerHeight&&t<window.pageXOffset+window.innerWidth&&f+n>\n"
373
"window.pageYOffset&&t+o>window.pageXOffset"
374
)
375
return driver.execute_script(script, element)
376
377