selenium-webdriver 2.53.4 → 3.8.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (152) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGES +363 -10
  3. data/LICENSE +1 -1
  4. data/README.md +2 -3
  5. data/lib/selenium-webdriver.rb +0 -2
  6. data/lib/selenium/server.rb +69 -70
  7. data/lib/selenium/webdriver.rb +32 -23
  8. data/lib/selenium/webdriver/atoms.rb +18 -0
  9. data/lib/selenium/webdriver/atoms/getAttribute.js +8 -0
  10. data/lib/selenium/webdriver/chrome.rb +8 -6
  11. data/lib/selenium/webdriver/chrome/driver.rb +112 -0
  12. data/lib/selenium/webdriver/chrome/options.rb +168 -0
  13. data/lib/selenium/webdriver/chrome/profile.rb +17 -17
  14. data/lib/selenium/webdriver/chrome/service.rb +22 -89
  15. data/lib/selenium/webdriver/common.rb +13 -6
  16. data/lib/selenium/webdriver/common/action_builder.rb +49 -57
  17. data/lib/selenium/webdriver/common/alert.rb +5 -15
  18. data/lib/selenium/webdriver/common/bridge_helper.rb +10 -17
  19. data/lib/selenium/webdriver/common/driver.rb +53 -68
  20. data/lib/selenium/webdriver/common/driver_extensions/{has_input_devices.rb → has_addons.rb} +13 -23
  21. data/lib/selenium/webdriver/common/driver_extensions/has_location.rb +4 -8
  22. data/lib/selenium/webdriver/common/driver_extensions/has_network_connection.rb +4 -7
  23. data/lib/selenium/webdriver/common/driver_extensions/has_remote_status.rb +0 -4
  24. data/lib/selenium/webdriver/common/driver_extensions/has_session_id.rb +0 -4
  25. data/lib/selenium/webdriver/common/driver_extensions/has_touch_screen.rb +1 -5
  26. data/lib/selenium/webdriver/common/driver_extensions/has_web_storage.rb +0 -5
  27. data/lib/selenium/webdriver/common/driver_extensions/rotatable.rb +4 -9
  28. data/lib/selenium/webdriver/common/driver_extensions/takes_screenshot.rb +7 -7
  29. data/lib/selenium/webdriver/common/driver_extensions/uploads_files.rb +2 -7
  30. data/lib/selenium/webdriver/common/element.rb +57 -39
  31. data/lib/selenium/webdriver/common/error.rb +204 -106
  32. data/lib/selenium/webdriver/common/file_reaper.rb +3 -11
  33. data/lib/selenium/webdriver/common/html5/local_storage.rb +6 -10
  34. data/lib/selenium/webdriver/common/html5/session_storage.rb +6 -10
  35. data/lib/selenium/webdriver/common/html5/shared_web_storage.rb +7 -18
  36. data/lib/selenium/webdriver/{safari/options.rb → common/interactions/input_device.rb} +20 -31
  37. data/lib/selenium/webdriver/common/interactions/interaction.rb +50 -0
  38. data/lib/selenium/webdriver/{safari/browser.rb → common/interactions/interactions.rb} +16 -15
  39. data/lib/selenium/webdriver/common/interactions/key_actions.rb +143 -0
  40. data/lib/selenium/webdriver/common/interactions/key_input.rb +62 -0
  41. data/lib/selenium/webdriver/{android.rb → common/interactions/none_input.rb} +11 -6
  42. data/lib/selenium/webdriver/common/interactions/pointer_actions.rb +353 -0
  43. data/lib/selenium/webdriver/common/interactions/pointer_input.rb +132 -0
  44. data/lib/selenium/webdriver/common/keyboard.rb +7 -14
  45. data/lib/selenium/webdriver/common/keys.rb +99 -82
  46. data/lib/selenium/webdriver/common/log_entry.rb +3 -6
  47. data/lib/selenium/webdriver/common/logger.rb +140 -0
  48. data/lib/selenium/webdriver/common/logs.rb +2 -6
  49. data/lib/selenium/webdriver/common/mouse.rb +9 -14
  50. data/lib/selenium/webdriver/common/navigation.rb +2 -6
  51. data/lib/selenium/webdriver/common/options.rb +20 -23
  52. data/lib/selenium/webdriver/common/platform.rb +70 -97
  53. data/lib/selenium/webdriver/common/port_prober.rb +3 -4
  54. data/lib/selenium/webdriver/common/profile_helper.rb +6 -11
  55. data/lib/selenium/webdriver/common/proxy.rb +58 -72
  56. data/lib/selenium/webdriver/common/search_context.rb +22 -29
  57. data/lib/selenium/webdriver/common/service.rb +161 -0
  58. data/lib/selenium/webdriver/common/socket_lock.rb +6 -14
  59. data/lib/selenium/webdriver/common/socket_poller.rb +5 -12
  60. data/lib/selenium/webdriver/common/target_locator.rb +11 -15
  61. data/lib/selenium/webdriver/common/timeouts.rb +4 -8
  62. data/lib/selenium/webdriver/common/touch_action_builder.rb +2 -6
  63. data/lib/selenium/webdriver/common/touch_screen.rb +19 -23
  64. data/lib/selenium/webdriver/common/w3c_action_builder.rb +209 -0
  65. data/lib/selenium/webdriver/{phantomjs.rb → common/w3c_options.rb} +16 -14
  66. data/lib/selenium/webdriver/common/wait.rb +6 -13
  67. data/lib/selenium/webdriver/common/window.rb +48 -17
  68. data/lib/selenium/webdriver/common/zipper.rb +6 -10
  69. data/lib/selenium/webdriver/edge.rb +5 -12
  70. data/lib/selenium/webdriver/edge/bridge.rb +32 -63
  71. data/lib/selenium/webdriver/edge/driver.rb +73 -0
  72. data/lib/selenium/webdriver/edge/service.rb +18 -87
  73. data/lib/selenium/webdriver/firefox.rb +20 -11
  74. data/lib/selenium/webdriver/firefox/binary.rb +40 -56
  75. data/lib/selenium/webdriver/firefox/driver.rb +48 -0
  76. data/lib/selenium/webdriver/firefox/extension.rb +18 -8
  77. data/lib/selenium/webdriver/firefox/extension/prefs.json +3 -11
  78. data/lib/selenium/webdriver/firefox/extension/webdriver.xpi +0 -0
  79. data/lib/selenium/webdriver/firefox/launcher.rb +13 -22
  80. data/lib/selenium/webdriver/firefox/legacy/driver.rb +79 -0
  81. data/lib/selenium/webdriver/{iphone.rb → firefox/marionette/bridge.rb} +25 -6
  82. data/lib/selenium/webdriver/firefox/marionette/driver.rb +96 -0
  83. data/lib/selenium/webdriver/firefox/options.rb +149 -0
  84. data/lib/selenium/webdriver/firefox/profile.rb +46 -46
  85. data/lib/selenium/webdriver/firefox/profiles_ini.rb +8 -18
  86. data/lib/selenium/webdriver/firefox/service.rb +23 -83
  87. data/lib/selenium/webdriver/firefox/util.rb +0 -4
  88. data/lib/selenium/webdriver/ie.rb +4 -8
  89. data/lib/selenium/webdriver/ie/driver.rb +90 -0
  90. data/lib/selenium/webdriver/ie/options.rb +136 -0
  91. data/lib/selenium/webdriver/ie/service.rb +58 -0
  92. data/lib/selenium/webdriver/remote.rb +8 -16
  93. data/lib/selenium/webdriver/remote/bridge.rb +96 -565
  94. data/lib/selenium/webdriver/remote/capabilities.rb +76 -94
  95. data/lib/selenium/webdriver/remote/driver.rb +49 -0
  96. data/lib/selenium/webdriver/remote/http/common.rb +22 -20
  97. data/lib/selenium/webdriver/remote/http/curb.rb +9 -12
  98. data/lib/selenium/webdriver/remote/http/default.rb +54 -41
  99. data/lib/selenium/webdriver/remote/http/persistent.rb +9 -8
  100. data/lib/selenium/webdriver/remote/oss/bridge.rb +586 -0
  101. data/lib/selenium/webdriver/remote/oss/commands.rb +221 -0
  102. data/lib/selenium/webdriver/remote/response.rb +39 -27
  103. data/lib/selenium/webdriver/remote/server_error.rb +1 -5
  104. data/lib/selenium/webdriver/remote/w3c/bridge.rb +573 -0
  105. data/lib/selenium/webdriver/remote/w3c/capabilities.rb +290 -0
  106. data/lib/selenium/webdriver/remote/w3c/commands.rb +148 -0
  107. data/lib/selenium/webdriver/safari.rb +20 -29
  108. data/lib/selenium/webdriver/{firefox/w3c_bridge.rb → safari/driver.rb} +21 -30
  109. data/lib/selenium/webdriver/safari/service.rb +57 -0
  110. data/lib/selenium/webdriver/support.rb +1 -2
  111. data/lib/selenium/webdriver/support/abstract_event_listener.rb +17 -4
  112. data/lib/selenium/webdriver/support/block_event_listener.rb +1 -5
  113. data/lib/selenium/webdriver/support/color.rb +57 -42
  114. data/lib/selenium/webdriver/support/escaper.rb +41 -0
  115. data/lib/selenium/webdriver/support/event_firing_bridge.rb +36 -40
  116. data/lib/selenium/webdriver/support/select.rb +33 -86
  117. data/selenium-webdriver.gemspec +22 -25
  118. metadata +254 -261
  119. data/lib/selenium-client.rb +0 -21
  120. data/lib/selenium/client.rb +0 -57
  121. data/lib/selenium/client/base.rb +0 -151
  122. data/lib/selenium/client/driver.rb +0 -29
  123. data/lib/selenium/client/errors.rb +0 -28
  124. data/lib/selenium/client/extensions.rb +0 -132
  125. data/lib/selenium/client/idiomatic.rb +0 -507
  126. data/lib/selenium/client/javascript_expression_builder.rb +0 -135
  127. data/lib/selenium/client/javascript_frameworks/jquery.rb +0 -32
  128. data/lib/selenium/client/javascript_frameworks/prototype.rb +0 -32
  129. data/lib/selenium/client/legacy_driver.rb +0 -1722
  130. data/lib/selenium/client/protocol.rb +0 -123
  131. data/lib/selenium/client/selenium_helper.rb +0 -49
  132. data/lib/selenium/rake/server_task.rb +0 -176
  133. data/lib/selenium/webdriver/android/bridge.rb +0 -68
  134. data/lib/selenium/webdriver/chrome/bridge.rb +0 -139
  135. data/lib/selenium/webdriver/common/core_ext/base64.rb +0 -28
  136. data/lib/selenium/webdriver/common/core_ext/dir.rb +0 -61
  137. data/lib/selenium/webdriver/common/html5/location.rb +0 -19
  138. data/lib/selenium/webdriver/common/w3c_error.rb +0 -194
  139. data/lib/selenium/webdriver/edge/legacy_support.rb +0 -117
  140. data/lib/selenium/webdriver/firefox/bridge.rb +0 -89
  141. data/lib/selenium/webdriver/ie/bridge.rb +0 -88
  142. data/lib/selenium/webdriver/ie/server.rb +0 -133
  143. data/lib/selenium/webdriver/iphone/bridge.rb +0 -64
  144. data/lib/selenium/webdriver/phantomjs/bridge.rb +0 -78
  145. data/lib/selenium/webdriver/phantomjs/service.rb +0 -130
  146. data/lib/selenium/webdriver/remote/commands.rb +0 -211
  147. data/lib/selenium/webdriver/remote/w3c_bridge.rb +0 -668
  148. data/lib/selenium/webdriver/remote/w3c_capabilities.rb +0 -236
  149. data/lib/selenium/webdriver/remote/w3c_commands.rb +0 -132
  150. data/lib/selenium/webdriver/safari/bridge.rb +0 -135
  151. data/lib/selenium/webdriver/safari/resources/client.js +0 -7255
  152. data/lib/selenium/webdriver/safari/server.rb +0 -187
