selenium-webdriver 2.45.0 → 3.142.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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
@@ -1,634 +1,161 @@
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
+
1
20
  module Selenium
2
21
  module WebDriver
3
22
  module Remote
4
-
5
- COMMANDS = {}
6
-
7
- #
8
- # Low level bridge to the remote server, through which the rest of the API works.
9
- #
10
- # @api private
11
- #
12
-
13
23
  class Bridge
24
+ include Atoms
14
25
  include BridgeHelper
15
26
 
16
- #
17
- # Defines a wrapper method for a command, which ultimately calls #execute.
18
- #
19
- # @param name [Symbol]
20
- # name of the resulting method
21
- # @param url [String]
22
- # a URL template, which can include some arguments, much like the definitions on the server.
23
- # the :session_id parameter is implicitly handled, but the remainder will become required method arguments.
24
- # @param verb [Symbol]
25
- # the appropriate http verb, such as :get, :post, or :delete
26
- #
27
-
28
- def self.command(name, verb, url)
29
- COMMANDS[name] = [verb, url.freeze]
30
- end
27
+ PORT = 4444
28
+ COMMANDS = {
29
+ new_session: [:post, 'session']
30
+ }.freeze
31
31
 
32
32
  attr_accessor :context, :http, :file_detector
33
- attr_reader :capabilities
33
+ attr_reader :capabilities, :dialect
34
34
 
35
35
  #
36
- # Initializes the bridge with the given server URL.
36
+ # Implements protocol handshake which:
37
37
  #
38
- # @param url [String] url for the remote server
39
- # @param http_client [Object] an HTTP client instance that implements the same protocol as Http::Default
40
- # @param desired_capabilities [Capabilities] an instance of Remote::Capabilities describing the capabilities you want
38
+ # 1. Creates session with driver.
39
+ # 2. Sniffs response.
40
+ # 3. Based on the response, understands which dialect we should use.
41
41
  #
42
+ # @return [OSS:Bridge, W3C::Bridge]
43
+ #
44
+ def self.handshake(**opts)
45
+ desired_capabilities = opts.delete(:desired_capabilities) { Capabilities.new }
42
46
 
43
- def initialize(opts = {})
44
- opts = opts.dup
45
-
46
- http_client = opts.delete(:http_client) { Http::Default.new }
47
- desired_capabilities = opts.delete(:desired_capabilities) { Capabilities.firefox }
48
- url = opts.delete(:url) { "http://#{Platform.localhost}:4444/wd/hub" }
49
-
50
- unless opts.empty?
51
- raise ArgumentError, "unknown option#{'s' if opts.size != 1}: #{opts.inspect}"
52
- end
53
-
54
- if desired_capabilities.kind_of?(Symbol)
47
+ if desired_capabilities.is_a?(Symbol)
55
48
  unless Capabilities.respond_to?(desired_capabilities)
56
49
  raise Error::WebDriverError, "invalid desired capability: #{desired_capabilities.inspect}"
57
50
  end
58
51
 
