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,5 +1,3 @@
1
- # encoding: utf-8
2
- #
3
1
  # Licensed to the Software Freedom Conservancy (SFC) under one
4
2
  # or more contributor license agreements. See the NOTICE file
5
3
  # distributed with this work for additional information
@@ -24,27 +22,47 @@ module Selenium
24
22
  module WebDriver
25
23
  module Remote
26
24
  module Http
27
-
28
25
  # @api private
29
26
  class Default < Common
30
- attr_accessor :proxy
27
+ attr_writer :proxy
28
+
29
+ attr_accessor :open_timeout
30
+ attr_accessor :read_timeout
31
+
32
+ # Initializes object.
33
+ # Warning: Setting {#open_timeout} to non-nil values will cause a separate thread to spawn.
34
+ # Debuggers that freeze the process will not be able to evaluate any operations if that happens.
35
+ # @param [Numeric] open_timeout - Open timeout to apply to HTTP client.
36
+ # @param [Numeric] read_timeout - Read timeout (seconds) to apply to HTTP client.
37
+ def initialize(open_timeout: nil, read_timeout: nil)
38
+ @open_timeout = open_timeout
39
+ @read_timeout = read_timeout
40
+ end
41
+
42
+ # Maintaining backward compatibility.
43
+ # @param [Numeric] value - Timeout in seconds to apply to both open timeout and read timeouts.
44
+ # @deprecated Please set the specific desired timeout {#read_timeout} or {#open_timeout} directly.
45
+ def timeout=(value)
46
+ WebDriver.logger.deprecate ':timeout=', '#read_timeout= and #open_timeout='
47
+ self.open_timeout = value
48
+ self.read_timeout = value
49
+ end
31
50
 
32
51
  private
33
52
 
34
53
  def http
35
54
  @http ||= (
36
- http = new_http_client
37
- if server_url.scheme == "https"
38
- http.use_ssl = true
39
- http.verify_mode = OpenSSL::SSL::VERIFY_NONE
40
- end
55
+ http = new_http_client
56
+ if server_url.scheme == 'https'
57
+ http.use_ssl = true
58
+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE
59
+ end
41
60
 
42
- if @timeout
43
- http.open_timeout = @timeout
44
- http.read_timeout = @timeout
45
- end
61
+ # Defaulting open_timeout to nil to be consistent with Ruby 2.2 and earlier.
62
+ http.open_timeout = self.open_timeout
63
+ http.read_timeout = self.read_timeout if self.read_timeout
46
64
 
47
- http
65
+ http
48
66
  )
49
67
  end
50
68
 
@@ -74,17 +92,13 @@ module Selenium
74
92
  retries += 1
75
93
  sleep 2
76
94
  retry
77
-
78
95
  rescue Errno::ECONNREFUSED => ex
79
- if use_proxy?
80
- raise ex.class, "using proxy: #{proxy.http}"
81
- else
82
- raise
83
- end
96
+ raise ex.class, "using proxy: #{proxy.http}" if use_proxy?
97
+ raise
84
98
  end
85
99
 
86
- if response.kind_of? Net::HTTPRedirection
87
- raise Error::WebDriverError, "too many redirects" if redirects >= MAX_REDIRECTS
100
+ if response.is_a? Net::HTTPRedirection
101
+ raise Error::WebDriverError, 'too many redirects' if redirects >= MAX_REDIRECTS
88
102
  request(:get, URI.parse(response['Location']), DEFAULT_HEADERS.dup, nil, redirects + 1)
89
103
  else
90
104
  create_response response.code, response.body, response.content_type
@@ -109,7 +123,8 @@ module Selenium
109
123
 
110
124
  def new_http_client
111
125
  if use_proxy?
112
- unless proxy.respond_to?(:http) && url = @proxy.http
126
+ url = @proxy.http
127
+ unless proxy.respond_to?(:http) && url
113
128
  raise Error::WebDriverError, "expected HTTP proxy, got #{@proxy.inspect}"
114
129
  end
115
130
 
@@ -124,13 +139,13 @@ module Selenium
124
139
 
