Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
SeleniumHQ
GitHub Repository: SeleniumHQ/Selenium
Path: blob/trunk/py/test/selenium/webdriver/common/interactions_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.wheel_input import ScrollOrigin
26
from selenium.webdriver.common.by import By
27
from selenium.webdriver.common.keys import Keys
28
from selenium.webdriver.support.ui import WebDriverWait
29
30
31
def perform_drag_and_drop_with_mouse(driver, pages):
32
"""Copied from org.openqa.selenium.interactions.TestBasicMouseInterface."""
33
pages.load("draggableLists.html")
34
dragReporter = driver.find_element(By.ID, "dragging_reports")
35
toDrag = driver.find_element(By.ID, "rightitem-3")
36
dragInto = driver.find_element(By.ID, "sortable1")
37
38
holdItem = ActionChains(driver).click_and_hold(toDrag)
39
moveToSpecificItem = ActionChains(driver).move_to_element(driver.find_element(By.ID, "leftitem-4"))
40
moveToOtherList = ActionChains(driver).move_to_element(dragInto)
41
drop = ActionChains(driver).release(dragInto)
42
assert "Nothing happened." == dragReporter.text
43
44
holdItem.perform()
45
moveToSpecificItem.perform()
46
moveToOtherList.perform()
47
assert "Nothing happened. DragOut" == dragReporter.text
48
49
drop.perform()
50
51
52
@pytest.mark.xfail_safari
53
def test_dragging_element_with_mouse_moves_it_to_another_list(driver, pages):
54
"""Copied from org.openqa.selenium.interactions.TestBasicMouseInterface."""
55
perform_drag_and_drop_with_mouse(driver, pages)
56
dragInto = driver.find_element(By.ID, "sortable1")
57
assert 6 == len(dragInto.find_elements(By.TAG_NAME, "li"))
58
59
60
@pytest.mark.xfail_safari
61
def test_dragging_element_with_mouse_fires_events(driver, pages):
62
"""Copied from org.openqa.selenium.interactions.TestBasicMouseInterface."""
63
perform_drag_and_drop_with_mouse(driver, pages)
64
dragReporter = driver.find_element(By.ID, "dragging_reports")
65
assert "Nothing happened. DragOut DropIn RightItem 3" == dragReporter.text
66
67
68
def _is_element_available(driver, id):
69
"""Copied from org.openqa.selenium.interactions.TestBasicMouseInterface."""
70
try:
71
driver.find_element(By.ID, id)
72
return True
73
except Exception:
74
return False
75
76
77
@pytest.mark.xfail_safari
78
def test_drag_and_drop(driver, pages):
79
"""Copied from org.openqa.selenium.interactions.TestBasicMouseInterface."""
80
element_available_timeout = 15
81
wait = WebDriverWait(driver, element_available_timeout)
82
pages.load("droppableItems.html")
83
wait.until(lambda dr: _is_element_available(driver, "draggable"))
84
85
if not _is_element_available(driver, "draggable"):
86
raise AssertionError("Could not find draggable element after 15 seconds.")
87
88
toDrag = driver.find_element(By.ID, "draggable")
89
dropInto = driver.find_element(By.ID, "droppable")
90
91
holdDrag = ActionChains(driver).click_and_hold(toDrag)
92
move = ActionChains(driver).move_to_element(dropInto)
93
drop = ActionChains(driver).release(dropInto)
94
95
holdDrag.perform()
96
move.perform()
97
drop.perform()
98
99
dropInto = driver.find_element(By.ID, "droppable")
100
text = dropInto.find_element(By.TAG_NAME, "p").text
101
assert "Dropped!" == text
102
103
104
@pytest.mark.xfail_safari
105
def test_double_click(driver, pages):
106
"""Copied from org.openqa.selenium.interactions.TestBasicMouseInterface."""
107
pages.load("javascriptPage.html")
108
toDoubleClick = driver.find_element(By.ID, "doubleClickField")
109
110
dblClick = ActionChains(driver).double_click(toDoubleClick)
111
112
dblClick.perform()
113
assert "DoubleClicked" == toDoubleClick.get_attribute("value")
114
115
116
def test_context_click(driver, pages):
117
"""Copied from org.openqa.selenium.interactions.TestBasicMouseInterface."""
118
pages.load("javascriptPage.html")
119
toContextClick = driver.find_element(By.ID, "doubleClickField")
120
121
contextClick = ActionChains(driver).context_click(toContextClick)
122
123
contextClick.perform()
124
assert "ContextClicked" == toContextClick.get_attribute("value")
125
126
127
def test_move_and_click(driver, pages):
128
"""Copied from org.openqa.selenium.interactions.TestBasicMouseInterface."""
129
pages.load("javascriptPage.html")
130
toClick = driver.find_element(By.ID, "clickField")
131
132
click = ActionChains(driver).move_to_element(toClick).click()
133
134
click.perform()
135
assert "Clicked" == toClick.get_attribute("value")
136
137
138
def test_cannot_move_to_anull_locator(driver, pages):
139
"""Copied from org.openqa.selenium.interactions.TestBasicMouseInterface."""
140
pages.load("javascriptPage.html")
141
142
with pytest.raises(AttributeError):
143
move = ActionChains(driver).move_to_element(None)
144
move.perform()
145
146
147
@pytest.mark.xfail_safari
148
def test_clicking_on_form_elements(driver, pages):
149
"""Copied from org.openqa.selenium.interactions.CombinedInputActionsTest."""
150
pages.load("formSelectionPage.html")
151
options = driver.find_elements(By.TAG_NAME, "option")
152
selectThreeOptions = (
153
ActionChains(driver).click(options[1]).key_down(Keys.SHIFT).click(options[3]).key_up(Keys.SHIFT)
154
)
155
selectThreeOptions.perform()
156
157
showButton = driver.find_element(By.NAME, "showselected")
158
showButton.click()
159
160
resultElement = driver.find_element(By.ID, "result")
161
assert "roquefort parmigiano cheddar" == resultElement.text
162
163
164
@pytest.mark.xfail_firefox
165
@pytest.mark.xfail_safari
166
def test_selecting_multiple_items(driver, pages):
167
"""Copied from org.openqa.selenium.interactions.CombinedInputActionsTest."""
168
pages.load("selectableItems.html")
169
reportingElement = driver.find_element(By.ID, "infodiv")
170
assert "no info" == reportingElement.text
171
172
listItems = driver.find_elements(By.TAG_NAME, "li")
173
selectThreeItems = (
174
ActionChains(driver)
175
.key_down(Keys.CONTROL)
176
.click(listItems[1])
177
.click(listItems[3])
178
.click(listItems[5])
179
.key_up(Keys.CONTROL)
180
)
181
selectThreeItems.perform()
182
183
assert "#item2 #item4 #item6" == reportingElement.text
184
185
# Now click on another element, make sure that's the only one selected.
186
actionsBuilder = ActionChains(driver)
187
actionsBuilder.click(listItems[6]).perform()
188
assert "#item7" == reportingElement.text
189
190
191
@pytest.mark.xfail_safari
192
def test_sending_keys_to_active_element_with_modifier(driver, pages):
193
pages.load("formPage.html")
194
e = driver.find_element(By.ID, "working")
195
e.click()
196
197
ActionChains(driver).key_down(Keys.SHIFT).send_keys("abc").key_up(Keys.SHIFT).perform()
198
199
assert "ABC" == e.get_attribute("value")
200
201
202
def test_sending_keys_to_element(driver, pages):
203
pages.load("formPage.html")
204
e = driver.find_element(By.ID, "working")
205
206
ActionChains(driver).send_keys_to_element(e, "abc").perform()
207
208
assert "abc" == e.get_attribute("value")
209
210
211
def test_can_send_keys_between_clicks(driver, pages):
212
"""
213
For W3C, ensures that the correct number of pauses are given to the other
214
input device.
215
"""
216
pages.load("javascriptPage.html")
217
keyup = driver.find_element(By.ID, "keyUp")
218
keydown = driver.find_element(By.ID, "keyDown")
219
ActionChains(driver).click(keyup).send_keys("foobar").click(keydown).perform()
220
221
assert "foobar" == keyup.get_attribute("value")
222
223
224
def test_can_reset_interactions(driver):
225
actions = ActionChains(driver)
226
actions.click()
227
actions.key_down("A")
228
assert all(len(device.actions) > 0 for device in actions.w3c_actions.devices if device.type != interaction.WHEEL)
229
230
actions.reset_actions()
231
232
assert all(len(device.actions) == 0 for device in actions.w3c_actions.devices)
233
234
235
def test_can_pause(driver, pages):
236
from time import time
237
238
pages.load("javascriptPage.html")
239
240
pause_time = 2
241
toClick = driver.find_element(By.ID, "clickField")
242
toDoubleClick = driver.find_element(By.ID, "doubleClickField")
243
244
pause = ActionChains(driver).click(toClick).pause(pause_time).click(toDoubleClick)
245
246
start = time()
247
pause.perform()
248
end = time()
249
250
assert pause_time < end - start
251
assert "Clicked" == toClick.get_attribute("value")
252
assert "Clicked" == toDoubleClick.get_attribute("value")
253
254
255
@pytest.mark.xfail_firefox
256
@pytest.mark.xfail_remote
257
@pytest.mark.xfail_safari
258
def test_can_scroll_to_element(driver, pages):
259
pages.load("scrolling_tests/frame_with_nested_scrolling_frame_out_of_view.html")
260
iframe = driver.find_element(By.TAG_NAME, "iframe")
261
262
assert not _in_viewport(driver, iframe)
263
264
ActionChains(driver).scroll_to_element(iframe).perform()
265
266
assert _in_viewport(driver, iframe)
267
268
269
@pytest.mark.xfail_firefox
270
@pytest.mark.xfail_remote
271
@pytest.mark.xfail_safari
272
def test_can_scroll_from_element_by_amount(driver, pages):
273
pages.load("scrolling_tests/frame_with_nested_scrolling_frame_out_of_view.html")
274
iframe = driver.find_element(By.TAG_NAME, "iframe")
275
scroll_origin = ScrollOrigin.from_element(iframe)
276
277
ActionChains(driver).scroll_from_origin(scroll_origin, 0, 200).pause(0.2).perform()
278
279
driver.switch_to.frame(iframe)
280
checkbox = driver.find_element(By.NAME, "scroll_checkbox")
281
assert _in_viewport(driver, checkbox)
282
283
284
@pytest.mark.xfail_firefox
285
@pytest.mark.xfail_remote
286
@pytest.mark.xfail_safari
287
def test_can_scroll_from_element_with_offset_by_amount(driver, pages):
288
pages.load("scrolling_tests/frame_with_nested_scrolling_frame_out_of_view.html")
289
footer = driver.find_element(By.TAG_NAME, "footer")
290
scroll_origin = ScrollOrigin.from_element(footer, 0, -50)
291
292
ActionChains(driver).scroll_from_origin(scroll_origin, 0, 200).pause(0.2).perform()
293
294
iframe = driver.find_element(By.TAG_NAME, "iframe")
295
driver.switch_to.frame(iframe)
296
checkbox = driver.find_element(By.NAME, "scroll_checkbox")
297
assert _in_viewport(driver, checkbox)
298
299
300
def test_errors_when_element_offset_not_in_viewport(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
with pytest.raises(MoveTargetOutOfBoundsException):
306
ActionChains(driver).scroll_from_origin(scroll_origin, 0, 200).pause(0.2).perform()
307
308
309
@pytest.mark.xfail_firefox
310
@pytest.mark.xfail_remote
311
def test_can_scroll_from_viewport_by_amount(driver, pages):
312
pages.load("scrolling_tests/frame_with_nested_scrolling_frame_out_of_view.html")
313
footer = driver.find_element(By.TAG_NAME, "footer")
314
delta_y = footer.rect["y"]
315
316
ActionChains(driver).scroll_by_amount(0, delta_y).pause(0.2).perform()
317
318
assert _in_viewport(driver, footer)
319
320
321
@pytest.mark.xfail_safari
322
def test_can_scroll_from_viewport_with_offset_by_amount(driver, pages):
323
pages.load("scrolling_tests/frame_with_nested_scrolling_frame.html")
324
scroll_origin = ScrollOrigin.from_viewport(10, 10)
325
326
ActionChains(driver).scroll_from_origin(scroll_origin, 0, 200).pause(0.2).perform()
327
328
iframe = driver.find_element(By.TAG_NAME, "iframe")
329
driver.switch_to.frame(iframe)
330
checkbox = driver.find_element(By.NAME, "scroll_checkbox")
331
assert _in_viewport(driver, checkbox)
332
333
334
def test_errors_when_origin_offset_not_in_viewport(driver, pages):
335
pages.load("scrolling_tests/frame_with_nested_scrolling_frame.html")
336
scroll_origin = ScrollOrigin.from_viewport(-10, -10)
337
338
with pytest.raises(MoveTargetOutOfBoundsException):
339
ActionChains(driver).scroll_from_origin(scroll_origin, 0, 200).pause(0.2).perform()
340
341
342
def _get_events(driver):
343
"""Return list of key events recorded in the test_keys_page fixture."""
344
events = driver.execute_script("return allEvents.events;") or []
345
# `key` values in `allEvents` may be escaped (see `escapeSurrogateHalf` in
346
# test_keys_wdspec.html), so this converts them back into unicode literals.
347
for e in events:
348
# example: turn "U+d83d" (6 chars) into u"\ud83d" (1 char)
349
if "key" in e and e["key"].startswith("U+"):
350
key = e["key"]
351
hex_suffix = key[key.index("+") + 1 :]
352
e["key"] = chr(int(hex_suffix, 16))
353
354
# WebKit sets code as 'Unidentified' for unidentified key codes, but
355
# tests expect ''.
356
if "code" in e and e["code"] == "Unidentified":
357
e["code"] = ""
358
return events
359
360
361
def _in_viewport(driver, element):
362
script = (
363
"for(var e=arguments[0],f=e.offsetTop,t=e.offsetLeft,o=e.offsetWidth,n=e.offsetHeight;\n"
364
"e.offsetParent;)f+=(e=e.offsetParent).offsetTop,t+=e.offsetLeft;\n"
365
"return f<window.pageYOffset+window.innerHeight&&t<window.pageXOffset+window.innerWidth&&f+n>\n"
366
"window.pageYOffset&&t+o>window.pageXOffset"
367
)
368
return driver.execute_script(script, element)
369
370