59
- desired_capabilities = Capabilities.send(desired_capabilities)
60
- end
61
-
62
- uri = url.kind_of?(URI) ? url : URI.parse(url)
63
- uri.path += "/" unless uri.path =~ /\/$/
64
-
65
- http_client.server_url = uri
66
-
67
- @http = http_client
68
- @capabilities = create_session(desired_capabilities)
69
-
70
- @file_detector = nil
71
- end
72
-
73
- def browser
74
- @browser ||= (
75
- name = @capabilities.browser_name
76
- name ? name.gsub(" ", "_").to_sym : 'unknown'
77
- )
78
- end
79
-
80
- def driver_extensions
81
- [
82
- DriverExtensions::HasInputDevices,
83
- DriverExtensions::UploadsFiles,
84
- DriverExtensions::TakesScreenshot,
85
- DriverExtensions::HasSessionId,
86
- DriverExtensions::Rotatable,
87
- DriverExtensions::HasTouchScreen,
88
- DriverExtensions::HasRemoteStatus
89
- ]
90
- end
91
-
92
- #
93
- # Returns the current session ID.
94
- #
95
-
96
- def session_id
97
- @session_id || raise(Error::WebDriverError, "no current session exists")
98
- end
99
-
100
- def create_session(desired_capabilities)
101
- resp = raw_execute :newSession, {}, :desiredCapabilities => desired_capabilities
102
- @session_id = resp['sessionId'] or raise Error::WebDriverError, 'no sessionId in returned payload'
103
-
104
- Capabilities.json_create resp['value']
105
- end
106
-
107
- def status
108
- execute :status
109
- end
110
-
111
- def get(url)
112
- execute :get, {}, :url => url
113
- end
114
-
115
- def getCapabilities
116
- Capabilities.json_create execute(:getCapabilities)
117
- end
118
-
119
- def setImplicitWaitTimeout(milliseconds)
120
- execute :implicitlyWait, {}, :ms => milliseconds
121
- end
122
-
123
- def setScriptTimeout(milliseconds)
124
- execute :setScriptTimeout, {}, :ms => milliseconds
125
- end
126
-
127
- def setTimeout(type, milliseconds)
128
- execute :setTimeout, {}, :type => type, :ms => milliseconds
129
- end
130
-
131
- #
132
- # alerts
133
- #
134
-
135
- def getAlert
136
- execute :getAlert
137
- end
138
-
139
- def acceptAlert
140
- execute :acceptAlert
141
- end
142
-
143
- def dismissAlert
144
- execute :dismissAlert
145
- end
146
-
147
- def setAlertValue(keys)
148
- execute :setAlertValue, {}, :text => keys.to_s
149
- end
150
-
151
- def getAlertText
152
- execute :getAlertText
153
- end
154
-
155
- #
156
- # navigation
157
- #
158
-
159
- def goBack
160
- execute :goBack
161
- end
162
-
163
- def goForward
164
- execute :goForward
165
- end
166
-
167
- def getCurrentUrl
168
- execute :getCurrentUrl
169
- end
170
-
171
- def getTitle
172
- execute :getTitle
173
- end
174
-
175
- def getPageSource
176
- execute :getPageSource
177
- end
178
-
179
- def getVisible
180
- execute :getVisible
181
- end
182
-
183
- def setVisible(bool)
184
- execute :setVisible, {}, bool
185
- end
186
-
187
- def switchToWindow(name)
188
- execute :switchToWindow, {}, :name => name
189
- end
190
-
191
- def switchToFrame(id)
192
- execute :switchToFrame, {}, :id => id
193
- end
194
-
195
- def switchToParentFrame
196
- execute :switchToParentFrame
197
- end
198
-
199
- def switchToDefaultContent
200
- execute :switchToFrame, {}, :id => nil
201
- end
202
-
203
- QUIT_ERRORS = [IOError]
204
-
205
- def quit
206
- execute :quit
207
- http.close
208
- rescue *QUIT_ERRORS
209
- end
210
-
211
- def close
212
- execute :close
213
- end
214
-
215
- def refresh
216
- execute :refresh
217
- end
218
-
219
- #
220
- # window handling
221
- #
222
-
223
- def getWindowHandles
224
- execute :getWindowHandles
225
- end
226
-
227
- def getCurrentWindowHandle
228
- execute :getCurrentWindowHandle
229
- end
230
-
231
- def setWindowSize(width, height, handle = :current)
232
- execute :setWindowSize, {:window_handle => handle},
233
- :width => width,
234
- :height => height
235
- end
236
-
237
- def maximizeWindow(handle = :current)
238
- execute :maximizeWindow, :window_handle => handle
239
- end
240
-
241
- def getWindowSize(handle = :current)
242
- data = execute :getWindowSize, :window_handle => handle
243
-
244
- Dimension.new data['width'], data['height']
245
- end
246
-
247
- def setWindowPosition(x, y, handle = :current)
248
- execute :setWindowPosition, {:window_handle => handle},
249
- :x => x, :y => y
250
- end
251
-
252
- def getWindowPosition(handle = :current)
253
- data = execute :getWindowPosition, :window_handle => handle
254
-
255
- Point.new data['x'], data['y']
256
- end
257
-
258
- def getScreenshot
259
- execute :screenshot
260
- end
261
-
262
- #
263
- # HTML 5
264
- #
265
-
266
- def getLocalStorageItem(key)
267
- execute :getLocalStorageItem, :key => key
268
- end
269
-
270
- def removeLocalStorageItem(key)
271
- execute :removeLocalStorageItem, :key => key
272
- end
273
-
274
- def getLocalStorageKeys
275
- execute :getLocalStorageKeys
276
- end
277
-
278
- def setLocalStorageItem(key, value)
279
- execute :setLocalStorageItem, {}, :key => key, :value => value
280
- end
281
-
282
- def clearLocalStorage
283
- execute :clearLocalStorage
284
- end
285
-
286
- def getLocalStorageSize
287
- execute :getLocalStorageSize
288
- end
289
-
290
- def getSessionStorageItem(key)
291
- execute :getSessionStorageItem, :key => key
292
- end
293
-
294
- def removeSessionStorageItem(key)
295
- execute :removeSessionStorageItem, :key => key
296
- end
297
-
298
- def getSessionStorageKeys
299
- execute :getSessionStorageKeys
300
- end
301
-
302
- def setSessionStorageItem(key, value)
303
- execute :setSessionStorageItem, {}, :key => key, :value => value
304
- end
305
-
306
- def clearSessionStorage
307
- execute :clearSessionStorage
308
- end
309
-
310
- def getSessionStorageSize
311
- execute :getSessionStorageSize
312
- end
313
-
314
- def getLocation
315
- obj = execute(:getLocation) || {} # android returns null
316
- Location.new obj['latitude'], obj['longitude'], obj['altitude']
317
- end
318
-
319
- def setLocation(lat, lon, alt)
320
- loc = {:latitude => lat, :longitude => lon, :altitude => alt}
321
- execute :setLocation, {}, :location => loc
322
- end
323
-
324
- def isBrowserOnline
325
- execute :isBrowserOnline
326
- end
327
-
328
- def setBrowserOnline(bool)
329
- execute :setBrowserOnline, {}, :state => bool
330
- end
331
-
332
- #
333
- # javascript execution
334
- #
335
-
336
- def executeScript(script, *args)
337
- assert_javascript_enabled
338
-
339
- result = execute :executeScript, {}, :script => script, :args => args
340
- unwrap_script_result result
341
- end
342
-
343
- def executeAsyncScript(script, *args)
344
- assert_javascript_enabled
345
-
346
- result = execute :executeAsyncScript, {}, :script => script, :args => args
347
- unwrap_script_result result
348
- end
349
-
350
- #
351
- # cookies
352
- #
353
-
354
- def addCookie(cookie)
355
- execute :addCookie, {}, :cookie => cookie
356
- end
357
-
358
- def deleteCookie(name)
359
- execute :deleteCookie, :name => name
360
- end
361
-
362
- def getAllCookies
363
- execute :getCookies
364
- end
365
-
366
- def deleteAllCookies
367
- execute :deleteAllCookies
368
- end
369
-
370
- #
371
- # actions
372
- #
373
-
374
- def clickElement(element)
375
- execute :clickElement, :id => element
376
- end
377
-
378
- def click
379
- execute :click, {}, :button => 0
380
- end
381
-
382
- def doubleClick
383
- execute :doubleClick
384
- end
385
-
386
- def contextClick
387
- execute :click, {}, :button => 2
388
- end
389
-
390
- def mouseDown
391
- execute :mouseDown
392
- end
393
-
394
- def mouseUp
395
- execute :mouseUp
396
- end
397
-
398
- def mouseMoveTo(element, x = nil, y = nil)
399
- params = { :element => element }
400
-
401
- if x && y
402
- params.merge! :xoffset => x, :yoffset => y
403
- end
404
-
405
- execute :mouseMoveTo, {}, params
406
- end
407
-
408
- def sendKeysToActiveElement(key)
409
- execute :sendKeysToActiveElement, {}, :value => key
410
- end
411
-
412
- def sendKeysToElement(element, keys)
413
- if @file_detector && local_file = @file_detector.call(keys)
414
- keys = upload(local_file)
52
+ desired_capabilities = Capabilities.__send__(desired_capabilities)
415
53
  end
