selenium-webdriver 4.0.0.alpha5 → 4.0.0.beta3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (87) hide show
  1. checksums.yaml +4 -4
  2. data/lib/selenium/devtools.rb +30 -0
  3. data/lib/selenium/server.rb +18 -26
  4. data/lib/selenium/webdriver.rb +1 -3
  5. data/lib/selenium/webdriver/atoms/findElements.js +93 -93
  6. data/lib/selenium/webdriver/atoms/getAttribute.js +75 -59
  7. data/lib/selenium/webdriver/atoms/isDisplayed.js +72 -72
  8. data/lib/selenium/webdriver/atoms/mutationListener.js +55 -0
  9. data/lib/selenium/webdriver/chrome.rb +1 -1
  10. data/lib/selenium/webdriver/chrome/driver.rb +28 -6
  11. data/lib/selenium/webdriver/chrome/{bridge.rb → features.rb} +6 -8
  12. data/lib/selenium/webdriver/chrome/options.rb +54 -37
  13. data/lib/selenium/webdriver/chrome/profile.rb +6 -3
  14. data/lib/selenium/webdriver/chrome/service.rb +4 -2
  15. data/lib/selenium/webdriver/common.rb +7 -2
  16. data/lib/selenium/webdriver/common/driver.rb +86 -26
  17. data/lib/selenium/webdriver/common/driver_extensions/has_authentication.rb +89 -0
  18. data/lib/selenium/webdriver/common/driver_extensions/has_devtools.rb +6 -1
  19. data/lib/selenium/webdriver/common/driver_extensions/has_location.rb +5 -8
  20. data/lib/selenium/webdriver/common/driver_extensions/has_log_events.rb +149 -0
  21. data/lib/selenium/webdriver/{edge_chrome/bridge.rb → common/driver_extensions/has_logs.rb} +7 -7
  22. data/lib/selenium/webdriver/common/driver_extensions/has_network_connection.rb +6 -27
  23. data/lib/selenium/webdriver/common/driver_extensions/has_network_interception.rb +67 -0
  24. data/lib/selenium/webdriver/common/driver_extensions/has_remote_status.rb +1 -0
  25. data/lib/selenium/webdriver/common/driver_extensions/{rotatable.rb → prints_page.rb} +18 -20
  26. data/lib/selenium/webdriver/common/element.rb +66 -12
  27. data/lib/selenium/webdriver/common/interactions/interaction.rb +4 -1
  28. data/lib/selenium/webdriver/common/logger.rb +6 -3
  29. data/lib/selenium/webdriver/common/manager.rb +11 -1
  30. data/lib/selenium/webdriver/common/options.rb +90 -11
  31. data/lib/selenium/webdriver/common/platform.rb +3 -1
  32. data/lib/selenium/webdriver/common/port_prober.rb +4 -6
  33. data/lib/selenium/webdriver/common/proxy.rb +4 -1
  34. data/lib/selenium/webdriver/common/search_context.rb +4 -1
  35. data/lib/selenium/webdriver/common/service.rb +13 -114
  36. data/lib/selenium/webdriver/common/service_manager.rb +151 -0
  37. data/lib/selenium/webdriver/common/socket_poller.rb +19 -30
  38. data/lib/selenium/webdriver/common/takes_screenshot.rb +63 -0
  39. data/lib/selenium/webdriver/common/target_locator.rb +4 -4
  40. data/lib/selenium/webdriver/devtools.rb +144 -0
  41. data/lib/selenium/webdriver/devtools/console_event.rb +38 -0
  42. data/lib/selenium/webdriver/{edge_html/driver.rb → devtools/exception_event.rb} +10 -13
  43. data/lib/selenium/webdriver/devtools/mutation_event.rb +37 -0
  44. data/lib/selenium/webdriver/devtools/request.rb +57 -0
  45. data/lib/selenium/webdriver/edge.rb +7 -29
  46. data/lib/selenium/webdriver/{edge_chrome → edge}/driver.rb +10 -4
  47. data/lib/selenium/webdriver/edge/features.rb +39 -0
  48. data/lib/selenium/webdriver/{edge_chrome → edge}/options.rb +12 -3
  49. data/lib/selenium/webdriver/{edge_chrome → edge}/profile.rb +2 -2
  50. data/lib/selenium/webdriver/{edge_chrome → edge}/service.rb +2 -2
  51. data/lib/selenium/webdriver/firefox.rb +5 -1
  52. data/lib/selenium/webdriver/firefox/driver.rb +19 -3
  53. data/lib/selenium/webdriver/firefox/{bridge.rb → features.rb} +3 -3
  54. data/lib/selenium/webdriver/firefox/options.rb +25 -31
  55. data/lib/selenium/webdriver/firefox/profile.rb +12 -2
  56. data/lib/selenium/webdriver/firefox/service.rb +1 -1
  57. data/lib/selenium/webdriver/ie/driver.rb +1 -2
  58. data/lib/selenium/webdriver/ie/options.rb +7 -20
  59. data/lib/selenium/webdriver/ie/service.rb +4 -2
  60. data/lib/selenium/webdriver/remote/bridge.rb +50 -42
  61. data/lib/selenium/webdriver/remote/capabilities.rb +127 -71
  62. data/lib/selenium/webdriver/remote/commands.rb +3 -0
  63. data/lib/selenium/webdriver/remote/driver.rb +10 -3
  64. data/lib/selenium/webdriver/remote/http/common.rb +0 -5
  65. data/lib/selenium/webdriver/remote/http/default.rb +8 -7
  66. data/lib/selenium/webdriver/remote/http/persistent.rb +6 -0
  67. data/lib/selenium/webdriver/safari.rb +8 -1
  68. data/lib/selenium/webdriver/safari/driver.rb +3 -4
  69. data/lib/selenium/webdriver/safari/{bridge.rb → features.rb} +3 -3
  70. data/lib/selenium/webdriver/safari/options.rb +1 -33
  71. data/lib/selenium/webdriver/support/block_event_listener.rb +1 -1
  72. data/lib/selenium/webdriver/support/color.rb +2 -2
  73. data/lib/selenium/webdriver/support/event_firing_bridge.rb +1 -1
  74. data/lib/selenium/webdriver/support/guards.rb +95 -0
  75. data/lib/selenium/webdriver/support/guards/guard.rb +89 -0
  76. data/lib/selenium/webdriver/support/guards/guard_condition.rb +52 -0
  77. data/lib/selenium/webdriver/support/select.rb +2 -2
  78. data/lib/selenium/webdriver/version.rb +1 -1
  79. metadata +69 -32
  80. data/CHANGES +0 -1725
  81. data/Gemfile +0 -4
  82. data/LICENSE +0 -202
  83. data/README.md +0 -35
  84. data/lib/selenium/webdriver/common/driver_extensions/takes_screenshot.rb +0 -65
  85. data/lib/selenium/webdriver/edge_html/options.rb +0 -91
  86. data/lib/selenium/webdriver/edge_html/service.rb +0 -47
  87. data/selenium-webdriver.gemspec +0 -48
