selenium-webdriver 3.142.7 → 4.0.0.alpha1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (50) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGES +21 -43
  3. data/lib/selenium/webdriver.rb +2 -4
  4. data/lib/selenium/webdriver/chrome/bridge.rb +3 -21
  5. data/lib/selenium/webdriver/chrome/driver.rb +12 -39
  6. data/lib/selenium/webdriver/chrome/options.rb +3 -7
  7. data/lib/selenium/webdriver/chrome/profile.rb +2 -2
  8. data/lib/selenium/webdriver/chrome/service.rb +4 -9
  9. data/lib/selenium/webdriver/common.rb +7 -16
  10. data/lib/selenium/webdriver/common/action_builder.rb +97 -249
  11. data/lib/selenium/webdriver/common/driver.rb +2 -4
  12. data/lib/selenium/webdriver/common/driver_extensions/takes_screenshot.rb +1 -1
  13. data/lib/selenium/webdriver/common/element.rb +3 -6
  14. data/lib/selenium/webdriver/common/error.rb +27 -203
  15. data/lib/selenium/webdriver/common/interactions/key_actions.rb +5 -5
  16. data/lib/selenium/webdriver/common/interactions/pointer_actions.rb +13 -13
  17. data/lib/selenium/webdriver/common/manager.rb +1 -1
  18. data/lib/selenium/webdriver/common/options.rb +148 -24
  19. data/lib/selenium/webdriver/common/service.rb +16 -34
  20. data/lib/selenium/webdriver/common/socket_poller.rb +2 -2
  21. data/lib/selenium/webdriver/common/w3c_options.rb +45 -0
  22. data/lib/selenium/webdriver/edge.rb +0 -1
  23. data/lib/selenium/webdriver/edge/driver.rb +14 -10
  24. data/lib/selenium/webdriver/edge/service.rb +6 -7
  25. data/lib/selenium/webdriver/firefox.rb +2 -6
  26. data/lib/selenium/webdriver/firefox/binary.rb +3 -80
  27. data/lib/selenium/webdriver/firefox/bridge.rb +47 -0
  28. data/lib/selenium/webdriver/firefox/driver.rb +44 -22
  29. data/lib/selenium/webdriver/firefox/marionette/driver.rb +1 -1
  30. data/lib/selenium/webdriver/firefox/options.rb +2 -2
  31. data/lib/selenium/webdriver/firefox/profile.rb +25 -14
  32. data/lib/selenium/webdriver/firefox/service.rb +4 -4
  33. data/lib/selenium/webdriver/ie/driver.rb +5 -18
  34. data/lib/selenium/webdriver/ie/options.rb +2 -2
  35. data/lib/selenium/webdriver/ie/service.rb +4 -4
  36. data/lib/selenium/webdriver/remote.rb +2 -6
  37. data/lib/selenium/webdriver/remote/bridge.rb +515 -69
  38. data/lib/selenium/webdriver/remote/capabilities.rb +77 -99
  39. data/lib/selenium/webdriver/remote/commands.rb +156 -0
  40. data/lib/selenium/webdriver/remote/driver.rb +12 -5
  41. data/lib/selenium/webdriver/remote/http/default.rb +0 -9
  42. data/lib/selenium/webdriver/remote/response.rb +16 -47
  43. data/lib/selenium/webdriver/safari.rb +1 -1
  44. data/lib/selenium/webdriver/safari/bridge.rb +3 -3
  45. data/lib/selenium/webdriver/safari/driver.rb +4 -1
  46. data/lib/selenium/webdriver/safari/service.rb +4 -4
  47. data/lib/selenium/webdriver/support/select.rb +1 -1
  48. data/lib/selenium/webdriver/version.rb +1 -1
  49. data/selenium-webdriver.gemspec +3 -3
  50. metadata +14 -5
@@ -20,29 +20,38 @@
20
20
  module Selenium
21
21
  module WebDriver
22
22
  module Remote
23
+
23
24
  #
24
25
  # Specification of the desired and/or actual capabilities of the browser that the
25
26
  # server is being asked to create.
26
27
  #
28
+
27
29
  class Capabilities