416
54
 
417
- execute :sendKeysToElement, {:id => element}, {:value => Array(keys)}
418
- end
419
-
420
- def upload(local_file)
421
- unless File.file?(local_file)
422
- raise Error::WebDriverError, "you may only upload files: #{local_file.inspect}"
423
- end
424
-
425
- execute :uploadFile, {}, :file => Zipper.zip_file(local_file)
426
- end
427
-
428
- def clearElement(element)
429
- execute :clearElement, :id => element
430
- end
431
-
432
-
433
- def submitElement(element)
434
- execute :submitElement, :id => element
435
- end
436
-
437
- def dragElement(element, right_by, down_by)
438
- execute :dragElement, {:id => element}, :x => right_by, :y => down_by
439
- end
440
-
441
- def touchSingleTap(element)
442
- execute :touchSingleTap, {}, :element => element
443
- end
444
-
445
- def touchDoubleTap(element)
446
- execute :touchDoubleTap, {}, :element => element
447
- end
448
-
449
- def touchLongPress(element)
450
- execute :touchLongPress, {}, :element => element
451
- end
452
-
453
- def touchDown(x, y)
454
- execute :touchDown, {}, :x => x, :y => y
455
- end
55
+ bridge = new(opts)
56
+ capabilities = bridge.create_session(desired_capabilities, opts.delete(:options))
456
57
 