@@ -40,22 +40,15 @@ module Selenium
40
40
  :unhandled_prompt_behavior,
41
41
  :strict_file_interactability,
42
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
43
+ # remote-specific (webdriver.remote.sessionid)
44
+ :remote_session_id
50
45
  ].freeze
51
46
 
52
- KNOWN.each do |key|
47
+ (KNOWN - %i[proxy timeouts]).each do |key|
53
48
  define_method key do
54
49
  @capabilities.fetch(key)
55
50
  end
56
51
 
57
- next if key == :proxy
58
-
59
52
  define_method "#{key}=" do |value|
60
53
  @capabilities[key] = value
61
54
  end
@@ -82,39 +75,22 @@ module Selenium
82
75
  end
83
76
 
84
77
  def edge(opts = {})
85
- edge_html(opts)
86
- end
87
-
88
- def edge_html(opts = {})
89
- new({
90
- browser_name: 'MicrosoftEdge',
91
- platform_name: :windows
92
- }.merge(opts))
93
- end
94
-
95
- def edge_chrome(opts = {})
96
78
  new({
97
79
  browser_name: 'MicrosoftEdge'
98
80
  }.merge(opts))
99
81
  end
82
+ alias_method :microsoftedge, :edge
100
83
 
101
84
  def firefox(opts = {})
