selenium-webdriver 2.45.0 → 3.142.7

Sign up to get free protection for your applications and to get access to all the features.
Files changed (172) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGES +795 -3
  3. data/Gemfile +2 -0
  4. data/{COPYING → LICENSE} +1 -3
  5. data/README.md +13 -9
  6. data/lib/selenium/server.rb +93 -71
  7. data/lib/selenium/webdriver/atoms/getAttribute.js +7 -0
  8. data/lib/selenium/webdriver/atoms/isDisplayed.js +102 -0
  9. data/lib/selenium/webdriver/atoms.rb +37 -0
  10. data/lib/selenium/webdriver/chrome/bridge.rb +47 -99
  11. data/lib/selenium/webdriver/chrome/driver.rb +127 -0
  12. data/lib/selenium/webdriver/chrome/options.rb +190 -0
  13. data/lib/selenium/webdriver/chrome/profile.rb +40 -20
  14. data/lib/selenium/webdriver/chrome/service.rb +46 -62
  15. data/lib/selenium/webdriver/chrome.rb +34 -6
  16. data/lib/selenium/webdriver/common/action_builder.rb +69 -56
  17. data/lib/selenium/webdriver/common/alert.rb +25 -8
  18. data/lib/selenium/webdriver/common/bridge_helper.rb +35 -20
  19. data/lib/selenium/webdriver/common/driver.rb +90 -63
  20. data/lib/selenium/webdriver/common/driver_extensions/downloads_files.rb +45 -0
  21. data/lib/selenium/webdriver/common/driver_extensions/has_addons.rb +50 -0
  22. data/lib/selenium/webdriver/common/driver_extensions/has_debugger.rb +42 -0
  23. data/lib/selenium/webdriver/common/driver_extensions/has_location.rb +26 -11
  24. data/lib/selenium/webdriver/common/driver_extensions/has_network_conditions.rb +51 -0
  25. data/lib/selenium/webdriver/common/driver_extensions/has_network_connection.rb +58 -0
  26. data/lib/selenium/webdriver/common/driver_extensions/has_permissions.rb +51 -0
  27. data/lib/selenium/webdriver/common/driver_extensions/has_remote_status.rb +23 -6
  28. data/lib/selenium/webdriver/common/driver_extensions/has_session_id.rb +19 -2
  29. data/lib/selenium/webdriver/common/driver_extensions/has_touch_screen.rb +24 -7
  30. data/lib/selenium/webdriver/common/driver_extensions/has_web_storage.rb +19 -3
  31. data/lib/selenium/webdriver/common/driver_extensions/rotatable.rb +23 -7
  32. data/lib/selenium/webdriver/common/driver_extensions/takes_screenshot.rb +26 -5
  33. data/lib/selenium/webdriver/common/driver_extensions/uploads_files.rb +20 -6
  34. data/lib/selenium/webdriver/common/element.rb +79 -37
  35. data/lib/selenium/webdriver/common/error.rb +282 -106
  36. data/lib/selenium/webdriver/common/file_reaper.rb +23 -12
  37. data/lib/selenium/webdriver/common/html5/local_storage.rb +29 -12
  38. data/lib/selenium/webdriver/common/html5/session_storage.rb +29 -12
  39. data/lib/selenium/webdriver/common/html5/shared_web_storage.rb +29 -18
  40. data/lib/selenium/webdriver/common/interactions/input_device.rb +54 -0
  41. data/lib/selenium/webdriver/common/interactions/interaction.rb +53 -0
  42. data/lib/selenium/webdriver/common/interactions/interactions.rb +43 -0
  43. data/lib/selenium/webdriver/common/interactions/key_actions.rb +145 -0
  44. data/lib/selenium/webdriver/common/interactions/key_input.rb +66 -0
  45. data/lib/selenium/webdriver/common/interactions/none_input.rb +36 -0
  46. data/lib/selenium/webdriver/common/interactions/pointer_actions.rb +363 -0
  47. data/lib/selenium/webdriver/common/interactions/pointer_input.rb +139 -0
  48. data/lib/selenium/webdriver/common/keyboard.rb +27 -12
  49. data/lib/selenium/webdriver/common/keys.rb +118 -81
  50. data/lib/selenium/webdriver/common/log_entry.rb +27 -8
  51. data/lib/selenium/webdriver/common/logger.rb +115 -0
  52. data/lib/selenium/webdriver/common/logs.rb +24 -7
  53. data/lib/selenium/webdriver/common/manager.rb +177 -0
  54. data/lib/selenium/webdriver/common/mouse.rb +29 -12
  55. data/lib/selenium/webdriver/common/navigation.rb +21 -4
  56. data/lib/selenium/webdriver/common/options.rb +43 -126
  57. data/lib/selenium/webdriver/common/platform.rb +101 -97
  58. data/lib/selenium/webdriver/common/port_prober.rb +24 -17
  59. data/lib/selenium/webdriver/common/profile_helper.rb +27 -11
  60. data/lib/selenium/webdriver/common/proxy.rb +86 -73
  61. data/lib/selenium/webdriver/common/search_context.rb +49 -33
  62. data/lib/selenium/webdriver/common/service.rb +219 -0
  63. data/lib/selenium/webdriver/common/socket_lock.rb +82 -0
  64. data/lib/selenium/webdriver/common/socket_poller.rb +47 -26
  65. data/lib/selenium/webdriver/common/target_locator.rb +35 -14
  66. data/lib/selenium/webdriver/common/timeouts.rb +23 -6
  67. data/lib/selenium/webdriver/common/touch_action_builder.rb +25 -11
  68. data/lib/selenium/webdriver/common/touch_screen.rb +42 -24
  69. data/lib/selenium/webdriver/common/w3c_action_builder.rb +212 -0
  70. data/lib/selenium/webdriver/common/w3c_manager.rb +45 -0
  71. data/lib/selenium/webdriver/common/wait.rb +34 -14
  72. data/lib/selenium/webdriver/common/window.rb +75 -16
  73. data/lib/selenium/webdriver/common/zipper.rb +26 -11
  74. data/lib/selenium/webdriver/common.rb +40 -7
  75. data/lib/selenium/webdriver/edge/bridge.rb +76 -0
  76. data/lib/selenium/webdriver/edge/driver.rb +66 -0
  77. data/lib/selenium/webdriver/edge/options.rb +80 -0
  78. data/lib/selenium/webdriver/edge/service.rb +52 -0
  79. data/lib/selenium/webdriver/edge.rb +44 -0
  80. data/lib/selenium/webdriver/firefox/binary.rb +70 -48
  81. data/lib/selenium/webdriver/firefox/driver.rb +50 -0
  82. data/lib/selenium/webdriver/firefox/extension/prefs.json +14 -13
  83. data/lib/selenium/webdriver/firefox/extension/webdriver.xpi +0 -0
  84. data/lib/selenium/webdriver/firefox/extension.rb +50 -19
  85. data/lib/selenium/webdriver/firefox/launcher.rb +33 -28
  86. data/lib/selenium/webdriver/firefox/legacy/driver.rb +83 -0
  87. data/lib/selenium/webdriver/firefox/marionette/bridge.rb +49 -0
  88. data/lib/selenium/webdriver/firefox/marionette/driver.rb +90 -0
  89. data/lib/selenium/webdriver/firefox/options.rb +162 -0
  90. data/lib/selenium/webdriver/firefox/profile.rb +66 -48
  91. data/lib/selenium/webdriver/firefox/profiles_ini.rb +28 -16
  92. data/lib/selenium/webdriver/firefox/service.rb +52 -0
  93. data/lib/selenium/webdriver/firefox/util.rb +19 -2
  94. data/lib/selenium/webdriver/firefox.rb +46 -10
  95. data/lib/selenium/webdriver/ie/driver.rb +85 -0
  96. data/lib/selenium/webdriver/ie/options.rb +138 -0
  97. data/lib/selenium/webdriver/ie/service.rb +54 -0
  98. data/lib/selenium/webdriver/ie.rb +32 -10
  99. data/lib/selenium/webdriver/remote/bridge.rb +117 -572
  100. data/lib/selenium/webdriver/remote/capabilities.rb +116 -99
  101. data/lib/selenium/webdriver/remote/driver.rb +51 -0
  102. data/lib/selenium/webdriver/remote/http/common.rb +54 -23
  103. data/lib/selenium/webdriver/remote/http/curb.rb +30 -12
  104. data/lib/selenium/webdriver/remote/http/default.rb +85 -42
  105. data/lib/selenium/webdriver/remote/http/persistent.rb +29 -7
  106. data/lib/selenium/webdriver/remote/oss/bridge.rb +594 -0
  107. data/lib/selenium/webdriver/remote/oss/commands.rb +223 -0
  108. data/lib/selenium/webdriver/remote/response.rb +68 -30
  109. data/lib/selenium/webdriver/remote/server_error.rb +22 -5
  110. data/lib/selenium/webdriver/remote/w3c/bridge.rb +605 -0
  111. data/lib/selenium/webdriver/remote/w3c/capabilities.rb +310 -0
  112. data/lib/selenium/webdriver/remote/w3c/commands.rb +157 -0
  113. data/lib/selenium/webdriver/remote.rb +27 -13
  114. data/lib/selenium/webdriver/safari/bridge.rb +38 -107
  115. data/lib/selenium/webdriver/safari/driver.rb +68 -0
  116. data/lib/selenium/webdriver/safari/options.rb +56 -75
  117. data/lib/selenium/webdriver/safari/service.rb +38 -0
  118. data/lib/selenium/webdriver/safari.rb +49 -31
  119. data/lib/selenium/webdriver/support/abstract_event_listener.rb +40 -6
  120. data/lib/selenium/webdriver/support/block_event_listener.rb +24 -7
  121. data/lib/selenium/webdriver/support/color.rb +82 -46
  122. data/lib/selenium/webdriver/support/escaper.rb +43 -0
  123. data/lib/selenium/webdriver/support/event_firing_bridge.rb +56 -39
  124. data/lib/selenium/webdriver/support/select.rb +66 -89
  125. data/lib/selenium/webdriver/support.rb +20 -0
  126. data/lib/selenium/webdriver/version.rb +24 -0
  127. data/lib/selenium/webdriver.rb +55 -25
  128. data/lib/selenium-webdriver.rb +19 -0
  129. data/selenium-webdriver.gemspec +42 -29
  130. metadata +331 -260
  131. data/Gemfile.lock +0 -48
  132. data/lib/selenium/client/base.rb +0 -132
  133. data/lib/selenium/client/driver.rb +0 -10
  134. data/lib/selenium/client/errors.rb +0 -9
  135. data/lib/selenium/client/extensions.rb +0 -118
  136. data/lib/selenium/client/idiomatic.rb +0 -488
  137. data/lib/selenium/client/javascript_expression_builder.rb +0 -116
  138. data/lib/selenium/client/javascript_frameworks/jquery.rb +0 -13
  139. data/lib/selenium/client/javascript_frameworks/prototype.rb +0 -13
  140. data/lib/selenium/client/legacy_driver.rb +0 -1720
  141. data/lib/selenium/client/protocol.rb +0 -104
  142. data/lib/selenium/client/selenium_helper.rb +0 -34
  143. data/lib/selenium/client.rb +0 -38
  144. data/lib/selenium/rake/server_task.rb +0 -157
  145. data/lib/selenium/webdriver/android/bridge.rb +0 -49
  146. data/lib/selenium/webdriver/android.rb +0 -9
  147. data/lib/selenium/webdriver/common/core_ext/base64.rb +0 -9
  148. data/lib/selenium/webdriver/common/core_ext/dir.rb +0 -42
  149. data/lib/selenium/webdriver/common/core_ext/string.rb +0 -5
  150. data/lib/selenium/webdriver/common/driver_extensions/has_browser_connection.rb +0 -17
  151. data/lib/selenium/webdriver/common/driver_extensions/has_input_devices.rb +0 -39
  152. data/lib/selenium/webdriver/common/html5/location.rb +0 -0
  153. data/lib/selenium/webdriver/common/json_helper.rb +0 -34
  154. data/lib/selenium/webdriver/firefox/bridge.rb +0 -70
  155. data/lib/selenium/webdriver/firefox/socket_lock.rb +0 -61
  156. data/lib/selenium/webdriver/ie/bridge.rb +0 -69
  157. data/lib/selenium/webdriver/ie/server.rb +0 -90
  158. data/lib/selenium/webdriver/iphone/bridge.rb +0 -45
  159. data/lib/selenium/webdriver/iphone.rb +0 -9
  160. data/lib/selenium/webdriver/opera/bridge.rb +0 -112
  161. data/lib/selenium/webdriver/opera/service.rb +0 -49
  162. data/lib/selenium/webdriver/opera.rb +0 -24
  163. data/lib/selenium/webdriver/phantomjs/bridge.rb +0 -59
  164. data/lib/selenium/webdriver/phantomjs/service.rb +0 -90
  165. data/lib/selenium/webdriver/phantomjs.rb +0 -22
  166. data/lib/selenium/webdriver/remote/commands.rb +0 -192
  167. data/lib/selenium/webdriver/safari/browser.rb +0 -20
  168. data/lib/selenium/webdriver/safari/extensions.rb +0 -170
  169. data/lib/selenium/webdriver/safari/resources/SafariDriver.safariextz +0 -0
  170. data/lib/selenium/webdriver/safari/resources/client.js +0 -6903
  171. data/lib/selenium/webdriver/safari/server.rb +0 -145
  172. data/lib/selenium-client.rb +0 -2