125
140
  def proxy
126
141
  @proxy ||= (
127
- proxy = ENV['http_proxy'] || ENV['HTTP_PROXY']
128
- no_proxy = ENV['no_proxy'] || ENV['NO_PROXY']
142
+ proxy = ENV['http_proxy'] || ENV['HTTP_PROXY']
143
+ no_proxy = ENV['no_proxy'] || ENV['NO_PROXY']
129
144
 
130
- if proxy
131
- proxy = "http://#{proxy}" unless proxy.start_with?("http://")
132
- Proxy.new(:http => proxy, :no_proxy => no_proxy)
133
- end
145
+ if proxy
146
+ proxy = "http://#{proxy}" unless proxy.start_with?('http://')
147
+ Proxy.new(http: proxy, no_proxy: no_proxy)
148
+ end
134
149
  )
135
150
  end
136
151
 
@@ -138,24 +153,22 @@ module Selenium
138
153
  return false if proxy.nil?
139
154
 
140
155
  if proxy.no_proxy
141
- ignored = proxy.no_proxy.split(",").any? do |host|
142
- host == "*" ||
143
- host == server_url.host || (
144
- begin
145
- IPAddr.new(host).include?(server_url.host)
146
- rescue ArgumentError
147
- false
148
- end
149
- )
150
-
156
+ ignored = proxy.no_proxy.split(',').any? do |host|
157
+ host == '*' ||
158
+ host == server_url.host || (
159
+ begin
160
+ IPAddr.new(host).include?(server_url.host)
161
+ rescue ArgumentError
162
+ false
163
+ end
164
+ )
151
165
  end
152
166
 
153
- not ignored
167
+ !ignored
154
168
  else
155
169
  true
156
170
  end
157
171
  end
158
-
159
172
  end # Default
160
173
  end # Http
161
174
  end # Remote
@@ -1,5 +1,3 @@
1
- # encoding: utf-8
2
- #
3
1
  # Licensed to the Software Freedom Conservancy (SFC) under one
4
2
  # or more contributor license agreements. See the NOTICE file
5
3
  # distributed with this work for additional information
@@ -23,10 +21,8 @@ module Selenium
23
21
  module WebDriver
24
22
  module Remote
25
23
  module Http
26
-
27
24
  # @api private
28
25
  class Persistent < Default
29
-
30
26
  def close
31
27
  @http.shutdown if @http
32
28
  end
@@ -37,19 +33,24 @@ module Selenium
37
33
  proxy = nil
38
34
 
39
35
  if @proxy
40
- unless @proxy.respond_to?(:http) && url = @proxy.http
41
- raise Error::WebDriverError, "expected HTTP proxy, got #{@proxy.inspect}"
36
+ unless @proxy.respond_to?(:http)
37
+ url = @proxy.http
38
+ raise Error::WebDriverError, "expected HTTP proxy, got #{@proxy.inspect}" unless url
42
39
  end
43
40
  proxy = URI.parse(url)
44
41
  end
45
42
 
46
- Net::HTTP::Persistent.new "webdriver", proxy
43
+ if Net::HTTP::Persistent::VERSION >= '3'
44
+ Net::HTTP::Persistent.new name: 'webdriver', proxy: proxy
45
+ else
46
+ WebDriver.logger.warn 'Support for this version of net-http-persistent is deprecated. Please upgrade.'
47
+ Net::HTTP::Persistent.new 'webdriver', proxy
48
+ end
47
49
  end
48
50
 
49
51
  def response_for(request)
50
52
  http.request server_url, request
51
53
  end
52
-
53
54
  end # Persistent
54
55
  end # Http
55
56
  end # Remote