102
- opts[:browser_version] = opts.delete(:version) if opts.key?(:version)
103
- opts[:platform_name] = opts.delete(:platform) if opts.key?(:platform)
104
- opts[:timeouts] = {}
105
- opts[:timeouts]['implicit'] = opts.delete(:implicit_timeout) if opts.key?(:implicit_timeout)
106
- opts[:timeouts]['pageLoad'] = opts.delete(:page_load_timeout) if opts.key?(:page_load_timeout)
107
- opts[:timeouts]['script'] = opts.delete(:script_timeout) if opts.key?(:script_timeout)
108
- opts.delete(:timeouts) if opts[:timeouts].empty?
109
- new({browser_name: 'firefox'}.merge(opts))
85
+ new({
86
+ browser_name: 'firefox'
87
+ }.merge(opts))
110
88
  end
111
-
112
89
  alias_method :ff, :firefox
113
90
 
114
91
  def safari(opts = {})
115
92
  new({
116
- browser_name: 'safari',
117
- platform_name: :mac
93
+ browser_name: Selenium::WebDriver::Safari.technology_preview? ? "Safari Technology Preview" : 'safari'
118
94
  }.merge(opts))
119
95
  end
120
96
 
@@ -132,26 +108,23 @@ module Selenium
132
108
  end
133
109
  alias_method :ie, :internet_explorer
134
110
 
111
+ def always_match(capabilities)
112
+ new(always_match: capabilities)
113
+ end
114
+
115
+ def first_match(*capabilities)
116
+ new(first_match: capabilities)
117
+ end
118
+
135
119
  #
136
120
  # @api private
137
121
  #
138
122
 
139
123
  def json_create(data)
140
124
  data = data.dup
141
-
142
125
  caps = new
143
- caps.browser_name = data.delete('browserName') if data.key?('browserName')
144
- caps.browser_version = data.delete('browserVersion') if data.key?('browserVersion')
145
- caps.platform_name = data.delete('platformName') if data.key?('platformName')
146
- caps.accept_insecure_certs = data.delete('acceptInsecureCerts') if data.key?('acceptInsecureCerts')
147
- caps.page_load_strategy = data.delete('pageLoadStrategy') if data.key?('pageLoadStrategy')
148
-
149
- if data.key?('timeouts')
150
- timeouts = data.delete('timeouts')
151
- caps.implicit_timeout = timeouts['implicit'] if timeouts
152
- caps.page_load_timeout = timeouts['pageLoad'] if timeouts
153
- caps.script_timeout = timeouts['script'] if timeouts
154
- end
126
+
127
+ process_timeouts(caps, data.delete('timeouts'))
155
128
 
156
129
  if data.key?('proxy')
157
130
  proxy = data.delete('proxy')
@@ -159,13 +132,34 @@ module Selenium
159
132
  end
160
133
 
161
134
  # Remote Server Specific
162
- caps[:remote_session_id] = data.delete('webdriver.remote.sessionid') if data.key?('webdriver.remote.sessionid')
135
+ if data.key?('webdriver.remote.sessionid')
136
+ caps[:remote_session_id] = data.delete('webdriver.remote.sessionid')
137
+ end
138
+
139
+ KNOWN.each do |cap|
140
+ data_value = camel_case(cap)
141
+ caps[cap] = data.delete(data_value) if data.key?(data_value)
142
+ end
163
143
 
164
144
  # any remaining pairs will be added as is, with no conversion
165
145
  caps.merge!(data)
166
146
 
167
147
  caps
168
148
  end