457
- def touchUp(x, y)
458
- execute :touchUp, {}, :x => x, :y => y
459
- end
460
-
461
- def touchMove(x, y)
462
- execute :touchMove, {}, :x => x, :y => y
463
- end
464
-
465
- def touchScroll(element, x, y)
466
- if element
467
- execute :touchScroll, {}, :element => element,
468
- :xoffset => x,
469
- :yoffset => y
58
+ case bridge.dialect
59
+ when :oss
60
+ Remote::OSS::Bridge.new(capabilities, bridge.session_id, **opts)
61
+ when :w3c
62
+ Remote::W3C::Bridge.new(capabilities, bridge.session_id, **opts)
470
63
  else
471
- execute :touchScroll, {}, :xoffset => x, :yoffset => y
64
+ raise WebDriverError, 'cannot understand dialect'
472
65
  end
473
66
  end
474
67
 
475
- def touchFlick(xspeed, yspeed)
476
- execute :touchFlick, {}, :xspeed => xspeed, :yspeed => yspeed
477
- end
478
-
479
- def touchElementFlick(element, right_by, down_by, speed)
480
- execute :touchFlick, {}, :element => element,
481
- :xoffset => right_by,
482
- :yoffset => down_by,
483
- :speed => speed
484
-
485
- end
486
-
487
- def setScreenOrientation(orientation)
488
- execute :setScreenOrientation, {}, :orientation => orientation
489
- end
490
-
491
- def getScreenOrientation
492
- execute :getScreenOrientation
493
- end
494
-
495
68
  #
496
- # logs
69
+ # Initializes the bridge with the given server URL
70
+ # @param [Hash] opts options for the driver
71
+ # @option opts [String] :url url for the remote server
72
+ # @option opts [Object] :http_client an HTTP client instance that implements the same protocol as Http::Default
73
+ # @option opts [Capabilities] :desired_capabilities an instance of Remote::Capabilities describing the capabilities you want
74
+ # @api private
497
75
  #
498
76
 
