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