149
+
150
+ def camel_case(str_or_sym)
151
+ str_or_sym.to_s.gsub(/_([a-z])/) { Regexp.last_match(1).upcase }
152
+ end
153
+
154
+ private
155
+
156
+ def process_timeouts(caps, timeouts)
157
+ return if timeouts.nil?
158
+
159
+ caps.implicit_timeout = timeouts['implicit']
160
+ caps.page_load_timeout = timeouts['pageLoad']
161
+ caps.script_timeout = timeouts['script']
162
+ end
169
163
  end
170
164
 
171
165
  #
@@ -180,8 +174,9 @@ module Selenium
180
174
  #
181
175
 
182
176
  def initialize(opts = {})
183
- @capabilities = opts
184
- self.proxy = opts.delete(:proxy)
177
+ @capabilities = {}
178
+ self.proxy = opts.delete(:proxy) if opts[:proxy]
179
+ @capabilities.merge!(opts)
185
180
  end
186
181
 
187
182
  #
@@ -206,6 +201,10 @@ module Selenium
206
201
  end
207
202
  end
208
203
 
204
+ def proxy
205
+ @capabilities.fetch(:proxy)
206
+ end
207
+
209
208
  def proxy=(proxy)
210
209
  case proxy
211
210
  when Hash
@@ -217,33 +216,46 @@ module Selenium
217
216
  end
218
217
  end
219
218
 
219
+ def timeouts
220
+ @capabilities[:timeouts] ||= {}
221
+ end
222
+
223
+ def timeouts=(timeouts)
224
+ @capabilities[:timeouts] = timeouts
225
+ end
226
+
227
+ def implicit_timeout
228
+ timeouts[:implicit]
229
+ end
230
+
231
+ def implicit_timeout=(timeout)
232
+ timeouts[:implicit] = timeout
233
+ end
234
+
235
+ def page_load_timeout
236
+ timeouts[:page_load] || timeouts[:pageLoad]
237
+ end
238
+
239
+ def page_load_timeout=(timeout)
240
+ timeouts[:page_load] = timeout
241
+ end
242
+
243
+ def script_timeout
244
+ timeouts[:script]
245
+ end
246
+
247
+ def script_timeout=(timeout)
248
+ timeouts[:script] = timeout
249
+ end
250
+
220
251
  #
221
252
  # @api private
222
253
  #
223
254
 
224
255
  def as_json(*)
225
- hash = {}
226
-
227
- @capabilities.each do |key, value|
228
- case key
229
- when :platform
230
- hash['platform'] = value.to_s.upcase
231
- when :proxy
232
- if value
233
- hash['proxy'] = value.as_json
234
- hash['proxy']['proxyType'] &&= hash['proxy']['proxyType'].downcase
235
- hash['proxy']['noProxy'] = hash['proxy']['noProxy'].split(', ') if hash['proxy']['noProxy'].is_a?(String)
236
- end
237
- when String
238
- hash[key.to_s] = value
239
- when Symbol
240
- hash[camel_case(key.to_s)] = value
241
- else
242
- raise TypeError, "expected String or Symbol, got #{key.inspect}:#{key.class} / #{value.inspect}"
243
- end
256
+ @capabilities.each_with_object({}) do |(key, value), hash|
257
+ hash[convert_key(key)] = process_capabilities(key, value, hash)
244
258
  end
245
-
246
- hash
247
259
  end
248
260
 
249
261
  def to_json(*)
@@ -264,10 +276,54 @@ module Selenium
264
276
 
265
277
  private
266
278
 
267
- def camel_case(str)
268
- str.gsub(/_([a-z])/) { Regexp.last_match(1).upcase }
279
+ def process_capabilities(key, value, hash)
280
+ case value
281
+ when Array
282
+ value.map { |v| process_capabilities(key, v, hash) }
283
+ when Hash
284
+ value.each_with_object({}) do |(k, v), h|
285
+ h[convert_key(k)] = process_capabilities(k, v, h)
286
+ end
287
+ when Capabilities, Options
288
+ value.as_json
289
+ else
290
+ convert_value(key, value)
291
+ end
292
+ end
293
+
294
+ def convert_key(key)
295
+ case key
296
+ when String
297
+ key.to_s
298
+ when Symbol
299
+ self.class.camel_case(key)
300
+ else
301
+ raise TypeError, "expected String or Symbol, got #{key.inspect}:#{key.class}"
302
+ end
269
303
  end