499
- def getAvailableLogTypes
500
- types = execute :getAvailableLogTypes
501
- Array(types).map { |e| e.to_sym }
502
- end
77
+ def initialize(opts = {})
78
+ opts = opts.dup
503
79
 
504
- def getLog(type)
505
- data = execute :getLog, {}, :type => type.to_s
80
+ http_client = opts.delete(:http_client) { Http::Default.new }
81
+ url = opts.delete(:url) { "http://#{Platform.localhost}:#{PORT}/wd/hub" }
82
+ opts.delete(:options)
506
83
 
507
- Array(data).map do |l|
508
- LogEntry.new l.fetch('level'), l.fetch('timestamp'), l.fetch('message')
84
+ unless opts.empty?
85
+ raise ArgumentError, "unknown option#{'s' if opts.size != 1}: #{opts.inspect}"
509
86
  end
510
- end
511
-
512
- #
513
- # element properties
514
- #
515
-
516
- def getElementTagName(element)
517
- execute :getElementTagName, :id => element
518
- end
519
-
520
- def getElementAttribute(element, name)
521
- execute :getElementAttribute, :id => element, :name => name
522
- end
523
87
 
524
- def getElementValue(element)
525
- execute :getElementValue, :id => element
526
- end
88
+ uri = url.is_a?(URI) ? url : URI.parse(url)
89
+ uri.path += '/' unless uri.path =~ %r{\/$}
527
90
 
528
- def getElementText(element)
529
- execute :getElementText, :id => element
530
- end
531
-
532
- def getElementLocation(element)
533
- data = execute :getElementLocation, :id => element
91
+ http_client.server_url = uri
534
92
 
535
- Point.new data['x'], data['y']
93
+ @http = http_client
94
+ @file_detector = nil
536
95
  end
537
96
 
538
- def getElementLocationOnceScrolledIntoView(element)
539
- data = execute :getElementLocationOnceScrolledIntoView, :id => element
540
-
541
- Point.new data['x'], data['y']
542
- end
97
+ #
98
+ # Creates session handling both OSS and W3C dialects.
99
+ #
543
100
 
544
- def getElementSize(element)
545
- data = execute :getElementSize, :id => element
101
+ def create_session(desired_capabilities, options = nil)
102
+ response = execute(:new_session, {}, merged_capabilities(desired_capabilities, options))
546
103
 
547
- Dimension.new data['width'], data['height']
548
- end
104
+ @session_id = response['sessionId']
105
+ oss_status = response['status']
106
+ value = response['value']
549
107
 
550
- def isElementEnabled(element)
551
- execute :isElementEnabled, :id => element
552
- end
108
+ if value.is_a?(Hash)
109
+ @session_id = value['sessionId'] if value.key?('sessionId')
553
110
 
554
- def isElementSelected(element)
555
- execute :isElementSelected, :id => element
556
- end
111
+ if value.key?('capabilities')
112
+ value = value['capabilities']
113
+ elsif value.key?('value')
114
+ value = value['value']
115
+ end
116
+ end
557
117
 
558
- def isElementDisplayed(element)
559
- execute :isElementDisplayed, :id => element
560
- end
561
- def getElementValueOfCssProperty(element, prop)
562
- execute :getElementValueOfCssProperty, :id => element, :property_name => prop
563
- end
118
+ raise Error::WebDriverError, 'no sessionId in returned payload' unless @session_id
564
119
 
565
- def elementEquals(element, other)
566
- if element.ref == other.ref
567
- true
120
+ if oss_status
121
+ WebDriver.logger.info 'Detected OSS dialect.'
122
+ @dialect = :oss
123
+ Capabilities.json_create(value)
568
124
  else
569
- execute :elementEquals, :id => element.ref, :other => other.ref
125
+ WebDriver.logger.info 'Detected W3C dialect.'
126
+ @dialect = :w3c
127
+ W3C::Capabilities.json_create(value)
570
128
  end
571
129
  end
572
130
 
573
131
  #
