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
1865 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
"""
198
For W3C, ensures that the correct number of pauses are given to the other
199
input device.
200
"""
201
pages.load("javascriptPage.html")
202
keyup = driver.find_element(By.ID, "keyUp")
203
keydown = driver.find_element(By.ID, "keyDown")
204
205
key_board = KeyInput("test keyboard")
206
207
ActionChains(driver, devices=[key_board]).click(keyup).send_keys("foobar").click(keydown).perform()
208
209
assert "foobar" == keyup.get_attribute("value")
210
211
212
def test_can_reset_interactions_with_devices(driver):
213
mouse = PointerInput(interaction.POINTER_MOUSE, "test mouse")
214
key_board = KeyInput("test keyboard")
215
actions = ActionChains(driver, devices=[mouse, key_board])
216
actions.click()
217
actions.key_down("A")
218
219
assert all(len(device.actions) >= 0 for device in actions.w3c_actions.devices if device.type != interaction.WHEEL)
220
221
actions.reset_actions()
222
223
assert all(len(device.actions) == 0 for device in actions.w3c_actions.devices)
224
225
226
def test_can_pause_with_pointer(driver, pages):
227
from time import time
228
229
pages.load("javascriptPage.html")
230
231
pause_time = 2
232
toClick = driver.find_element(By.ID, "clickField")
233
toDoubleClick = driver.find_element(By.ID, "doubleClickField")
234
235
mouse = PointerInput(interaction.POINTER_MOUSE, "test mouse")
236
237
pause = ActionChains(driver, devices=[mouse]).click(toClick).pause(pause_time).click(toDoubleClick)
238
239
start = time()
240
pause.perform()
241
end = time()
242
243
assert pause_time < end - start
244
assert "Clicked" == toClick.get_attribute("value")
245
assert "Clicked" == toDoubleClick.get_attribute("value")
246
247
248
@pytest.mark.xfail_firefox
249
@pytest.mark.xfail_remote
250
@pytest.mark.xfail_safari
251
def test_can_scroll_to_element_with_wheel(driver, pages):
252
pages.load("scrolling_tests/frame_with_nested_scrolling_frame_out_of_view.html")
253
iframe = driver.find_element(By.TAG_NAME, "iframe")
254
255
assert not _in_viewport(driver, iframe)
256
257
wheel = WheelInput("test wheel")
258
259
ActionChains(driver, devices=[wheel]).scroll_to_element(iframe).perform()
260
261
assert _in_viewport(driver, iframe)
262
263
264
@pytest.mark.xfail_firefox
265
@pytest.mark.xfail_remote
266
@pytest.mark.xfail_safari
267
def test_can_scroll_from_element_by_amount_with_wheel(driver, pages):
268
pages.load("scrolling_tests/frame_with_nested_scrolling_frame_out_of_view.html")
269
iframe = driver.find_element(By.TAG_NAME, "iframe")
270
scroll_origin = ScrollOrigin.from_element(iframe)
271
272
wheel = WheelInput("test wheel")
273
274
ActionChains(driver, devices=[wheel]).scroll_from_origin(scroll_origin, 0, 200).pause(0.2).perform()
275
276
driver.switch_to.frame(iframe)
277
checkbox = driver.find_element(By.NAME, "scroll_checkbox")
278
assert _in_viewport(driver, checkbox)
279
280
281
@pytest.mark.xfail_firefox
282
@pytest.mark.xfail_remote
283
@pytest.mark.xfail_safari
284
def test_can_scroll_from_element_with_offset_by_amount_with_wheel(driver, pages):
285
pages.load("scrolling_tests/frame_with_nested_scrolling_frame_out_of_view.html")
286
footer = driver.find_element(By.TAG_NAME, "footer")
287
scroll_origin = ScrollOrigin.from_element(footer, 0, -50)
288
289
wheel = WheelInput("test wheel")
290
291
ActionChains(driver, devices=[wheel]).scroll_from_origin(scroll_origin, 0, 200).pause(0.2).perform()
292
293
iframe = driver.find_element(By.TAG_NAME, "iframe")
294
driver.switch_to.frame(iframe)
295
checkbox = driver.find_element(By.NAME, "scroll_checkbox")
296
assert _in_viewport(driver, checkbox)
297
298
299
@pytest.mark.xfail_firefox
300
def test_errors_when_element_offset_not_in_viewport_with_wheel(driver, pages):
301
pages.load("scrolling_tests/frame_with_nested_scrolling_frame_out_of_view.html")
302
footer = driver.find_element(By.TAG_NAME, "footer")
303
scroll_origin = ScrollOrigin.from_element(footer, 0, 50)
304
305
wheel = WheelInput("test wheel")
306
307
with pytest.raises(MoveTargetOutOfBoundsException):
308
ActionChains(driver, devices=[wheel]).scroll_from_origin(scroll_origin, 0, 200).pause(0.2).perform()
309
310
311
@pytest.mark.xfail_firefox
312
@pytest.mark.xfail_remote
313
def test_can_scroll_from_viewport_by_amount_with_wheel(driver, pages):
314
pages.load("scrolling_tests/frame_with_nested_scrolling_frame_out_of_view.html")
315
footer = driver.find_element(By.TAG_NAME, "footer")
316
delta_y = footer.rect["y"]
317
318
wheel = WheelInput("test wheel")
319
320
ActionChains(driver, devices=[wheel]).scroll_by_amount(0, delta_y).pause(0.2).perform()
321
322
assert _in_viewport(driver, footer)
323
324
325
@pytest.mark.xfail_firefox
326
@pytest.mark.xfail_safari
327
def test_can_scroll_from_viewport_with_offset_by_amount_with_wheel(driver, pages):
328
pages.load("scrolling_tests/frame_with_nested_scrolling_frame.html")
329
scroll_origin = ScrollOrigin.from_viewport(10, 10)
330
331
wheel = WheelInput("test wheel")
332
333
ActionChains(driver, devices=[wheel]).scroll_from_origin(scroll_origin, 0, 200).pause(0.2).perform()
334
335
iframe = driver.find_element(By.TAG_NAME, "iframe")
336
driver.switch_to.frame(iframe)
337
checkbox = driver.find_element(By.NAME, "scroll_checkbox")
338
assert _in_viewport(driver, checkbox)
339
340
341
@pytest.mark.xfail_firefox
342
def test_errors_when_origin_offset_not_in_viewport_with_wheel(driver, pages):
343
pages.load("scrolling_tests/frame_with_nested_scrolling_frame.html")
344
scroll_origin = ScrollOrigin.from_viewport(-10, -10)
345
346
wheel = WheelInput("test wheel")
347
348
with pytest.raises(MoveTargetOutOfBoundsException):
349
ActionChains(driver, devices=[wheel]).scroll_from_origin(scroll_origin, 0, 200).pause(0.2).perform()
350
351
352
def _get_events(driver):
353
"""Return list of key events recorded in the test_keys_page fixture."""
354
events = driver.execute_script("return allEvents.events;") or []
355
# `key` values in `allEvents` may be escaped (see `escapeSurrogateHalf` in
356
# test_keys_wdspec.html), so this converts them back into unicode literals.
357
for e in events:
358
# example: turn "U+d83d" (6 chars) into u"\ud83d" (1 char)
359
if "key" in e and e["key"].startswith("U+"):
360
key = e["key"]
361
hex_suffix = key[key.index("+") + 1 :]
362
e["key"] = chr(int(hex_suffix, 16))
363
364
# WebKit sets code as 'Unidentified' for unidentified key codes, but
365
# tests expect ''.
366
if "code" in e and e["code"] == "Unidentified":
367
e["code"] = ""
368
return events
369
370
371
def _in_viewport(driver, element):
372
script = (
373
"for(var e=arguments[0],f=e.offsetTop,t=e.offsetLeft,o=e.offsetWidth,n=e.offsetHeight;\n"
374
"e.offsetParent;)f+=(e=e.offsetParent).offsetTop,t+=e.offsetLeft;\n"
375
"return f<window.pageYOffset+window.innerHeight&&t<window.pageXOffset+window.innerWidth&&f+n>\n"
376
"window.pageYOffset&&t+o>window.pageXOffset"
377
)
378
return driver.execute_script(script, element)
379
380