270
304
 
305
+ def convert_value(key, value)
306
+ case key
307
+ when :platform
308
+ value.to_s.upcase
309
+ when :proxy
310
+ convert_proxy(value)
311
+ when :unhandled_prompt_behavior
312
+ value.is_a?(Symbol) ? value.to_s.tr('_', ' ') : value
313
+ else
314
+ value
315
+ end
316
+ end
317
+
318
+ def convert_proxy(value)
319
+ return unless value
320
+
321
+ hash = value.as_json
322
+ hash['proxyType'] &&= hash['proxyType'].downcase
323
+ hash['noProxy'] = hash['noProxy'].split(', ') if hash['noProxy'].is_a?(String)
324
+
325
+ hash
326
+ end
271
327
  end # Capabilities
272
328
  end # Remote
273
329
  end # WebDriver
@@ -82,6 +82,8 @@ module Selenium
82
82
  get_element_attribute: [:get, 'session/:session_id/element/:id/attribute/:name'],
83
83
  get_element_property: [:get, 'session/:session_id/element/:id/property/:name'],
84
84
  get_element_css_value: [:get, 'session/:session_id/element/:id/css/:property_name'],
85
+ get_element_aria_role: [:get, 'session/:session_id/element/:id/computedrole'],
86
+ get_element_aria_label: [:get, 'session/:session_id/element/:id/computedlabel'],
85
87
  get_element_text: [:get, 'session/:session_id/element/:id/text'],
86
88
  get_element_tag_name: [:get, 'session/:session_id/element/:id/name'],
87
89
  get_element_rect: [:get, 'session/:session_id/element/:id/rect'],
@@ -117,6 +119,7 @@ module Selenium
117
119
 
118
120
  actions: [:post, 'session/:session_id/actions'],
119
121
  release_actions: [:delete, 'session/:session_id/actions'],
122
+ print_page: [:post, 'session/:session_id/print'],
120
123
 
121
124
  #
122
125
  # Element Operations
@@ -28,11 +28,8 @@ module Selenium
28
28
 
29
29
  class Driver < WebDriver::Driver
30
30
  include DriverExtensions::UploadsFiles
31
- include DriverExtensions::TakesScreenshot
32
31
  include DriverExtensions::HasSessionId
33
- include DriverExtensions::Rotatable
34
32
  include DriverExtensions::HasRemoteStatus
35
- include DriverExtensions::HasWebStorage
36
33
 
37
34
  def initialize(bridge: nil, listener: nil, **opts)
38
35
  desired_capabilities = opts[:desired_capabilities]
@@ -46,6 +43,16 @@ module Selenium
46
43
  opts[:url] ||= "http://#{Platform.localhost}:4444/wd/hub"
47
44
  super
48
45
  end
46
+
47
+ private
48
+
49
+ def devtools_url
50
+ capabilities['se:cdp']
51
+ end
52
+
53
+ def devtools_version
54
+ capabilities['se:cdpVersion'].split('.').first
55
+ end
49
56
  end # Driver
50
57
  end # Remote
51
58
  end # WebDriver
@@ -30,13 +30,8 @@ module Selenium
30
30
  'User-Agent' => "selenium/#{WebDriver::VERSION} (ruby #{Platform.os})"
31
31
  }.freeze
32
32
 
33
- attr_accessor :timeout
34
33
  attr_writer :server_url
35
34
 
36
- def initialize
37
- @timeout = nil
38
- end
39
-
40
35
  def quit_errors
41
36
  [IOError]
42
37
  end
@@ -28,8 +28,7 @@ module Selenium
28
28
  class Default < Common
29
29
  attr_writer :proxy
30
30
 
31
- attr_accessor :open_timeout
32
- attr_accessor :read_timeout
31
+ attr_accessor :open_timeout, :read_timeout
33
32
 