@@ -0,0 +1,605 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Licensed to the Software Freedom Conservancy (SFC) under one
4
+ # or more contributor license agreements. See the NOTICE file
5
+ # distributed with this work for additional information
6
+ # regarding copyright ownership. The SFC licenses this file
7
+ # to you under the Apache License, Version 2.0 (the
8
+ # "License"); you may not use this file except in compliance
9
+ # with the License. You may obtain a copy of the License at
10
+ #
11
+ # http://www.apache.org/licenses/LICENSE-2.0
12
+ #
13
+ # Unless required by applicable law or agreed to in writing,
14
+ # software distributed under the License is distributed on an
15
+ # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16
+ # KIND, either express or implied. See the License for the
17
+ # specific language governing permissions and limitations
18
+ # under the License.
19
+
20
+ require 'json'
21
+
22
+ module Selenium
23
+ module WebDriver
24
+ module Remote
25
+ module W3C
26
+
27
+ #
28
+ # Low level bridge to the remote server implementing JSON wire
29
+ # protocol (W3C dialect), through which the rest of the API works.
30
+ # @api private
31
+ #
32
+
33
+ class Bridge < Remote::Bridge
34
+
35
+ def initialize(capabilities, session_id, **opts)
36
+ @capabilities = capabilities
37
+ @session_id = session_id
38
+ super(opts)
39
+ end
40
+
41
+ def dialect
42
+ :w3c
43
+ end
44
+
45
+ def commands(command)
46
+ case command
47
+ when :status
48
+ Remote::OSS::Bridge::COMMANDS[command]
49
+ else
50
+ COMMANDS[command]
51
+ end
52
+ end
53
+
54
+ def status
55
+ execute :status
56
+ end
57
+
58
+ def get(url)
59
+ execute :get, {}, {url: url}
60
+ end
61
+
62
+ def implicit_wait_timeout=(milliseconds)
63
+ timeout('implicit', milliseconds)
64
+ end
65
+
66
+ def script_timeout=(milliseconds)
67
+ timeout('script', milliseconds)
68
+ end
69
+
70
+ def timeout(type, milliseconds)
71
+ type = 'pageLoad' if type == 'page load'
72
+ execute :set_timeout, {}, {type => milliseconds}
73
+ end
74
+
75
+ #
76
+ # alerts
77
+ #
78
+
79
+ def accept_alert
80
+ execute :accept_alert
81
+ end
82
+
83
+ def dismiss_alert
84
+ execute :dismiss_alert
85
+ end
86
+
87
+ def alert=(keys)
88
+ execute :send_alert_text, {}, {value: keys.split(//), text: keys}
89
+ end
90
+
91
+ def alert_text
92
+ execute :get_alert_text
93
+ end
94
+
95
+ #
96
+ # navigation
97
+ #
98
+
99
+ def go_back
100
+ execute :back
101
+ end
102
+
103
+ def go_forward
104
+ execute :forward
105
+ end
106
+
107
+ def url
108
+ execute :get_current_url
109
+ end
110
+
111
+ def title
112
+ execute :get_title
113
+ end
114
+
115
+ def page_source
116
+ execute_script('var source = document.documentElement.outerHTML;' \
117
+ 'if (!source) { source = new XMLSerializer().serializeToString(document); }' \
118
+ 'return source;')
119
+ end
120
+
121
+ #
122
+ # Create a new top-level browsing context
123
+ # https://w3c.github.io/webdriver/#new-window
124
+ # @param type [String] Supports two values: 'tab' and 'window'.
125
+ # Use 'tab' if you'd like the new window to share an OS-level window
126
+ # with the current browsing context.
127
+ # Use 'window' otherwise
128
+ # @return [Hash] Containing 'handle' with the value of the window handle
129
+ # and 'type' with the value of the created window type
130
+ #
131
+ def new_window(type)
132
+ execute :new_window, {}, {type: type}
133
+ end
134
+
135
+ def switch_to_window(name)
136
+ execute :switch_to_window, {}, {handle: name}
137
+ end
138
+
139
+ def switch_to_frame(id)
140
+ id = find_element_by('id', id) if id.is_a? String
141
+ execute :switch_to_frame, {}, {id: id}
142
+ end
143
+
144
+ def switch_to_parent_frame
145
+ execute :switch_to_parent_frame
146
+ end
147
+
148
+ def switch_to_default_content
149
+ switch_to_frame nil
150
+ end
151
+
152
+ QUIT_ERRORS = [IOError].freeze
153
+
154
+ def quit
155
+ execute :delete_session
156
+ http.close
157
+ rescue *QUIT_ERRORS
158
+ end
159
+
160
+ def close
161
+ execute :close_window
162
+ end
163
+
164
+ def refresh
165
+ execute :refresh
166
+ end
167
+
168
+ #
169
+ # window handling
170
+ #
171
+
172
+ def window_handles
173
+ execute :get_window_handles
174
+ end
175
+
176
+ def window_handle
177
+ execute :get_window_handle
178
+ end
179
+
180
+ def resize_window(width, height, handle = :current)
181
+ raise Error::WebDriverError, 'Switch to desired window before changing its size' unless handle == :current
182
+
183
+ set_window_rect(width: width, height: height)
184
+ end
185
+
186
+ def window_size(handle = :current)
187
+ raise Error::UnsupportedOperationError, 'Switch to desired window before getting its size' unless handle == :current
188
+
189
+ data = execute :get_window_rect
190
+
191
+ Dimension.new data['width'], data['height']
192
+ end
193
+
194
+ def minimize_window
195
+ execute :minimize_window
196
+ end
197
+
198
+ def maximize_window(handle = :current)
199
+ raise Error::UnsupportedOperationError, 'Switch to desired window before changing its size' unless handle == :current
200
+
201
+ execute :maximize_window
202
+ end
203
+
204
+ def full_screen_window
205
+ execute :fullscreen_window
206
+ end
207
+
208
+ def reposition_window(x, y)
209
+ set_window_rect(x: x, y: y)
210
+ end
211
+
212
+ def window_position
213
+ data = execute :get_window_rect
214
+ Point.new data['x'], data['y']
215
+ end
216
+
217
+ def set_window_rect(x: nil, y: nil, width: nil, height: nil)
218
+ params = {x: x, y: y, width: width, height: height}
219
+ params.update(params) { |_k, v| Integer(v) unless v.nil? }
220
+ execute :set_window_rect, {}, params
221
+ end
222
+
223
+ def window_rect
224
+ data = execute :get_window_rect
225
+ Rectangle.new data['x'], data['y'], data['width'], data['height']
226
+ end
227
+
228
+ def screenshot
229
+ execute :take_screenshot
230
+ end
231
+
232
+ #
233
+ # HTML 5
234
+ #
235
+
236
+ def local_storage_item(key, value = nil)
237
+ if value
238
+ execute_script("localStorage.setItem('#{key}', '#{value}')")
239
+ else
240
+ execute_script("return localStorage.getItem('#{key}')")
241
+ end
242
+ end
243
+
244
+ def remove_local_storage_item(key)
245
+ execute_script("localStorage.removeItem('#{key}')")
246
+ end
247
+
248
+ def local_storage_keys
249
+ execute_script('return Object.keys(localStorage)')
250
+ end
251
+
252
+ def clear_local_storage
253
+ execute_script('localStorage.clear()')
254
+ end
255
+
256
+ def local_storage_size
257
+ execute_script('return localStorage.length')
258
+ end
259
+
260
+ def session_storage_item(key, value = nil)
261
+ if value
262
+ execute_script("sessionStorage.setItem('#{key}', '#{value}')")
263
+ else
264
+ execute_script("return sessionStorage.getItem('#{key}')")
265
+ end
266
+ end
267
+
268
+ def remove_session_storage_item(key)
269
+ execute_script("sessionStorage.removeItem('#{key}')")
270
+ end
271
+
272
+ def session_storage_keys
273
+ execute_script('return Object.keys(sessionStorage)')
274
+ end
275
+
276
+ def clear_session_storage
277
+ execute_script('sessionStorage.clear()')
278
+ end
279
+
280
+ def session_storage_size
281
+ execute_script('return sessionStorage.length')
282
+ end
283
+
284
+ def location
285
+ raise Error::UnsupportedOperationError, 'The W3C standard does not currently support getting location'
286
+ end
287
+
288
+ def set_location(_lat, _lon, _alt)
289
+ raise Error::UnsupportedOperationError, 'The W3C standard does not currently support setting location'
290
+ end
291
+
292
+ def network_connection
293
+ raise Error::UnsupportedOperationError, 'The W3C standard does not currently support getting network connection'
294
+ end
295
+
296
+ def network_connection=(_type)
297
+ raise Error::UnsupportedOperationError, 'The W3C standard does not currently support setting network connection'
298
+ end
299
+
300
+ #
301
+ # javascript execution
302
+ #
303
+
304
+ def execute_script(script, *args)
305
+ result = execute :execute_script, {}, {script: script, args: args}
306
+ unwrap_script_result result
307
+ end
308
+
309
+ def execute_async_script(script, *args)
310
+ result = execute :execute_async_script, {}, {script: script, args: args}
311
+ unwrap_script_result result
312
+ end
313
+
314
+ #
315
+ # cookies
316
+ #
317
+
318
+ def manage
319
+ @manage ||= WebDriver::W3CManager.new(self)
320
+ end
321
+
322
+ def add_cookie(cookie)
323
+ execute :add_cookie, {}, {cookie: cookie}
324
+ end
325
+
326
+ def delete_cookie(name)
327
+ execute :delete_cookie, name: name
328
+ end
329
+
330
+ def cookie(name)
331
+ execute :get_cookie, name: name
332
+ end
333
+
334
+ def cookies
335
+ execute :get_all_cookies
336
+ end
337
+
338
+ def delete_all_cookies
339
+ execute :delete_all_cookies
340
+ end
341
+
342
+ #
343
+ # actions
344
+ #
345
+
346
+ def action(async = false)
347
+ W3CActionBuilder.new self,
348
+ Interactions.pointer(:mouse, name: 'mouse'),
349
+ Interactions.key('keyboard'),
350
+ async
351
+ end
352
+ alias_method :actions, :action
353
+
354
+ def mouse
355
+ raise Error::UnsupportedOperationError, '#mouse is no longer supported, use #action instead'
356
+ end
357
+
358
+ def keyboard
359
+ raise Error::UnsupportedOperationError, '#keyboard is no longer supported, use #action instead'
360
+ end
361
+
362
+ def send_actions(data)
363
+ execute :actions, {}, {actions: data}
364
+ end
365
+
366
+ def release_actions
367
+ execute :release_actions
368
+ end
369
+
370
+ def click_element(element)
371
+ execute :element_click, id: element
372
+ end
373
+
374
+ def send_keys_to_element(element, keys)
375
+ # TODO: rework file detectors before Selenium 4.0
376
+ if @file_detector
377
+ local_files = keys.first.split("\n").map { |key| @file_detector.call(Array(key)) }.compact
378
+ if local_files.any?
379
+ keys = local_files.map { |local_file| upload(local_file) }
380
+ keys = Array(keys.join("\n"))
381
+ end
382
+ end
383
+
384
+ # Keep .split(//) for backward compatibility for now
385
+ text = keys.join('')
386
+ execute :element_send_keys, {id: element}, {value: text.split(//), text: text}
387
+ end
388
+
389
+ def upload(local_file)
390
+ unless File.file?(local_file)
391
+ WebDriver.logger.debug("File detector only works with files. #{local_file.inspect} isn`t a file!")
392
+ raise Error::WebDriverError, "You are trying to work with something that isn't a file."
393
+ end
394
+
395
+ execute :upload_file, {}, {file: Zipper.zip_file(local_file)}
396
+ end
397
+
398
+ def clear_element(element)
399
+ execute :element_clear, id: element
400
+ end
401
+
402
+ def submit_element(element)
403
+ form = find_element_by('xpath', "./ancestor-or-self::form", element)
404
+ execute_script("var e = arguments[0].ownerDocument.createEvent('Event');" \
405
+ "e.initEvent('submit', true, true);" \
406
+ 'if (arguments[0].dispatchEvent(e)) { arguments[0].submit() }', form.as_json)
407
+ end
408
+
409
+ def drag_element(element, right_by, down_by)
410
+ execute :drag_element, {id: element}, {x: right_by, y: down_by}
411
+ end
412
+
413
+ def touch_single_tap(element)
414
+ execute :touch_single_tap, {}, {element: element}
415
+ end
416
+
417
+ def touch_double_tap(element)
418
+ execute :touch_double_tap, {}, {element: element}
419
+ end
420
+
421
+ def touch_long_press(element)
422
+ execute :touch_long_press, {}, {element: element}
423
+ end
424
+
425
+ def touch_down(x, y)
426
+ execute :touch_down, {}, {x: x, y: y}
427
+ end
428
+
429
+ def touch_up(x, y)
430
+ execute :touch_up, {}, {x: x, y: y}
431
+ end
432
+
433
+ def touch_move(x, y)
434
+ execute :touch_move, {}, {x: x, y: y}
435
+ end
436
+
437
+ def touch_scroll(element, x, y)
438
+ if element
439
+ execute :touch_scroll, {}, {element: element,
440
+ xoffset: x,
441
+ yoffset: y}
442
+ else
443
+ execute :touch_scroll, {}, {xoffset: x, yoffset: y}
444
+ end
445
+ end
446
+
447
+ def touch_flick(xspeed, yspeed)
448
+ execute :touch_flick, {}, {xspeed: xspeed, yspeed: yspeed}
449
+ end
450
+
451
+ def touch_element_flick(element, right_by, down_by, speed)
452
+ execute :touch_flick, {}, {element: element,
453
+ xoffset: right_by,
454
+ yoffset: down_by,
455
+ speed: speed}
456
+ end
457
+
458
+ def screen_orientation=(orientation)
459
+ execute :set_screen_orientation, {}, {orientation: orientation}
460
+ end
461
+
462
+ def screen_orientation
463
+ execute :get_screen_orientation
464
+ end
465
+
466
+ #
467
+ # element properties
468
+ #
469
+
470
+ def element_tag_name(element)
471
+ execute :get_element_tag_name, id: element
472
+ end
473
+
474
+ def element_attribute(element, name)
475
+ WebDriver.logger.info "Using script for :getAttribute of #{name}"
476
+ execute_atom :getAttribute, element, name
477
+ end
478
+
479
+ def element_property(element, name)
480
+ execute :get_element_property, id: element.ref, name: name
481
+ end
482
+
483
+ def element_value(element)
484
+ element_property element, 'value'
485
+ end
486
+
487
+ def element_text(element)
488
+ execute :get_element_text, id: element
489
+ end
490
+
491
+ def element_location(element)
492
+ data = execute :get_element_rect, id: element
493
+
494
+ Point.new data['x'], data['y']
495
+ end
496
+
497
+ def element_rect(element)
498
+ data = execute :get_element_rect, id: element
499
+
500
+ Rectangle.new data['x'], data['y'], data['width'], data['height']
501
+ end
502
+
503
+ def element_location_once_scrolled_into_view(element)
504
+ send_keys_to_element(element, [''])
505
+ element_location(element)
506
+ end
507
+
508
+ def element_size(element)
509
+ data = execute :get_element_rect, id: element
510
+
511
+ Dimension.new data['width'], data['height']
512
+ end
513
+
514
+ def element_enabled?(element)
515
+ execute :is_element_enabled, id: element
516
+ end
517
+
518
+ def element_selected?(element)
519
+ execute :is_element_selected, id: element
520
+ end
521
+
522
+ def element_displayed?(element)
523
+ WebDriver.logger.info 'Using script for :isDisplayed'
524
+ execute_atom :isDisplayed, element
525
+ end
526
+
527
+ def element_value_of_css_property(element, prop)
528
+ execute :get_element_css_value, id: element, property_name: prop
529
+ end
530
+
531
+ #
532
+ # finding elements
533
+ #
534
+
535
+ def active_element
536
+ Element.new self, element_id_from(execute(:get_active_element))
537
+ end
538
+
539
+ alias_method :switch_to_active_element, :active_element
540
+
541
+ def find_element_by(how, what, parent = nil)
542
+ how, what = convert_locators(how, what)
543
+
544
+ id = if parent
545
+ execute :find_child_element, {id: parent}, {using: how, value: what}
546
+ else
547
+ execute :find_element, {}, {using: how, value: what}
548
+ end
549
+ Element.new self, element_id_from(id)
550
+ end
551
+
552
+ def find_elements_by(how, what, parent = nil)
553
+ how, what = convert_locators(how, what)
554
+
555
+ ids = if parent
556
+ execute :find_child_elements, {id: parent}, {using: how, value: what}
557
+ else
558
+ execute :find_elements, {}, {using: how, value: what}
559
+ end
560
+
561
+ ids.map { |id| Element.new self, element_id_from(id) }
562
+ end
563
+
564
+ private
565
+
566
+ def execute(*)
567
+ super['value']
568
+ end
569
+
570
+ def convert_locators(how, what)
571
+ case how
572
+ when 'class name'
573
+ how = 'css selector'
574
+ what = ".#{escape_css(what)}"
575
+ when 'id'
576
+ how = 'css selector'
577
+ what = "##{escape_css(what)}"
578
+ when 'name'
579
+ how = 'css selector'
580
+ what = "*[name='#{escape_css(what)}']"
581
+ when 'tag name'
582
+ how = 'css selector'
583
+ end
584
+ [how, what]
585
+ end
586
+
587
+ ESCAPE_CSS_REGEXP = /(['"\\#.:;,!?+<>=~*^$|%&@`{}\-\[\]\(\)])/.freeze
588
+ UNICODE_CODE_POINT = 30
589
+
590
+ # Escapes invalid characters in CSS selector.
591
+ # @see https://mathiasbynens.be/notes/css-escapes
592
+ def escape_css(string)
593
+ string = string.gsub(ESCAPE_CSS_REGEXP) { |match| "\\#{match}" }
594
+ if !string.empty? && string[0] =~ /[[:digit:]]/
595
+ string = "\\#{UNICODE_CODE_POINT + Integer(string[0])} #{string[1..-1]}"
596
+ end
597
+
598
+ string
599
+ end
600
+
601
+ end # Bridge
602
+ end # W3C
603
+ end # Remote
604
+ end # WebDriver
605
+ end # Selenium