574
- # finding elements
132
+ # Returns the current session ID.
575
133
  #
576
134
 
577
- def getActiveElement
578
- Element.new self, element_id_from(execute(:getActiveElement))
579
- end
580
- alias_method :switchToActiveElement, :getActiveElement
581
-
582
- def find_element_by(how, what, parent = nil)
583
- if parent
584
- id = execute :findChildElement, {:id => parent}, {:using => how, :value => what}
585
- else
586
- id = execute :findElement, {}, {:using => how, :value => what}
587
- end
588
-
589
- Element.new self, element_id_from(id)
135
+ def session_id
136
+ @session_id || raise(Error::WebDriverError, 'no current session exists')
590
137
  end
591
138
 
592
- def find_elements_by(how, what, parent = nil)
593
- if parent
594
- ids = execute :findChildElements, {:id => parent}, {:using => how, :value => what}
595
- else
596
- ids = execute :findElements, {}, {:using => how, :value => what}
139
+ def browser
140
+ @browser ||= begin
141
+ name = @capabilities.browser_name
142
+ name ? name.tr(' ', '_').to_sym : 'unknown'
597
143
  end
598
-
599
- ids.map { |id| Element.new self, element_id_from(id) }
600
144
  end
601
145
 
602
146
  private
603
147
 
604
- def assert_javascript_enabled
605
- unless capabilities.javascript_enabled?
606
- raise Error::UnsupportedOperationError, "underlying webdriver instance does not support javascript"
607
- end
608
- end
609
-
610
- #
611
- # executes a command on the remote server.
612
- #
613
- #
614
- # Returns the 'value' of the returned payload
615
- #
616
-
617
- def execute(*args)
618
- raw_execute(*args)['value']
619
- end
620
-
621
148
  #
622
149
  # executes a command on the remote server.
623
150
  #
624
151
  # @return [WebDriver::Remote::Response]
625
152
  #
626
153
 
627
- def raw_execute(command, opts = {}, command_hash = nil)
628
- verb, path = COMMANDS[command] || raise(ArgumentError, "unknown command: #{command.inspect}")
629
- path = path.dup
154
+ def execute(command, opts = {}, command_hash = nil)
155
+ verb, path = commands(command) || raise(ArgumentError, "unknown command: #{command.inspect}")
156
+ path = path.dup
630
157
 
631
- path[':session_id'] = @session_id if path.include?(":session_id")
158
+ path[':session_id'] = session_id if path.include?(':session_id')
632
159
 
633
160
  begin
634
161
  opts.each { |key, value| path[key.inspect] = escaper.escape(value.to_s) }
@@ -636,12 +163,30 @@ module Selenium
636
163
  raise ArgumentError, "#{opts.inspect} invalid for #{command.inspect}"
637
164
  end
638
165
 
639
- puts "-> #{verb.to_s.upcase} #{path}" if $DEBUG
640
- http.call verb, path, command_hash
166
+ WebDriver.logger.info("-> #{verb.to_s.upcase} #{path}")
167
+ http.call(verb, path, command_hash)
641
168
  end
642
169
 
643
170
  def escaper
644
- @escaper ||= defined?(URI::Parser) ? URI::Parser.new : URI
171
+ @escaper ||= defined?(URI::Parser) ? URI::DEFAULT_PARSER : URI
172
+ end
173
+
174
+ def commands(command)
175
+ raise NotImplementedError unless command == :new_session
176
+
177
+ COMMANDS[command]
178
+ end
179
+
180
+ def merged_capabilities(oss_capabilities, options = nil)
181
+ w3c_capabilities = W3C::Capabilities.from_oss(oss_capabilities)
182
+ w3c_capabilities.merge!(options.as_json) if options
183
+
184
+ {
185
+ desiredCapabilities: oss_capabilities,
186
+ capabilities: {
187
+ firstMatch: [w3c_capabilities]
188
+ }
189
+ }
645
190
  end
646
191
 
647
192
  end # Bridge