34
33
  # Initializes object.
35
34
  # Warning: Setting {#open_timeout} to non-nil values will cause a separate thread to spawn.
@@ -39,6 +38,7 @@ module Selenium
39
38
  def initialize(open_timeout: nil, read_timeout: nil)
40
39
  @open_timeout = open_timeout
41
40
  @read_timeout = read_timeout
41
+ super()
42
42
  end
43
43
 
44
44
  def close
@@ -55,8 +55,7 @@ module Selenium
55
55
  http.verify_mode = OpenSSL::SSL::VERIFY_NONE
56
56
  end
57
57
 
58
- # Defaulting open_timeout to nil to be consistent with Ruby 2.2 and earlier.
59
- http.open_timeout = open_timeout
58
+ http.open_timeout = open_timeout if open_timeout
60
59
  http.read_timeout = read_timeout if read_timeout
61
60
 
62
61
  start(http)
@@ -128,12 +127,14 @@ module Selenium
128
127
  def new_http_client
129
128
  if use_proxy?
130
129
  url = @proxy.http
131
- raise Error::WebDriverError, "expected HTTP proxy, got #{@proxy.inspect}" unless proxy.respond_to?(:http) && url
130
+ unless proxy.respond_to?(:http) && url
131
+ raise Error::WebDriverError,
132
+ "expected HTTP proxy, got #{@proxy.inspect}"
133
+ end
132
134
 
133
135
  proxy = URI.parse(url)
134
136
 
135
- clazz = Net::HTTP::Proxy(proxy.host, proxy.port, proxy.user, proxy.password)
136
- clazz.new(server_url.host, server_url.port)
137
+ Net::HTTP.new(server_url.host, server_url.port, proxy.host, proxy.port, proxy.user, proxy.password)
137
138
  else
138
139
  Net::HTTP.new server_url.host, server_url.port
139
140
  end
@@ -25,6 +25,12 @@ module Selenium
25
25
  module Http
26
26
  # @api private
27
27
  class Persistent < Default
28
+ def initialize(open_timeout: nil, read_timeout: nil)
29
+ WebDriver.logger.deprecate("Selenium::WebDriver::Remote::Http::Persistent",
30
+ id: :http_persistent) { "The default HTTP client now uses persistence." }
31
+ super
32
+ end
33
+
28
34
  def close
29
35
  @http&.shutdown
30
36
  end
@@ -20,18 +20,25 @@
20
20
  module Selenium
21
21
  module WebDriver
22
22
  module Safari
23
- autoload :Bridge, 'selenium/webdriver/safari/bridge'
23
+ autoload :Features, 'selenium/webdriver/safari/features'
24
24
  autoload :Driver, 'selenium/webdriver/safari/driver'
25
25
  autoload :Options, 'selenium/webdriver/safari/options'
26
26
  autoload :Service, 'selenium/webdriver/safari/service'
27
27
 
28
28
  class << self
29
+ attr_accessor :use_technology_preview
30
+
29
31
  def technology_preview
30
32
  "/Applications/Safari\ Technology\ Preview.app/Contents/MacOS/safaridriver"
31
33
  end
32
34
 
33
35
  def technology_preview!
34
36
  Service.driver_path = technology_preview
37
+ @use_technology_preview = true
38
+ end
39
+
40
+ def technology_preview?
41
+ use_technology_preview
35
42
  end
36
43
 
37
44
  def path=(path)
@@ -27,10 +27,9 @@ module Selenium
27
27
  #
28
28
 
29
29
  class Driver < WebDriver::Driver
30
- include DriverExtensions::HasDebugger
31
- include DriverExtensions::HasPermissions
32
- include DriverExtensions::HasWebStorage
33
- include DriverExtensions::TakesScreenshot
30
+ EXTENSIONS = [DriverExtensions::HasDebugger,
31
+ DriverExtensions::HasPermissions,
32
+ DriverExtensions::HasWebStorage].freeze
34
33
 
35
34
  def browser
36
35
  :safari