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