@@ -0,0 +1,586 @@
1
+ # Licensed to the Software Freedom Conservancy (SFC) under one
2
+ # or more contributor license agreements. See the NOTICE file
3
+ # distributed with this work for additional information
4
+ # regarding copyright ownership. The SFC licenses this file
5
+ # to you under the Apache License, Version 2.0 (the
6
+ # "License"); you may not use this file except in compliance
7
+ # with the License. You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing,
12
+ # software distributed under the License is distributed on an
13
+ # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14
+ # KIND, either express or implied. See the License for the
15
+ # specific language governing permissions and limitations
16
+ # under the License.
17
+
18
+ module Selenium
19
+ module WebDriver
20
+ module Remote
21
+ module OSS
22
+
23
+ #
24
+ # Low level bridge to the remote server implementing JSON wire
25
+ # protocol (OSS dialect), through which the rest of the API works.
26
+ # @api private
27
+ #
28
+
29
+ class Bridge < Remote::Bridge
30
+
31
+ def initialize(capabilities, session_id, **opts)
32
+ @capabilities = capabilities
33
+ @session_id = session_id
34
+ super(opts)
35
+ end
36
+
37
+ def dialect
38
+ :oss
39
+ end
40
+
41
+ def commands(command)
42
+ COMMANDS[command]
43
+ end
44
+
45
+ def status
46
+ execute :status
47
+ end
48
+
49
+ def get(url)
50
+ execute :get, {}, {url: url}
51
+ end
52
+
53
+ def session_capabilities
54
+ Capabilities.json_create execute(:get_capabilities)
55
+ end
56
+
57
+ def implicit_wait_timeout=(milliseconds)
58
+ execute :implicitly_wait, {}, {ms: milliseconds}
59
+ end
60
+
61
+ def script_timeout=(milliseconds)
62
+ execute :set_script_timeout, {}, {ms: milliseconds}
63
+ end
64
+
65
+ def timeout(type, milliseconds)
66
+ execute :set_timeout, {}, {type: type, ms: milliseconds}
67
+ end
68
+
69
+ #
70
+ # alerts
71
+ #
72
+
73
+ def accept_alert
74
+ execute :accept_alert
75
+ end
76
+
77
+ def dismiss_alert
78
+ execute :dismiss_alert
79
+ end
80
+
81
+ def alert=(keys)
82
+ execute :set_alert_value, {}, {text: keys.to_s}
83
+ end
84
+
85
+ def alert_text
86
+ execute :get_alert_text
87
+ end
88
+
89
+ def authentication(credentials)
90
+ execute :set_authentication, {}, credentials
91
+ end
92
+
93
+ #
94
+ # navigation
95
+ #
96
+
97
+ def go_back
98
+ execute :go_back
99
+ end
100
+
101
+ def go_forward
102
+ execute :go_forward
103
+ end
104
+
105
+ def url
106
+ execute :get_current_url
107
+ end
108
+
109
+ def title
110
+ execute :get_title
111
+ end
112
+
113
+ def page_source
114
+ execute :get_page_source
115
+ end
116
+
117
+ def switch_to_window(name)
118
+ execute :switch_to_window, {}, {name: name}
119
+ end
120
+
121
+ def switch_to_frame(id)
122
+ execute :switch_to_frame, {}, {id: id}
123
+ end
124
+
125
+ def switch_to_parent_frame
126
+ execute :switch_to_parent_frame
127
+ end
128
+
129
+ def switch_to_default_content
130
+ switch_to_frame(nil)
131
+ end
132
+
133
+ def quit
134
+ execute :quit
135
+ http.close
136
+ rescue *http.quit_errors
137
+ end
138
+
139
+ def close
140
+ execute :close
141
+ end
142
+
143
+ def refresh
144
+ execute :refresh
145
+ end
146
+
147
+ #
148
+ # window handling
149
+ #
150
+
151
+ def window_handles
152
+ execute :get_window_handles
153
+ end
154
+
155
+ def window_handle
156
+ execute :get_current_window_handle
157
+ end
158
+
159
+ def resize_window(width, height, handle = :current)
160
+ execute :set_window_size, {window_handle: handle},
161
+ {width: width,
162
+ height: height}
163
+ end
164
+
165
+ def maximize_window(handle = :current)
166
+ execute :maximize_window, window_handle: handle
167
+ end
168
+
169
+ def window_size(handle = :current)
170
+ data = execute :get_window_size, window_handle: handle
171
+
172
+ Dimension.new data['width'], data['height']
173
+ end
174
+
175
+ def reposition_window(x, y, handle = :current)
176
+ execute :set_window_position, {window_handle: handle},
177
+ {x: x, y: y}
178
+ end
179
+
180
+ def window_position(handle = :current)
181
+ data = execute :get_window_position, window_handle: handle
182
+
183
+ Point.new data['x'], data['y']
184
+ end
185
+
186
+ def screenshot
187
+ execute :screenshot
188
+ end
189
+
190
+ #
191
+ # HTML 5
192
+ #
193
+
194
+ def local_storage_item(key, value = nil)
195
+ if value
196
+ execute :set_local_storage_item, {}, {key: key, value: value}
197
+ else
198
+ execute :get_local_storage_item, key: key
199
+ end
200
+ end
201
+
202
+ def remove_local_storage_item(key)
203
+ execute :remove_local_storage_item, key: key
204
+ end
205
+
206
+ def local_storage_keys
207
+ execute :get_local_storage_keys
208
+ end
209
+
210
+ def clear_local_storage
211
+ execute :clear_local_storage
212
+ end
213
+
214
+ def local_storage_size
215
+ execute :get_local_storage_size
216
+ end
217
+
218
+ def session_storage_item(key, value = nil)
219
+ if value
220
+ execute :set_session_storage_item, {}, {key: key, value: value}
221
+ else
222
+ execute :get_session_storage_item, key: key
223
+ end
224
+ end
225
+
226
+ def remove_session_storage_item(key)
227
+ execute :remove_session_storage_item, key: key
228
+ end
229
+
230
+ def session_storage_keys
231
+ execute :get_session_storage_keys
232
+ end
233
+
234
+ def clear_session_storage
235
+ execute :clear_session_storage
236
+ end
237
+
238
+ def session_storage_size
239
+ execute :get_session_storage_size
240
+ end
241
+
242
+ def location
243
+ obj = execute(:get_location) || {}
244
+ Location.new obj['latitude'], obj['longitude'], obj['altitude']
245
+ end
246
+
247
+ def set_location(lat, lon, alt)
248
+ loc = {latitude: lat, longitude: lon, altitude: alt}
249
+ execute :set_location, {}, {location: loc}
250
+ end
251
+
252
+ def network_connection
253
+ execute :get_network_connection
254
+ end
255
+
256
+ def network_connection=(type)
257
+ execute :set_network_connection, {}, {parameters: {type: type}}
258
+ end
259
+
260
+ #
261
+ # javascript execution
262
+ #
263
+
264
+ def execute_script(script, *args)
265
+ assert_javascript_enabled
266
+
267
+ result = execute :execute_script, {}, {script: script, args: args}
268
+ unwrap_script_result result
269
+ end
270
+
271
+ def execute_async_script(script, *args)
272
+ assert_javascript_enabled
273
+
274
+ result = execute :execute_async_script, {}, {script: script, args: args}
275
+ unwrap_script_result result
276
+ end
277
+
278
+ #
279
+ # cookies
280
+ #
281
+
282
+ def options
283
+ @options ||= WebDriver::Options.new(self)
284
+ end
285
+
286
+ def add_cookie(cookie)
287
+ execute :add_cookie, {}, {cookie: cookie}
288
+ end
289
+
290
+ def delete_cookie(name)
291
+ execute :delete_cookie, name: name
292
+ end
293
+
294
+ def cookies
295
+ execute :get_cookies
296
+ end
297
+
298
+ def delete_all_cookies
299
+ execute :delete_all_cookies
300
+ end
301
+
302
+ #
303
+ # actions
304
+ #
305
+
306
+ #
307
+ # @return [ActionBuilder]
308
+ # @api public
309
+ #
310
+
311
+ def action
312
+ ActionBuilder.new Mouse.new(self), Keyboard.new(self)
313
+ end
314
+
315
+ def mouse
316
+ WebDriver.logger.deprecate 'Driver#mouse', 'driver.action.<command>.perform'
317
+ Mouse.new self
318
+ end
319
+
320
+ def keyboard
321
+ WebDriver.logger.deprecate 'Driver#keyboard', 'driver.action.<command>.perform'
322
+ Keyboard.new self
323
+ end
324
+
325
+ def click_element(element)
326
+ execute :click_element, id: element
327
+ end
328
+
329
+ def click
330
+ execute :click, {}, {button: 0}
331
+ end
332
+
333
+ def double_click
334
+ execute :double_click
335
+ end
336
+
337
+ def context_click
338
+ execute :click, {}, {button: 2}
339
+ end
340
+
341
+ def mouse_down
342
+ execute :mouse_down
343
+ end
344
+
345
+ def mouse_up
346
+ execute :mouse_up
347
+ end
348
+
349
+ def mouse_move_to(element, x = nil, y = nil)
350
+ params = {element: element}
351
+
352
+ if x && y
353
+ params[:xoffset] = x
354
+ params[:yoffset] = y
355
+ end
356
+
357
+ execute :mouse_move_to, {}, params
358
+ end
359
+
360
+ def send_keys_to_active_element(key)
361
+ execute :send_keys_to_active_element, {}, {value: key}
362
+ end
363
+
364
+ def send_keys_to_element(element, keys)
365
+ if @file_detector
366
+ local_file = @file_detector.call(keys)
367
+ keys = upload(local_file) if local_file
368
+ end
369
+
370
+ execute :send_keys_to_element, {id: element}, {value: Array(keys)}
371
+ end
372
+
373
+ def upload(local_file)
374
+ unless File.file?(local_file)
375
+ raise Error::WebDriverError, "you may only upload files: #{local_file.inspect}"
376
+ end
377
+
378
+ execute :upload_file, {}, {file: Zipper.zip_file(local_file)}
379
+ end
380
+
381
+ def clear_element(element)
382
+ execute :clear_element, id: element
383
+ end
384
+
385
+ def submit_element(element)
386
+ execute :submit_element, id: element
387
+ end
388
+
389
+ def drag_element(element, right_by, down_by)
390
+ execute :drag_element, {id: element}, {x: right_by, y: down_by}
391
+ end
392
+
393
+ def touch_single_tap(element)
394
+ execute :touch_single_tap, {}, {element: element}
395
+ end
396
+
397
+ def touch_double_tap(element)
398
+ execute :touch_double_tap, {}, {element: element}
399
+ end
400
+
401
+ def touch_long_press(element)
402
+ execute :touch_long_press, {}, {element: element}
403
+ end
404
+
405
+ def touch_down(x, y)
406
+ execute :touch_down, {}, {x: x, y: y}
407
+ end
408
+
409
+ def touch_up(x, y)
410
+ execute :touch_up, {}, {x: x, y: y}
411
+ end
412
+
413
+ def touch_move(x, y)
414
+ execute :touch_move, {}, {x: x, y: y}
415
+ end
416
+
417
+ def touch_scroll(element, x, y)
418
+ if element
419
+ execute :touch_scroll, {}, {element: element,
420
+ xoffset: x,
421
+ yoffset: y}
422
+ else
423
+ execute :touch_scroll, {}, {xoffset: x, yoffset: y}
424
+ end
425
+ end
426
+
427
+ def touch_flick(xspeed, yspeed)
428
+ execute :touch_flick, {}, {xspeed: xspeed, yspeed: yspeed}
429
+ end
430
+
431
+ def touch_element_flick(element, right_by, down_by, speed)
432
+ execute :touch_flick, {}, {element: element,
433
+ xoffset: right_by,
434
+ yoffset: down_by,
435
+ speed: speed}
436
+ end
437
+
438
+ def screen_orientation=(orientation)
439
+ execute :set_screen_orientation, {}, {orientation: orientation}
440
+ end
441
+
442
+ def screen_orientation
443
+ execute :get_screen_orientation
444
+ end
445
+
446
+ #
447
+ # logs
448
+ #
449
+
450
+ def available_log_types
451
+ types = execute :get_available_log_types
452
+ Array(types).map(&:to_sym)
453
+ end
454
+
455
+ def log(type)
456
+ data = execute :get_log, {}, {type: type.to_s}
457
+
458
+ Array(data).map do |l|
459
+ begin
460
+ LogEntry.new l.fetch('level', 'UNKNOWN'), l.fetch('timestamp'), l.fetch('message')
461
+ rescue KeyError
462
+ next
463
+ end
464
+ end
465
+ end
466
+
467
+ #
468
+ # element properties
469
+ #
470
+
471
+ def element_tag_name(element)
472
+ execute :get_element_tag_name, id: element
473
+ end
474
+
475
+ def element_attribute(element, name)
476
+ execute :get_element_attribute, id: element.ref, name: name
477
+ end
478
+
479
+ # Backwards compatibility for w3c
480
+ def element_property(element, name)
481
+ execute_script 'return arguments[0][arguments[1]]', element, name
482
+ end
483
+
484
+ def element_value(element)
485
+ execute :get_element_value, id: element
486
+ end
487
+
488
+ def element_text(element)
489
+ execute :get_element_text, id: element
490
+ end
491
+
492
+ def element_location(element)
493
+ data = execute :get_element_location, id: element
494
+
495
+ Point.new data['x'], data['y']
496
+ end
497
+
498
+ def element_rect(element)
499
+ loc = execute :get_element_location, id: element
500
+ size = execute :get_element_size, id: element
501
+
502
+ Rectangle.new loc['x'], loc['y'], size['width'], size['height']
503
+ end
504
+
505
+ def element_location_once_scrolled_into_view(element)
506
+ data = execute :get_element_location_once_scrolled_into_view, id: element
507
+
508
+ Point.new data['x'], data['y']
509
+ end
510
+
511
+ def element_size(element)
512
+ data = execute :get_element_size, id: element
513
+
514
+ Dimension.new data['width'], data['height']
515
+ end
516
+
517
+ def element_enabled?(element)
518
+ execute :is_element_enabled, id: element
519
+ end
520
+
521
+ def element_selected?(element)
522
+ execute :is_element_selected, id: element
523
+ end
524
+
525
+ def element_displayed?(element)
526
+ execute :is_element_displayed, id: element
527
+ end
528
+
529
+ def element_value_of_css_property(element, prop)
530
+ execute :get_element_value_of_css_property, id: element, property_name: prop
531
+ end
532
+
533
+ #
534
+ # finding elements
535
+ #
536
+
537
+ def active_element
538
+ Element.new self, element_id_from(execute(:get_active_element))
539
+ end
540
+
541
+ alias_method :switch_to_active_element, :active_element
542
+
543
+ def find_element_by(how, what, parent = nil)
544
+ id = if parent
545
+ execute :find_child_element, {id: parent}, {using: how, value: what}
546
+ else
547
+ execute :find_element, {}, {using: how, value: what}
548
+ end
549
+
550
+ Element.new self, element_id_from(id)
551
+ end
552
+
553
+ def find_elements_by(how, what, parent = nil)
554
+ ids = if parent
555
+ execute :find_child_elements, {id: parent}, {using: how, value: what}
556
+ else
557
+ execute :find_elements, {}, {using: how, value: what}
558
+ end
559
+ # see https://github.com/SeleniumHQ/selenium/issues/4555
560
+ ids ||= []
561
+
562
+ ids.map { |id| Element.new self, element_id_from(id) }
563
+ end
564
+
565
+ private
566
+
567
+ def assert_javascript_enabled
568
+ return if capabilities.javascript_enabled?
569
+ raise Error::UnsupportedOperationError, 'underlying webdriver instance does not support javascript'
570
+ end
571
+
572
+ #
573
+ # executes a command on the remote server.
574
+ #
575
+ # Returns the 'value' of the returned payload
576
+ #
577
+
578
+ def execute(*args)
579
+ super['value']
580
+ end
581
+
582
+ end # Bridge
583
+ end # OSS
584
+ end # Remote
585
+ end # WebDriver
586
+ end # Selenium