28
- DEFAULTS = {
29
- browser_name: '',
30
- version: '',
31
- platform: :any,
32
- javascript_enabled: false,
33
- css_selectors_enabled: false,
34
- takes_screenshot: false,
35
- native_events: false,
36
- rotatable: false,
37
- firefox_profile: nil,
38
- proxy: nil
39
- }.freeze
40
-
41
- DEFAULTS.each_key do |key|
42
- if key != :javascript_enabled
43
- define_method key do
44
- @capabilities.fetch(key)
45
- end
30
+
31
+ KNOWN = [
32
+ :browser_name,
33
+ :browser_version,
34
+ :platform_name,
35
+ :accept_insecure_certs,
36
+ :page_load_strategy,
37
+ :proxy,
38
+ :set_window_rect,
39
+ :timeouts,
40
+ :unhandled_prompt_behavior,
41
+ :strict_file_interactability,
42
+
43
+ # remote-specific
44
+ :remote_session_id,
45
+
46
+ # TODO: (AR) deprecate compatibility with OSS-capabilities
47
+ :implicit_timeout,
48
+ :page_load_timeout,
49
+ :script_timeout
50
+ ].freeze
51
+
52
+ KNOWN.each do |key|
53
+ define_method key do
54
+ @capabilities.fetch(key)
46
55
  end
47
56
 
48
57
  next if key == :proxy
@@ -53,19 +62,13 @@ module Selenium
53
62
  end
54
63
 
55
64
  #
56
- # Returns javascript_enabled capability.
57
- # It is true if not set explicitly.
65
+ # Backward compatibility
58
66
  #
59
- def javascript_enabled
60
- javascript_enabled = @capabilities.fetch(:javascript_enabled)
61
- javascript_enabled.nil? ? true : javascript_enabled
62
- end
63
67
 
64
- alias_method :css_selectors_enabled?, :css_selectors_enabled
65
- alias_method :javascript_enabled?, :javascript_enabled
66
- alias_method :native_events?, :native_events
67
- alias_method :takes_screenshot?, :takes_screenshot
68
- alias_method :rotatable?, :rotatable
68
+ alias_method :version, :browser_version
69
+ alias_method :version=, :browser_version=
70
+ alias_method :platform, :platform_name
71
+ alias_method :platform=, :platform_name=
69
72
 
70
73
  #
71
74
  # Convenience methods for the common choices.
@@ -74,16 +77,14 @@ module Selenium
74
77
  class << self
75
78
  def chrome(opts = {})
76
79
  new({
77
- browser_name: 'chrome',
78
- javascript_enabled: true,
79
- css_selectors_enabled: true
80
+ browser_name: 'chrome'
80
81
  }.merge(opts))
81
82
  end
82
83
 
83
84
  def edge(opts = {})
84
85
  new({
85
86
  browser_name: 'MicrosoftEdge',
86
- platform: :windows
87
+ platform_name: :windows
87
88
  }.merge(opts))
88
89
  end
89
90
 
@@ -94,15 +95,15 @@ module Selenium
94
95
  opts[:timeouts]['implicit'] = opts.delete(:implicit_timeout) if opts.key?(:implicit_timeout)
95
96
  opts[:timeouts]['pageLoad'] = opts.delete(:page_load_timeout) if opts.key?(:page_load_timeout)
96
97
  opts[:timeouts]['script'] = opts.delete(:script_timeout) if opts.key?(:script_timeout)
97
- new({browser_name: 'firefox', marionette: true}.merge(opts))
98
+ new({browser_name: 'firefox'}.merge(opts))
98
99
  end
99
100
 
100
- def firefox_legacy(opts = {})
101
+ alias_method :ff, :firefox
102
+
103
+ def safari(opts = {})
101
104
  new({
102
- browser_name: 'firefox',
103
- javascript_enabled: true,
104
- takes_screenshot: true,
105
- css_selectors_enabled: true
105
+ browser_name: 'safari',
106
+ platform_name: :mac
106
107
  }.merge(opts))
107
108
  end
108
109
 
@@ -112,44 +113,14 @@ module Selenium
112
113
  }.merge(opts))
113
114
  end
114
115
 
115
- def htmlunitwithjs(opts = {})
116
- new({
117
- browser_name: 'htmlunit',
118
- javascript_enabled: true
119
- }.merge(opts))
120
- end
121
-
122
116
  def internet_explorer(opts = {})
123
117
  new({
124
118
  browser_name: 'internet explorer',
125
- platform: :windows,
126
- takes_screenshot: true,
127
- css_selectors_enabled: true,
128
- native_events: true
119
+ platform_name: :windows
129
120
  }.merge(opts))
130
121
  end
131
122
  alias_method :ie, :internet_explorer
132
123
 
