selenium-webdriver 2.53.4 → 3.8.0

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 (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