@@ -1,211 +0,0 @@
1
- # encoding: utf-8
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
- class Selenium::WebDriver::Remote::Bridge
21
-
22
- #
23
- # https://github.com/SeleniumHQ/selenium/wiki/JsonWireProtocol#command-reference
24
- #
25
-
26
- command :newSession, :post, "session"
27
- command :getCapabilities, :get, "session/:session_id"
28
- command :status, :get, "status"
29
-
30
- #
31
- # basic driver
32
- #
33
-
34
- command :getCurrentUrl, :get, "session/:session_id/url"
35
- command :get, :post, "session/:session_id/url"
36
- command :goForward, :post, "session/:session_id/forward"
37
- command :goBack, :post, "session/:session_id/back"
38
- command :refresh, :post, "session/:session_id/refresh"
39
- command :quit, :delete, "session/:session_id"
40
- command :close, :delete, "session/:session_id/window"
41
- command :getPageSource, :get, "session/:session_id/source"
42
- command :getTitle, :get, "session/:session_id/title"
43
- command :findElement, :post, "session/:session_id/element"
44
- command :findElements, :post, "session/:session_id/elements"
45
- command :getActiveElement, :post, "session/:session_id/element/active"
46
-
47
- #
48
- # window handling
49
- #
50
-
51
- command :getCurrentWindowHandle, :get, "session/:session_id/window_handle"
52
- command :getWindowHandles, :get, "session/:session_id/window_handles"
53
- command :setWindowSize, :post, "session/:session_id/window/:window_handle/size"
54
- command :setWindowPosition, :post, "session/:session_id/window/:window_handle/position"
55
- command :getWindowSize, :get, "session/:session_id/window/:window_handle/size"
56
- command :getWindowPosition, :get, "session/:session_id/window/:window_handle/position"
57
- command :maximizeWindow, :post, "session/:session_id/window/:window_handle/maximize"
58
-
59
- #
60
- # script execution
61
- #
62
-
63
- command :executeScript, :post, "session/:session_id/execute"
64
- command :executeAsyncScript, :post, "session/:session_id/execute_async"
65
-
66
- #
67
- # screenshot
68
- #
69
-
70
- command :screenshot, :get, "session/:session_id/screenshot"
71
-
72
- #
73
- # alerts
74
- #
75
-
76
- command :dismissAlert, :post, "session/:session_id/dismiss_alert"
77
- command :acceptAlert, :post, "session/:session_id/accept_alert"
78
- command :getAlertText, :get, "session/:session_id/alert_text"
79
- command :setAlertValue, :post, "session/:session_id/alert_text"
80
- command :setAuthentication, :post, "session/:session_id/alert/credentials"
81
-
82
- #
83
- # target locator
84
- #
85
-
86
- command :switchToFrame, :post, "session/:session_id/frame"
87
- command :switchToParentFrame, :post, "session/:session_id/frame/parent"
88
- command :switchToWindow, :post, "session/:session_id/window"
89
-
90
- #
91
- # options
92
- #
93
-
94
- command :getCookies, :get, "session/:session_id/cookie"
95
- command :addCookie, :post, "session/:session_id/cookie"
96
- command :deleteAllCookies, :delete, "session/:session_id/cookie"
97
- command :deleteCookie, :delete, "session/:session_id/cookie/:name"
98
-
99
- #
100
- # timeouts
101
- #
102
-
103
- command :implicitlyWait, :post, "session/:session_id/timeouts/implicit_wait"
104
- command :setScriptTimeout, :post, "session/:session_id/timeouts/async_script"
105
- command :setTimeout, :post, "session/:session_id/timeouts"
106
-
107
- #
108
- # element
109
- #
110
-
111
- command :describeElement, :get, "session/:session_id/element/:id"
112
- command :findChildElement, :post, "session/:session_id/element/:id/element"
113
- command :findChildElements, :post, "session/:session_id/element/:id/elements"
114
- command :clickElement, :post, "session/:session_id/element/:id/click"
115
- command :submitElement, :post, "session/:session_id/element/:id/submit"
116
- command :getElementValue, :get, "session/:session_id/element/:id/value"
117
- command :sendKeysToElement, :post, "session/:session_id/element/:id/value"
118
- command :uploadFile, :post, "session/:session_id/file"
119
- command :getElementTagName, :get, "session/:session_id/element/:id/name"
120
- command :clearElement, :post, "session/:session_id/element/:id/clear"
121
- command :isElementSelected, :get, "session/:session_id/element/:id/selected"
122
- command :isElementEnabled, :get, "session/:session_id/element/:id/enabled"
123
- command :getElementAttribute, :get, "session/:session_id/element/:id/attribute/:name"
124
- command :elementEquals, :get, "session/:session_id/element/:id/equals/:other"
125
- command :isElementDisplayed, :get, "session/:session_id/element/:id/displayed"
126
- command :getElementLocation, :get, "session/:session_id/element/:id/location"
127
- command :getElementLocationOnceScrolledIntoView, :get, "session/:session_id/element/:id/location_in_view"
128
- command :getElementSize, :get, "session/:session_id/element/:id/size"
129
- command :dragElement, :post, "session/:session_id/element/:id/drag"
130
- command :getElementValueOfCssProperty, :get, "session/:session_id/element/:id/css/:property_name"
131
- command :getElementText, :get, "session/:session_id/element/:id/text"
132
-
133
- #
134
- # rotatable
135
- #
136
-
137
- command :getScreenOrientation, :get, "session/:session_id/orientation"
138
- command :setScreenOrientation, :post, "session/:session_id/orientation"
139
-
140
- #
141
- # interactions API
142
- #
143
-
144
- command :click, :post, "session/:session_id/click"
145
- command :doubleClick, :post, "session/:session_id/doubleclick"
146
- command :mouseDown, :post, "session/:session_id/buttondown"
147
- command :mouseUp, :post, "session/:session_id/buttonup"
148
- command :mouseMoveTo, :post, "session/:session_id/moveto"
149
- command :sendModifierKeyToActiveElement, :post, "session/:session_id/modifier"
150
- command :sendKeysToActiveElement, :post, "session/:session_id/keys"
151
-
152
- #
153
- # html 5
154
- #
155
-
156
- command :executeSql, :post, "session/:session_id/execute_sql"
157
-
158
- command :getLocation, :get, "session/:session_id/location"
159
- command :setLocation, :post, "session/:session_id/location"
160
-
161
- command :getAppCache, :get, "session/:session_id/application_cache"
162
- command :getAppCacheStatus, :get, "session/:session_id/application_cache/status"
163
- command :clearAppCache, :delete, "session/:session_id/application_cache/clear"
164
-
165
- command :getNetworkConnection, :get, "session/:session_id/network_connection"
166
- command :setNetworkConnection, :post, "session/:session_id/network_connection"
167
-
168
- command :getLocalStorageItem, :get, "session/:session_id/local_storage/key/:key"
169
- command :removeLocalStorageItem, :delete, "session/:session_id/local_storage/key/:key"
170
- command :getLocalStorageKeys, :get, "session/:session_id/local_storage"
171
- command :setLocalStorageItem, :post, "session/:session_id/local_storage"
172
- command :clearLocalStorage, :delete, "session/:session_id/local_storage"
173
- command :getLocalStorageSize, :get, "session/:session_id/local_storage/size"
174
-
175
- command :getSessionStorageItem, :get, "session/:session_id/session_storage/key/:key"
176
- command :removeSessionStorageItem, :delete, "session/:session_id/session_storage/key/:key"
177
- command :getSessionStorageKeys, :get, "session/:session_id/session_storage"
178
- command :setSessionStorageItem, :post, "session/:session_id/session_storage"
179
- command :clearSessionStorage, :delete, "session/:session_id/session_storage"
180
- command :getSessionStorageSize, :get, "session/:session_id/session_storage/size"
181
-
182
- #
183
- # ime
184
- #
185
-
186
- command :imeGetAvailableEngines, :get, "session/:session_id/ime/available_engines"
187
- command :imeGetActiveEngine, :get, "session/:session_id/ime/active_engine"
188
- command :imeIsActivated, :get, "session/:session_id/ime/activated"
189
- command :imeDeactivate, :post, "session/:session_id/ime/deactivate"
190
- command :imeActivateEngine, :post, "session/:session_id/ime/activate"
191
-
192
- #
193
- # touch
194
- #
195
-
196
- command :touchSingleTap, :post, "session/:session_id/touch/click"
197
- command :touchDoubleTap, :post, "session/:session_id/touch/doubleclick"
198
- command :touchLongPress, :post, "session/:session_id/touch/longclick"
199
- command :touchDown, :post, "session/:session_id/touch/down"
200
- command :touchUp, :post, "session/:session_id/touch/up"
201
- command :touchMove, :post, "session/:session_id/touch/move"
202
- command :touchScroll, :post, "session/:session_id/touch/scroll"
203
- command :touchFlick, :post, "session/:session_id/touch/flick"
204
-
205
- #
206
- # logs
207
- #
208
-
209
- command :getAvailableLogTypes, :get, "session/:session_id/log/types"
210
- command :getLog, :post, "session/:session_id/log"
211
- end
@@ -1,668 +0,0 @@
1
- # encoding: utf-8
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
-
26
- #
27
- # Low level bridge to the remote server, through which the rest of the API works.
28
- #
29
- # @api private
30
- #
31
-
32
- class W3CBridge
33
- include BridgeHelper
34
-
35
- COMMANDS = {}
36
-
37
- #
38
- # Defines a wrapper method for a command, which ultimately calls #execute.
39
- #
40
- # @param name [Symbol]
41
- # name of the resulting method
42
- # @param verb [Symbol]
43
- # the appropriate http verb, such as :get, :post, or :delete
44
- # @param url [String]
45
- # a URL template, which can include some arguments, much like the definitions on the server.
46
- # the :session_id parameter is implicitly handled, but the remainder will become required method arguments.
47
- #
48
-
49
- def self.command(name, verb, url)
50
- COMMANDS[name] = [verb, url.freeze]
51
- end
52
-
53
- attr_accessor :context, :http, :file_detector
54
- attr_reader :capabilities
55
-
56
- #
57
- # Initializes the bridge with the given server URL.
58
- #
59
- # @param url [String] url for the remote server
60
- # @param http_client [Object] an HTTP client instance that implements the same protocol as Http::Default
61
- # @param desired_capabilities [Capabilities] an instance of Remote::Capabilities describing the capabilities you want
62
- #
63
-
64
- def initialize(opts = {})
65
- if opts.fetch(:desired_capabilities, {})[:browser_name] == 'MicrosoftEdge'
66
- require_relative '../edge/legacy_support'
67
- extend Edge::LegacySupport
68
- end
69
-
70
- opts = opts.dup
71
-
72
- http_client = opts.delete(:http_client) { Http::Default.new }
73
- desired_capabilities = opts.delete(:desired_capabilities) { W3CCapabilities.firefox }
74
- url = opts.delete(:url) { "http://#{Platform.localhost}:4444/wd/hub" }
75
-
76
- desired_capabilities = W3CCapabilities.send(desired_capabilities) if desired_capabilities.is_a? Symbol
77
-
78
- desired_capabilities[:marionette] = opts.delete(:marionette) unless opts[:marionette].nil?
79
-
80
- unless opts.empty?
81
- raise ArgumentError, "unknown option#{'s' if opts.size != 1}: #{opts.inspect}"
82
- end
83
-
84
- uri = url.kind_of?(URI) ? url : URI.parse(url)
85
- uri.path += "/" unless uri.path =~ /\/$/
86
-
87
- http_client.server_url = uri
88
-
89
- @http = http_client
90
- @capabilities = create_session(desired_capabilities)
91
- @file_detector = nil
92
- end
93
-
94
- def browser
95
- @browser ||= (
96
- name = @capabilities.browser_name
97
- name ? name.gsub(" ", "_").to_sym : 'unknown'
98
- )
99
- end
100
-
101
- def driver_extensions
102
- [
103
- DriverExtensions::HasInputDevices,
104
- DriverExtensions::UploadsFiles,
105
- DriverExtensions::TakesScreenshot,
106
- DriverExtensions::HasSessionId,
107
- DriverExtensions::Rotatable,
108
- DriverExtensions::HasTouchScreen,
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
- W3CCapabilities.json_create resp['value']
127
- end
128
-
129
- def status
130
- jwp = Selenium::WebDriver::Remote::Bridge::COMMANDS[:status]
131
- self.class.command(:status, jwp.first, jwp.last)
132
- execute :status
133
- end
134
-
135
- def get(url)
136
- execute :get, {}, :url => url
137
- end
138
-
139
- def setImplicitWaitTimeout(milliseconds)
140
- setTimeout('implicit', milliseconds)
141
- end
142
-
143
- def setScriptTimeout(milliseconds)
144
- setTimeout('script', milliseconds)
145
- end
146
-
147
- def setTimeout(type, milliseconds)
148
- execute :setTimeout, {}, :type => type, :ms => milliseconds
149
- end
150
-
151
- #
152
- # alerts
153
- #
154
-
155
- def acceptAlert
156
- execute :acceptAlert
157
- end
158
-
159
- def dismissAlert
160
- execute :dismissAlert
161
- end
162
-
163
- def setAlertValue(keys)
164
- execute :sendAlertText, {}, {:handler => 'prompt', :message => keys}
165
- end
166
-
167
- def getAlertText
168
- execute :getAlertText
169
- end
170
-
171
- #
172
- # navigation
173
- #
174
-
175
- def goBack
176
- execute :back
177
- end
178
-
179
- def goForward
180
- execute :forward
181
- end
182
-
183
- def getCurrentUrl
184
- execute :getCurrentUrl
185
- end
186
-
187
- def getTitle
188
- execute :getTitle
189
- end
190
-
191
- def getPageSource
192
- executeScript("var source = document.documentElement.outerHTML;" +
193
- "if (!source) { source = new XMLSerializer().serializeToString(document); }" +
194
- "return source;")
195
- end
196
-
197
- def switchToWindow(name)
198
- execute :switchToWindow, {}, :handle => name
199
- end
200
-
201
- def switchToFrame(id)
202
- id = find_element_by('id', id) if id.is_a? String
203
- execute :switchToFrame, {}, :id => id
204
- end
205
-
206
- def switchToParentFrame
207
- execute :switchToParentFrame
208
- end
209
-
210
- def switchToDefaultContent
211
- switchToFrame nil
212
- end
213
-
214
- QUIT_ERRORS = [IOError]
215
-
216
- def quit
217
- execute :deleteSession
218
- http.close
219
- rescue *QUIT_ERRORS
220
- end
221
-
222
- def close
223
- execute :closeWindow
224
- end
225
-
226
- def refresh
227
- execute :refresh
228
- end
229
-
230
- #
231
- # window handling
232
- #
233
-
234
- def getWindowHandles
235
- execute :getWindowHandles
236
- end
237
-
238
- def getCurrentWindowHandle
239
- execute :getWindowHandle
240
- end
241
-
242
- def setWindowSize(width, height, handle = :current)
243
- unless handle == :current
244
- raise Error::WebDriverError, 'Switch to desired window before changing its size'
245
- end
246
- execute :setWindowSize, {}, {:width => width,
247
- :height => height}
248
- end
249
-
250
- def maximizeWindow(handle = :current)
251
- unless handle == :current
252
- raise Error::UnsupportedOperationError, 'Switch to desired window before changing its size'
253
- end
254
- execute :maximizeWindow
255
- end
256
-
257
- def fullscreenWindow
258
- execute :fullscreenWindow
259
- end
260
-
261
- def getWindowSize(handle = :current)
262
- unless handle == :current
263
- raise Error::UnsupportedOperationError, 'Switch to desired window before getting its size'
264
- end
265
- data = execute :getWindowSize
266
-
267
- Dimension.new data['width'], data['height']
268
- end
269
-
270
- def setWindowPosition(_x, _y, _handle = nil)
271
- raise Error::UnsupportedOperationError, 'The W3C standard does not currently support setting the Window Position'
272
- end
273
-
274
- def getWindowPosition(_handle = nil)
275
- raise Error::UnsupportedOperationError, 'The W3C standard does not currently support getting the Window Position'
276
- end
277
-
278
- def getScreenshot
279
- execute :takeScreenshot
280
- end
281
-
282
- #
283
- # HTML 5
284
- #
285
-
286
- def getLocalStorageItem(key)
287
- executeScript("return localStorage.getItem('#{key}')")
288
- end
289
-
290
- def removeLocalStorageItem(key)
291
- executeScript("localStorage.removeItem('#{key}')")
292
- end
293
-
294
- def getLocalStorageKeys
295
- executeScript("return Object.keys(localStorage)")
296
- end
297
-
298
- def setLocalStorageItem(key, value)
299
- executeScript("localStorage.setItem('#{key}', '#{value}')")
300
- end
301
-
302
- def clearLocalStorage
303
- executeScript("localStorage.clear()")
304
- end
305
-
306
- def getLocalStorageSize
307
- executeScript("return localStorage.length")
308
- end
309
-
310
- def getSessionStorageItem(key)
311
- executeScript("return sessionStorage.getItem('#{key}')")
312
- end
313
-
314
- def removeSessionStorageItem(key)
315
- executeScript("sessionStorage.removeItem('#{key}')")
316
- end
317
-
318
- def getSessionStorageKeys
319
- executeScript("return Object.keys(sessionStorage)")
320
- end
321
-
322
- def setSessionStorageItem(key, value)
323
- executeScript("sessionStorage.setItem('#{key}', '#{value}')")
324
- end
325
-
326
- def clearSessionStorage
327
- executeScript("sessionStorage.clear()")
328
- end
329
-
330
- def getSessionStorageSize
331
- executeScript("return sessionStorage.length")
332
- end
333
-
334
- def getLocation
335
- raise Error::UnsupportedOperationError, 'The W3C standard does not currently support getting location'
336
- end
337
-
338
- def setLocation(_lat, _lon, _alt)
339
- raise Error::UnsupportedOperationError, 'The W3C standard does not currently support setting location'
340
- end
341
-
342
- def getNetworkConnection
343
- raise Error::UnsupportedOperationError, 'The W3C standard does not currently support getting network connection'
344
- end
345
-
346
- def setNetworkConnection(_type)
347
- raise Error::UnsupportedOperationError, 'The W3C standard does not currently support setting network connection'
348
- end
349
-
350
- #
351
- # javascript execution
352
- #
353
-
354
- def executeScript(script, *args)
355
- result = execute :executeScript, {}, :script => script, :args => args
356
- unwrap_script_result result
357
- end
358
-
359
- def executeAsyncScript(script, *args)
360
- result = execute :executeAsyncScript, {}, :script => script, :args => args
361
- unwrap_script_result result
362
- end
363
-
364
- #
365
- # cookies
366
- #
367
-
368
- def addCookie(cookie)
369
- execute :addCookie, {}, :cookie => cookie
370
- end
371
-
372
- def deleteCookie(name)
373
- execute :deleteCookie, :name => name
374
- end
375
-
376
- # TODO - write specs
377
- def getCookie(name)
378
- execute :getCookie, :name => name
379
- end
380
-
381
- def getAllCookies
382
- execute :getAllCookies
383
- end
384
-
385
- def deleteAllCookies
386
- getAllCookies.each { |cookie| deleteCookie(cookie['name'])}
387
- end
388
-
389
- #
390
- # actions
391
- #
392
-
393
- def clickElement(element)
394
- execute :elementClick, :id => element
395
- end
396
-
397
- def click
398
- execute :click, {}, :button => 0
399
- end
400
-
401
- def doubleClick
402
- execute :doubleClick
403
- end
404
-
405
- def contextClick
406
- execute :click, {}, :button => 2
407
- end
408
-
409
- def mouseDown
410
- execute :mouseDown
411
- end
412
-
413
- def mouseUp
414
- execute :mouseUp
415
- end
416
-
417
- def mouseMoveTo(element, x = nil, y = nil)
418
- params = { :element => element }
419
-
420
- if x && y
421
- params.merge! :xoffset => x, :yoffset => y
422
- end
423
-
424
- execute :mouseMoveTo, {}, params
425
- end
426
-
427
- def sendKeysToActiveElement(keys)
428
- sendKeysToElement(getActiveElement, keys)
429
- end
430
-
431
- # TODO - Implement file verification
432
- def sendKeysToElement(element, keys)
433
- execute :elementSendKeys, {:id => element}, {:value => keys.join('').split(//)}
434
- end
435
-
436
- def clearElement(element)
437
- execute :elementClear, :id => element
438
- end
439
-
440
- def submitElement(element)
441
- executeScript("var e = arguments[0].ownerDocument.createEvent('Event');" +
442
- "e.initEvent('submit', true, true);" +
443
- "if (arguments[0].dispatchEvent(e)) { arguments[0].submit() }", element)
444
- end
445
-
446
- def dragElement(element, right_by, down_by)
447
- execute :dragElement, {:id => element}, :x => right_by, :y => down_by
448
- end
449
-
450
- def touchSingleTap(element)
451
- execute :touchSingleTap, {}, :element => element
452
- end
453
-
454
- def touchDoubleTap(element)
455
- execute :touchDoubleTap, {}, :element => element
456
- end
457
-
458
- def touchLongPress(element)
459
- execute :touchLongPress, {}, :element => element
460
- end
461
-
462
- def touchDown(x, y)
463
- execute :touchDown, {}, :x => x, :y => y
464
- end
465
-
466
- def touchUp(x, y)
467
- execute :touchUp, {}, :x => x, :y => y
468
- end
469
-
470
- def touchMove(x, y)
471
- execute :touchMove, {}, :x => x, :y => y
472
- end
473
-
474
- def touchScroll(element, x, y)
475
- if element
476
- execute :touchScroll, {}, :element => element,
477
- :xoffset => x,
478
- :yoffset => y
479
- else
480
- execute :touchScroll, {}, :xoffset => x, :yoffset => y
481
- end
482
- end
483
-
484
- def touchFlick(xspeed, yspeed)
485
- execute :touchFlick, {}, :xspeed => xspeed, :yspeed => yspeed
486
- end
487
-
488
- def touchElementFlick(element, right_by, down_by, speed)
489
- execute :touchFlick, {}, :element => element,
490
- :xoffset => right_by,
491
- :yoffset => down_by,
492
- :speed => speed
493
-
494
- end
495
-
496
- def setScreenOrientation(orientation)
497
- execute :setScreenOrientation, {}, :orientation => orientation
498
- end
499
-
500
- def getScreenOrientation
501
- execute :getScreenOrientation
502
- end
503
-
504
- #
505
- # element properties
506
- #
507
-
508
- def getElementTagName(element)
509
- execute :getElementTagName, :id => element
510
- end
511
-
512
- def getElementAttribute(element, name)
513
- execute :getElementAttribute, :id => element, :name => name
514
- end
515
-
516
- def getElementValue(element)
517
- execute :getElementProperty, :id => element, :name => 'value'
518
- end
519
-
520
- def getElementText(element)
521
- execute :getElementText, :id => element
522
- end
523
-
524
- def getElementLocation(element)
525
- data = execute :getElementRect, :id => element
526
-
527
- Point.new data['x'], data['y']
528
- end
529
-
530
- def getElementLocationOnceScrolledIntoView(element)
531
- sendKeysToElement(element, [''])
532
- getElementLocation(element)
533
- end
534
-
535
- def getElementSize(element)
536
- data = execute :getElementRect, :id => element
537
-
538
- Dimension.new data['width'], data['height']
539
- end
540
-
541
- def isElementEnabled(element)
542
- execute :isElementEnabled, :id => element
543
- end
544
-
545
- def isElementSelected(element)
546
- execute :isElementSelected, :id => element
547
- end
548
-
549
- def isElementDisplayed(element)
550
- jwp = Selenium::WebDriver::Remote::Bridge::COMMANDS[:isElementDisplayed]
551
- self.class.command(:isElementDisplayed, jwp.first, jwp.last)
552
- execute :isElementDisplayed, :id => element
553
- end
554
-
555
- def getElementValueOfCssProperty(element, prop)
556
- execute :getElementCssValue, :id => element, :property_name => prop
557
- end
558
-
559
- #
560
- # finding elements
561
- #
562
-
563
- def getActiveElement
564
- Element.new self, element_id_from(execute(:getActiveElement))
565
- end
566
- alias_method :switchToActiveElement, :getActiveElement
567
-
568
- def find_element_by(how, what, parent = nil)
569
- how, what = convert_locators(how, what)
570
-
571
- if parent
572
- id = execute :findChildElement, {:id => parent}, {:using => how, :value => what}
573
- else
574
- id = execute :findElement, {}, {:using => how, :value => what}
575
- end
576
-
577
- Element.new self, element_id_from(id)
578
- end
579
-
580
- def find_elements_by(how, what, parent = nil)
581
- how, what = convert_locators(how, what)
582
-
583
- if parent
584
- ids = execute :findChildElements, {:id => parent}, {:using => how, :value => what}
585
- else
586
- ids = execute :findElements, {}, {:using => how, :value => what}
587
- end
588
-
589
- ids.map { |id| Element.new self, element_id_from(id) }
590
- end
591
-
592
- private
593
-
594
- def convert_locators(how, what)
595
- case how
596
- when 'class name'
597
- how = 'css selector'
598
- what = ".#{escape_css(what)}"
599
- when 'id'
600
- how = 'css selector'
601
- what = "##{escape_css(what)}"
602
- when 'name'
603
- how = 'css selector'
604
- what = "*[name='#{escape_css(what)}']"
605
- when 'tag name'
606
- how = 'css selector'
607
- end
608
- return how, what
609
- end
610
-
611
- #
612
- # executes a command on the remote server.
613
- #
614
- #
615
- # Returns the 'value' of the returned payload
616
- #
617
-
618
- def execute(*args)
619
- result = raw_execute(*args)
620
- result.payload.key?('value') ? result['value'] : result
621
- end
622
-
623
- #
624
- # executes a command on the remote server.
625
- #
626
- # @return [WebDriver::Remote::Response]
627
- #
628
-
629
- def raw_execute(command, opts = {}, command_hash = nil)
630
- verb, path = COMMANDS[command] || raise(ArgumentError, "unknown command: #{command.inspect}")
631
- path = path.dup
632
-
633
- path[':session_id'] = @session_id if path.include?(":session_id")
634
-
635
- begin
636
- opts.each { |key, value|
637
- path[key.inspect] = escaper.escape(value.to_s)
638
- }
639
- rescue IndexError
640
- raise ArgumentError, "#{opts.inspect} invalid for #{command.inspect}"
641
- end
642
-
643
- puts "-> #{verb.to_s.upcase} #{path}" if $DEBUG
644
- http.call verb, path, command_hash
645
- end
646
-
647
- def escaper
648
- @escaper ||= defined?(URI::Parser) ? URI::Parser.new : URI
649
- end
650
-
651
- ESCAPE_CSS_REGEXP = /(['"\\#.:;,!?+<>=~*^$|%&@`{}\-\[\]\(\)])/
652
- UNICODE_CODE_POINT = 30
653
-
654
- # Escapes invalid characters in CSS selector.
655
- # @see https://mathiasbynens.be/notes/css-escapes
656
- def escape_css(string)
657
- string = string.gsub(ESCAPE_CSS_REGEXP) { |match| "\\#{match}" }
658
- if !string.empty? && string[0] =~ /[[:digit:]]/
659
- string = "\\#{UNICODE_CODE_POINT + Integer(string[0])} #{string[1..-1]}"
660
- end
661
-
662
- string
663
- end
664
-
665
- end # W3CBridge
666
- end # Remote
667
- end # WebDriver
668
- end # Selenium