133
- def phantomjs(opts = {})
134
- WebDriver.logger.deprecate 'Selenium support for PhantomJS', 'headless Chrome/Firefox or HTMLUnit'
135
- new({
136
- browser_name: 'phantomjs',
137
- javascript_enabled: true,
138
- takes_screenshot: true,
139
- css_selectors_enabled: true
140
- }.merge(opts))
141
- end
142
-
143
- def safari(opts = {})
144
- new({
145
- browser_name: 'safari',
146
- platform: :mac,
147
- javascript_enabled: true,
148
- takes_screenshot: true,
149
- css_selectors_enabled: true
150
- }.merge(opts))
151
- end
152
-
153
124
  #
154
125
  # @api private
155
126
  #
@@ -158,15 +129,26 @@ module Selenium
158
129
  data = data.dup
159
130
 
160
131
  caps = new
161
- caps.browser_name = data.delete('browserName')
162
- caps.version = data.delete('version')
163
- caps.platform = data.delete('platform').downcase.tr(' ', '_').to_sym if data.key?('platform')
164
- caps.javascript_enabled = data.delete('javascriptEnabled')
165
- caps.css_selectors_enabled = data.delete('cssSelectorsEnabled')
166
- caps.takes_screenshot = data.delete('takesScreenshot')
167
- caps.native_events = data.delete('nativeEvents')
168
- caps.rotatable = data.delete('rotatable')
169
- caps.proxy = Proxy.json_create(data['proxy']) if data.key?('proxy') && !data['proxy'].empty?
132
+ caps.browser_name = data.delete('browserName') if data.key?('browserName')
133
+ caps.browser_version = data.delete('browserVersion') if data.key?('browserVersion')
134
+ caps.platform_name = data.delete('platformName') if data.key?('platformName')
135
+ caps.accept_insecure_certs = data.delete('acceptInsecureCerts') if data.key?('acceptInsecureCerts')
136
+ caps.page_load_strategy = data.delete('pageLoadStrategy') if data.key?('pageLoadStrategy')
137
+
138
+ if data.key?('timeouts')
139
+ timeouts = data.delete('timeouts')
140
+ caps.implicit_timeout = timeouts['implicit'] if timeouts
141
+ caps.page_load_timeout = timeouts['pageLoad'] if timeouts
142
+ caps.script_timeout = timeouts['script'] if timeouts
143
+ end
144
+
145
+ if data.key?('proxy')
146
+ proxy = data.delete('proxy')
147
+ caps.proxy = Proxy.json_create(proxy) unless proxy.nil? || proxy.empty?
148
+ end
149
+
150
+ # Remote Server Specific
151
+ caps[:remote_session_id] = data.delete('webdriver.remote.sessionid') if data.key?('webdriver.remote.sessionid')
170
152
 
171
153
  # any remaining pairs will be added as is, with no conversion
172
154
  caps.merge!(data)
@@ -176,21 +158,19 @@ module Selenium
176
158
  end
177
159
 
178
160
  #
179
- # @option :browser_name [String] required browser name
180
- # @option :version [String] required browser version number
181
- # @option :platform [Symbol] one of :any, :win, :mac, or :x
182
- # @option :javascript_enabled [Boolean] does the driver have javascript enabled?
183
- # @option :css_selectors_enabled [Boolean] does the driver support CSS selectors?
184
- # @option :takes_screenshot [Boolean] can this driver take screenshots?
185
- # @option :native_events [Boolean] does this driver use native events?
186
- # @option :proxy [Selenium::WebDriver::Proxy, Hash] proxy configuration
161
+ # @param [Hash] opts
162
+ # @option :browser_name [String] required browser name
163
+ # @option :browser_version [String] required browser version number
164
+ # @option :platform_name [Symbol] one of :any, :win, :mac, or :x
165
+ # @option :accept_insecure_certs [Boolean] does the driver accept insecure SSL certifications?
166
+ # @option :proxy [Selenium::WebDriver::Proxy, Hash] proxy configuration
187
167
  #
188
168
  # @api public
189
169
  #
190
170
 
191
171
  def initialize(opts = {})
192
- @capabilities = DEFAULTS.merge(opts)
193
- self.proxy = opts.delete(:proxy)
172
+ @capabilities = opts
173
+ self.proxy = opts.delete(:proxy)
194
174
  end
195
175
 
196
176
  #
@@ -230,24 +210,20 @@ module Selenium
230
210
  # @api private
231
211
  #
232
212
 
233
- def as_json(*) # rubocop:disable Metrics/CyclomaticComplexity
213
+ def as_json(*)
234
214
  hash = {}
235
215
 
236
216
  @capabilities.each do |key, value|
237
217
  case key
238
218
  when :platform
239
219
  hash['platform'] = value.to_s.upcase
240
- when :firefox_profile
241
- if value
242
- WebDriver.logger.deprecate(':firefox_profile capabilitiy', 'Selenium::WebDriver::Firefox::Options#profile')
243
- hash['firefox_profile'] = value.as_json['zip']
244
- end
245
220
  when :proxy
246
- hash['proxy'] = value.as_json if value
247
- when String, :firefox_binary
248
- if key == :firefox_binary && value
249
- WebDriver.logger.deprecate(':firefox_binary capabilitiy', 'Selenium::WebDriver::Firefox::Options#binary')
221
+ if value
222
+ hash['proxy'] = value.as_json
223
+ hash['proxy']['proxyType'] &&= hash['proxy']['proxyType'].downcase
224
+ hash['proxy']['noProxy'] = hash['proxy']['noProxy'].split(', ') if hash['proxy']['noProxy'].is_a?(String)
250
225
  end
226
+ when String
251
227
  hash[key.to_s] = value
252
228
  when Symbol
253
229
  hash[camel_case(key.to_s)] = value
@@ -268,6 +244,7 @@ module Selenium
268
244
 
269
245
  as_json == other.as_json
270
246
  end
247
+
271
248
  alias_method :eql?, :==
272
249
 
273
250
  protected
@@ -279,6 +256,7 @@ module Selenium
279
256
  def camel_case(str)
280
257
  str.gsub(/_([a-z])/) { Regexp.last_match(1).upcase }
281
258
  end
259
+
282
260
  end # Capabilities
283
261
  end # Remote
284
262
  end # WebDriver
@@ -0,0 +1,156 @@
1
+ # frozen_string_literal: true
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
+ module Selenium
21
+ module WebDriver
22
+ module Remote
23
+
24
+ #
25
+ # https://w3c.github.io/webdriver/#endpoints
26
+ # @api private
27
+ #
28
+
29
+ class Bridge
30
+ COMMANDS = {
31
+ status: [:get, 'status'],
32
+
33
+ #
34
+ # session handling
35
+ #
36
+
37
+ new_session: [:post, 'session'],
38
+ delete_session: [:delete, 'session/:session_id'],
39
+
40
+ #
41
+ # basic driver
42
+ #
43
+
44
+ get: [:post, 'session/:session_id/url'],
45
+ get_current_url: [:get, 'session/:session_id/url'],
46
+ back: [:post, 'session/:session_id/back'],
47
+ forward: [:post, 'session/:session_id/forward'],
48
+ refresh: [:post, 'session/:session_id/refresh'],
49
+ get_title: [:get, 'session/:session_id/title'],
50
+
51
+ #
52
+ # window and Frame handling
53
+ #
54
+
55
+ get_window_handle: [:get, 'session/:session_id/window'],
56
+ new_window: [:post, 'session/:session_id/window/new'],
57
+ close_window: [:delete, 'session/:session_id/window'],
58
+ switch_to_window: [:post, 'session/:session_id/window'],
59
+ get_window_handles: [:get, 'session/:session_id/window/handles'],
60
+ fullscreen_window: [:post, 'session/:session_id/window/fullscreen'],
61
+ minimize_window: [:post, 'session/:session_id/window/minimize'],
62
+ maximize_window: [:post, 'session/:session_id/window/maximize'],
63
+ set_window_size: [:post, 'session/:session_id/window/size'],
64
+ get_window_size: [:get, 'session/:session_id/window/size'],
65
+ set_window_position: [:post, 'session/:session_id/window/position'],
66
+ get_window_position: [:get, 'session/:session_id/window/position'],
67
+ set_window_rect: [:post, 'session/:session_id/window/rect'],
68
+ get_window_rect: [:get, 'session/:session_id/window/rect'],
69
+ switch_to_frame: [:post, 'session/:session_id/frame'],
70
+ switch_to_parent_frame: [:post, 'session/:session_id/frame/parent'],
71
+
72
+ #
73
+ # element
74
+ #
75
+
76
+ find_element: [:post, 'session/:session_id/element'],
77
+ find_elements: [:post, 'session/:session_id/elements'],
78
+ find_child_element: [:post, 'session/:session_id/element/:id/element'],
79
+ find_child_elements: [:post, 'session/:session_id/element/:id/elements'],
80
+ get_active_element: [:get, 'session/:session_id/element/active'],
81
+ is_element_selected: [:get, 'session/:session_id/element/:id/selected'],
82
+ get_element_attribute: [:get, 'session/:session_id/element/:id/attribute/:name'],
83
+ get_element_property: [:get, 'session/:session_id/element/:id/property/:name'],
84
+ get_element_css_value: [:get, 'session/:session_id/element/:id/css/:property_name'],
85
+ get_element_text: [:get, 'session/:session_id/element/:id/text'],
86
+ get_element_tag_name: [:get, 'session/:session_id/element/:id/name'],
87
+ get_element_rect: [:get, 'session/:session_id/element/:id/rect'],
88
+ is_element_enabled: [:get, 'session/:session_id/element/:id/enabled'],
89
+
90
+ #
91
+ # document handling
92
+ #
93
+
94
+ get_page_source: [:get, 'session/:session_id/source'],
95
+ execute_script: [:post, 'session/:session_id/execute/sync'],
96
+ execute_async_script: [:post, 'session/:session_id/execute/async'],
97
+
98
+ #
99
+ # cookies
100
+ #
101
+
102
+ get_all_cookies: [:get, 'session/:session_id/cookie'],
103
+ get_cookie: [:get, 'session/:session_id/cookie/:name'],
104
+ add_cookie: [:post, 'session/:session_id/cookie'],
105
+ delete_cookie: [:delete, 'session/:session_id/cookie/:name'],
106
+ delete_all_cookies: [:delete, 'session/:session_id/cookie'],
107
+
108
+ #
109
+ # timeouts
110
+ #
111
+
112
+ set_timeout: [:post, 'session/:session_id/timeouts'],
113
+
114
+ #
115
+ # actions
116
+ #
117
+
118
+ actions: [:post, 'session/:session_id/actions'],
119
+ release_actions: [:delete, 'session/:session_id/actions'],
120
+
121
+ #
122
+ # Element Operations
123
+ #
124
+
125
+ element_click: [:post, 'session/:session_id/element/:id/click'],
126
+ element_tap: [:post, 'session/:session_id/element/:id/tap'],
127
+ element_clear: [:post, 'session/:session_id/element/:id/clear'],
128
+ element_send_keys: [:post, 'session/:session_id/element/:id/value'],
129
+
130
+ #
131
+ # alerts
132
+ #
133
+
134
+ dismiss_alert: [:post, 'session/:session_id/alert/dismiss'],
135
+ accept_alert: [:post, 'session/:session_id/alert/accept'],
136
+ get_alert_text: [:get, 'session/:session_id/alert/text'],
137
+ send_alert_text: [:post, 'session/:session_id/alert/text'],
138
+
139
+ #
140
+ # screenshot
141
+ #
142
+
143
+ take_screenshot: [:get, 'session/:session_id/screenshot'],
144
+ take_element_screenshot: [:get, 'session/:session_id/element/:id/screenshot'],
145
+
146
+ #
147
+ # server extensions
148
+ #
149
+
150
+ upload_file: [:post, 'session/:session_id/se/file']
151
+ }.freeze
152
+
153
+ end # Bridge
154
+ end # Remote
155
+ end # WebDriver
156
+ end # Selenium
@@ -36,12 +36,19 @@ module Selenium
36
36
 
37
37
  def initialize(opts = {})
38
38
  listener = opts.delete(:listener)
39
- @bridge = Bridge.handshake(opts)
40
- if @bridge.dialect == :oss
41
- extend DriverExtensions::HasTouchScreen
42
- extend DriverExtensions::HasLocation
43
- extend DriverExtensions::HasNetworkConnection
39
+ desired_capabilities = opts.delete(:desired_capabilities) { Capabilities.new }
40
+
41
+ if desired_capabilities.is_a?(Symbol)
42
+ unless Capabilities.respond_to?(desired_capabilities)
43
+ raise Error::WebDriverError, "invalid desired capability: #{desired_capabilities.inspect}"
44
+ end
45
+
46
+ desired_capabilities = Capabilities.__send__(desired_capabilities)
44
47
  end
48
+
49
+ @bridge = Bridge.new(opts)
50
+ @bridge.create_session(desired_capabilities, opts.delete(:options))
51
+
45
52
  super(@bridge, listener: listener)
46
53
  end
47
54