selenium-webdriver 4.0.0.beta2 → 4.0.0.rc2

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 (66) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGES +1947 -0
  3. data/Gemfile +6 -0
  4. data/LICENSE +202 -0
  5. data/NOTICE +2 -0
  6. data/README.md +34 -0
  7. data/lib/selenium/webdriver/atoms/findElements.js +0 -0
  8. data/lib/selenium/webdriver/atoms/getAttribute.js +25 -25
  9. data/lib/selenium/webdriver/atoms/isDisplayed.js +0 -0
  10. data/lib/selenium/webdriver/chrome/driver.rb +16 -4
  11. data/lib/selenium/webdriver/chrome/features.rb +44 -4
  12. data/lib/selenium/webdriver/chrome/options.rb +25 -2
  13. data/lib/selenium/webdriver/chrome/profile.rb +5 -2
  14. data/lib/selenium/webdriver/common/driver.rb +5 -1
  15. data/lib/selenium/webdriver/common/driver_extensions/full_page_screenshot.rb +43 -0
  16. data/lib/selenium/webdriver/common/driver_extensions/has_apple_permissions.rb +51 -0
  17. data/lib/selenium/webdriver/common/driver_extensions/has_casting.rb +77 -0
  18. data/lib/selenium/webdriver/common/driver_extensions/has_cdp.rb +38 -0
  19. data/lib/selenium/webdriver/common/driver_extensions/has_context.rb +45 -0
  20. data/lib/selenium/webdriver/common/driver_extensions/has_devtools.rb +0 -17
  21. data/lib/selenium/{devtools.rb → webdriver/common/driver_extensions/has_launching.rb} +16 -8
  22. data/lib/selenium/webdriver/common/driver_extensions/has_log_events.rb +1 -6
  23. data/lib/selenium/webdriver/common/driver_extensions/has_network_conditions.rb +8 -0
  24. data/lib/selenium/webdriver/common/driver_extensions/has_network_interception.rb +87 -18
  25. data/lib/selenium/webdriver/common/driver_extensions/has_permissions.rb +11 -11
  26. data/lib/selenium/webdriver/common/driver_extensions/has_pinned_scripts.rb +77 -0
  27. data/lib/selenium/webdriver/common/driver_extensions/prints_page.rb +28 -1
  28. data/lib/selenium/webdriver/common/element.rb +35 -6
  29. data/lib/selenium/webdriver/common/error.rb +12 -0
  30. data/lib/selenium/webdriver/common/log_entry.rb +2 -2
  31. data/lib/selenium/webdriver/common/manager.rb +3 -13
  32. data/lib/selenium/webdriver/common/options.rb +31 -12
  33. data/lib/selenium/webdriver/common/proxy.rb +2 -2
  34. data/lib/selenium/webdriver/common/shadow_root.rb +87 -0
  35. data/lib/selenium/webdriver/common/socket_poller.rb +19 -30
  36. data/lib/selenium/webdriver/common/takes_screenshot.rb +9 -6
  37. data/lib/selenium/webdriver/common/target_locator.rb +28 -0
  38. data/lib/selenium/webdriver/common/window.rb +0 -4
  39. data/lib/selenium/webdriver/common.rb +8 -0
  40. data/lib/selenium/webdriver/devtools/pinned_script.rb +59 -0
  41. data/lib/selenium/webdriver/devtools/request.rb +27 -17
  42. data/lib/selenium/webdriver/devtools/response.rb +66 -0
  43. data/lib/selenium/webdriver/devtools.rb +50 -12
  44. data/lib/selenium/webdriver/edge/features.rb +5 -0
  45. data/lib/selenium/webdriver/edge/options.rb +0 -0
  46. data/lib/selenium/webdriver/edge/profile.rb +0 -0
  47. data/lib/selenium/webdriver/firefox/driver.rb +15 -2
  48. data/lib/selenium/webdriver/firefox/features.rb +20 -1
  49. data/lib/selenium/webdriver/firefox/options.rb +24 -1
  50. data/lib/selenium/webdriver/firefox.rb +0 -1
  51. data/lib/selenium/webdriver/ie/options.rb +3 -1
  52. data/lib/selenium/webdriver/ie/service.rb +1 -1
  53. data/lib/selenium/webdriver/remote/bridge.rb +43 -13
  54. data/lib/selenium/webdriver/remote/capabilities.rb +97 -53
  55. data/lib/selenium/webdriver/remote/commands.rb +5 -0
  56. data/lib/selenium/webdriver/remote/driver.rb +7 -7
  57. data/lib/selenium/webdriver/remote.rb +1 -1
  58. data/lib/selenium/webdriver/safari/driver.rb +1 -1
  59. data/lib/selenium/webdriver/safari/options.rb +7 -0
  60. data/lib/selenium/webdriver/support/cdp/domain.rb.erb +63 -0
  61. data/lib/selenium/webdriver/support/cdp_client_generator.rb +108 -0
  62. data/lib/selenium/webdriver/support/event_firing_bridge.rb +2 -2
  63. data/lib/selenium/webdriver/version.rb +1 -1
  64. data/lib/selenium/webdriver.rb +1 -1
  65. data/selenium-webdriver.gemspec +63 -0
  66. metadata +60 -44
@@ -39,23 +39,17 @@ module Selenium
39
39
  :timeouts,
40
40
  :unhandled_prompt_behavior,
41
41
  :strict_file_interactability,
42
+ :web_socket_url,
42
43
 
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
44
+ # remote-specific (webdriver.remote.sessionid)
45
+ :remote_session_id
50
46
  ].freeze
51
47
 
52
- KNOWN.each do |key|
48
+ (KNOWN - %i[proxy timeouts]).each do |key|
53
49
  define_method key do
54
- @capabilities.fetch(key)
50
+ @capabilities[key]
55
51
  end
56
52
 
57
- next if key == :proxy
58
-
59
53
  define_method "#{key}=" do |value|
60
54
  @capabilities[key] = value
61
55
  end
@@ -89,16 +83,10 @@ module Selenium
89
83
  alias_method :microsoftedge, :edge
90
84
 
91
85
  def firefox(opts = {})
92
- opts[:browser_version] = opts.delete(:version) if opts.key?(:version)
93
- opts[:platform_name] = opts.delete(:platform) if opts.key?(:platform)
94
- opts[:timeouts] = {}
95
- opts[:timeouts]['implicit'] = opts.delete(:implicit_timeout) if opts.key?(:implicit_timeout)
96
- opts[:timeouts]['pageLoad'] = opts.delete(:page_load_timeout) if opts.key?(:page_load_timeout)
97
- opts[:timeouts]['script'] = opts.delete(:script_timeout) if opts.key?(:script_timeout)
98
- opts.delete(:timeouts) if opts[:timeouts].empty?
99
- new({browser_name: 'firefox'}.merge(opts))
86
+ new({
87
+ browser_name: 'firefox'
88
+ }.merge(opts))
100
89
  end
101
-
102
90
  alias_method :ff, :firefox
103
91
 
104
92
  def safari(opts = {})
@@ -121,18 +109,21 @@ module Selenium
121
109
  end
122
110
  alias_method :ie, :internet_explorer
123
111
 
112
+ def always_match(capabilities)
113
+ new(always_match: capabilities)
114
+ end
115
+
116
+ def first_match(*capabilities)
117
+ new(first_match: capabilities)
118
+ end
119
+
124
120
  #
125
121
  # @api private
126
122
  #
127
123
 
128
124
  def json_create(data)
129
125
  data = data.dup
130
-
131
126
  caps = new
132
- (KNOWN - %i[timeouts proxy]).each do |cap|
133
- data_value = camel_case(cap)
134
- caps[cap] = data.delete(data_value) if data.key?(data_value)
135
- end
136
127
 
137
128
  process_timeouts(caps, data.delete('timeouts'))
138
129
 
@@ -146,6 +137,11 @@ module Selenium
146
137
  caps[:remote_session_id] = data.delete('webdriver.remote.sessionid')
147
138
  end
148
139
 
140
+ KNOWN.each do |cap|
141
+ data_value = camel_case(cap)
142
+ caps[cap] = data.delete(data_value) if data.key?(data_value)
143
+ end
144
+
149
145
  # any remaining pairs will be added as is, with no conversion
150
146
  caps.merge!(data)
151
147
 
@@ -179,8 +175,9 @@ module Selenium
179
175
  #
180
176
 
181
177
  def initialize(opts = {})
182
- @capabilities = opts
183
- self.proxy = opts.delete(:proxy)
178
+ @capabilities = {}
179
+ self.proxy = opts.delete(:proxy) if opts[:proxy]
180
+ @capabilities.merge!(opts)
184
181
  end
185
182
 
186
183
  #
@@ -205,6 +202,10 @@ module Selenium
205
202
  end
206
203
  end
207
204
 
205
+ def proxy
206
+ @capabilities[:proxy]
207
+ end
208
+
208
209
  def proxy=(proxy)
209
210
  case proxy
210
211
  when Hash
@@ -216,33 +217,46 @@ module Selenium
216
217
  end
217
218
  end
218
219
 
220
+ def timeouts
221
+ @capabilities[:timeouts] ||= {}
222
+ end
223
+
224
+ def timeouts=(timeouts)
225
+ @capabilities[:timeouts] = timeouts
226
+ end
227
+
228
+ def implicit_timeout
229
+ timeouts[:implicit]
230
+ end
231
+
232
+ def implicit_timeout=(timeout)
233
+ timeouts[:implicit] = timeout
234
+ end
235
+
236
+ def page_load_timeout
237
+ timeouts[:page_load] || timeouts[:pageLoad]
238
+ end
239
+
240
+ def page_load_timeout=(timeout)
241
+ timeouts[:page_load] = timeout
242
+ end
243
+
244
+ def script_timeout
245
+ timeouts[:script]
246
+ end
247
+
248
+ def script_timeout=(timeout)
249
+ timeouts[:script] = timeout
250
+ end
251
+
219
252
  #
220
253
  # @api private
221
254
  #
222
255
 
223
256
  def as_json(*)
224
- hash = {}
225
-
226
- @capabilities.each do |key, value|
227
- case key
228
- when :platform
229
- hash['platform'] = value.to_s.upcase
230
- when :proxy
231
- next unless value
232
-
233
- process_proxy(hash, value)
234
- when :unhandled_prompt_behavior
235
- hash['unhandledPromptBehavior'] = value.is_a?(Symbol) ? value.to_s.tr('_', ' ') : value
236
- when String
237
- hash[key.to_s] = value
238
- when Symbol
239
- hash[self.class.camel_case(key)] = value
240
- else
241
- raise TypeError, "expected String or Symbol, got #{key.inspect}:#{key.class} / #{value.inspect}"
242
- end
257
+ @capabilities.each_with_object({}) do |(key, value), hash|
258
+ hash[convert_key(key)] = process_capabilities(key, value, hash)
243
259
  end
244
-
245
- hash
246
260
  end
247
261
 
248
262
  def to_json(*)
@@ -263,13 +277,43 @@ module Selenium
263
277
 
264
278
  private
265
279
 
266
- def process_proxy(hash, value)
267
- hash['proxy'] = value.as_json
268
- hash['proxy']['proxyType'] &&= hash['proxy']['proxyType'].downcase
280
+ def process_capabilities(key, value, hash)
281
+ case value
282
+ when Array
283
+ value.map { |v| process_capabilities(key, v, hash) }
284
+ when Hash
285
+ value.each_with_object({}) do |(k, v), h|
286
+ h[convert_key(k)] = process_capabilities(k, v, h)
287
+ end
288
+ when Capabilities, Options
289
+ value.as_json
290
+ else
291
+ convert_value(key, value)
292
+ end
293
+ end
269
294
 
270
- return unless hash['proxy']['noProxy'].is_a?(String)
295
+ def convert_key(key)
296
+ case key
297
+ when String
298
+ key.to_s
299
+ when Symbol
300
+ self.class.camel_case(key)
301
+ else
302
+ raise TypeError, "expected String or Symbol, got #{key.inspect}:#{key.class}"
303
+ end
304
+ end
271
305
 
272
- hash['proxy']['noProxy'] = hash['proxy']['noProxy'].split(', ')
306
+ def convert_value(key, value)
307
+ case key
308
+ when :platform
309
+ value.to_s.upcase
310
+ when :proxy
311
+ value&.as_json
312
+ when :unhandled_prompt_behavior
313
+ value.is_a?(Symbol) ? value.to_s.tr('_', ' ') : value
314
+ else
315
+ value
316
+ end
273
317
  end
274
318
  end # Capabilities
275
319
  end # Remote
@@ -77,11 +77,16 @@ module Selenium
77
77
  find_elements: [:post, 'session/:session_id/elements'],
78
78
  find_child_element: [:post, 'session/:session_id/element/:id/element'],
79
79
  find_child_elements: [:post, 'session/:session_id/element/:id/elements'],
80
+ find_shadow_child_element: [:post, 'session/:session_id/shadow/:id/element'],
81
+ find_shadow_child_elements: [:post, 'session/:session_id/shadow/:id/elements'],
80
82
  get_active_element: [:get, 'session/:session_id/element/active'],
83
+ get_element_shadow_root: [:get, 'session/:session_id/element/:id/shadow'],
81
84
  is_element_selected: [:get, 'session/:session_id/element/:id/selected'],
82
85
  get_element_attribute: [:get, 'session/:session_id/element/:id/attribute/:name'],
83
86
  get_element_property: [:get, 'session/:session_id/element/:id/property/:name'],
84
87
  get_element_css_value: [:get, 'session/:session_id/element/:id/css/:property_name'],
88
+ get_element_aria_role: [:get, 'session/:session_id/element/:id/computedrole'],
89
+ get_element_aria_label: [:get, 'session/:session_id/element/:id/computedlabel'],
85
90
  get_element_text: [:get, 'session/:session_id/element/:id/text'],
86
91
  get_element_tag_name: [:get, 'session/:session_id/element/:id/name'],
87
92
  get_element_rect: [:get, 'session/:session_id/element/:id/rect'],
@@ -42,19 +42,19 @@ module Selenium
42
42
  end
43
43
  opts[:url] ||= "http://#{Platform.localhost}:4444/wd/hub"
44
44
  super
45
- end
46
-
47
- def print_page(**options)
48
- options[:page_ranges] &&= Array(options[:page_ranges])
49
-
50
- @bridge.print_page(options)
45
+ @bridge.file_detector = ->((filename, *)) { File.exist?(filename) && filename.to_s }
51
46
  end
52
47
 
53
48
  private
54
49
 
55
- def devtools_address
50
+ def devtools_url
56
51
  capabilities['se:cdp']
57
52
  end
53
+
54
+ def devtools_version
55
+ capabilities['se:cdpVersion']&.split('.')&.first ||
56
+ raise(Error::WebDriverError, "DevTools is not supported by the Remote Server")
57
+ end
58
58
  end # Driver
59
59
  end # Remote
60
60
  end # WebDriver
@@ -18,6 +18,7 @@
18
18
  # under the License.
19
19
 
20
20
  require 'uri'
21
+ require 'selenium/webdriver/remote/server_error'
21
22
 
22
23
  module Selenium
23
24
  module WebDriver
@@ -25,7 +26,6 @@ module Selenium
25
26
  autoload :Bridge, 'selenium/webdriver/remote/bridge'
26
27
  autoload :Driver, 'selenium/webdriver/remote/driver'
27
28
  autoload :Response, 'selenium/webdriver/remote/response'
28
- autoload :ServerError, 'selenium/webdriver/remote/server_error'
29
29
  autoload :Capabilities, 'selenium/webdriver/remote/capabilities'
30
30
  autoload :COMMANDS, 'selenium/webdriver/remote/commands'
31
31
  module Http
@@ -28,7 +28,7 @@ module Selenium
28
28
 
29
29
  class Driver < WebDriver::Driver
30
30
  EXTENSIONS = [DriverExtensions::HasDebugger,
31
- DriverExtensions::HasPermissions,
31
+ DriverExtensions::HasApplePermissions,
32
32
  DriverExtensions::HasWebStorage].freeze
33
33
 
34
34
  def browser
@@ -28,6 +28,13 @@ module Selenium
28
28
  automatic_profiling: 'safari:automaticProfiling'}.freeze
29
29
  BROWSER = 'safari'
30
30
 
31
+ def add_option(name, value = nil)
32
+ key = name.is_a?(Hash) ? name.keys.first : name
33
+ raise ArgumentError, 'Safari does not support options that are not namespaced' unless key.to_s.include?(':')
34
+
35
+ super
36
+ end
37
+
31
38
  end # Options
32
39
  end # Safari
33
40
  end # WebDriver
@@ -0,0 +1,63 @@
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
+ # This file is automatically generated. Any changes will be lost!
21
+ module Selenium
22
+ module DevTools
23
+ module <%= version %>
24
+ class <%= domain[:domain] %>
25
+ <% if domain[:events] %>
26
+ EVENTS = {
27
+ <% domain[:events].each do |event| %>
28
+ <%= h.snake_case(event[:name]) %>: '<%= event[:name] %>',
29
+ <% end %>
30
+ }.freeze
31
+ <% end %>
32
+
33
+ def initialize(devtools)
34
+ @devtools = devtools
35
+ end
36
+
37
+ def on(event, &block)
38
+ event = EVENTS[event] if event.is_a?(Symbol)
39
+ @devtools.callbacks["<%= domain[:domain] %>.#{event}"] << block
40
+ end
41
+
42
+ <% domain[:commands].each do |command| %>
43
+ <% if command[:parameters] %>
44
+ def <%= h.snake_case(command[:name]) %>(<%= h.kwargs(command[:parameters]) %>)
45
+ <% else %>
46
+ def <%= h.snake_case(command[:name]) %>
47
+ <% end %>
48
+ <% if command[:parameters] %>
49
+ @devtools.send_cmd('<%= domain[:domain] %>.<%= command[:name] %>',
50
+ <% until command[:parameters].empty? %>
51
+ <% parameter = command[:parameters].shift %>
52
+ <%= parameter[:name] %>: <%= h.snake_case(parameter[:name]) %><%= command[:parameters].empty? ? ')' : ',' %>
53
+ <% end %>
54
+ <% else %>
55
+ @devtools.send_cmd('<%= domain[:domain] %>.<%= command[:name] %>')
56
+ <% end %>
57
+ end
58
+
59
+ <% end %>
60
+ end # <%= domain[:domain] %>
61
+ end # <%= version %>
62
+ end # DevTools
63
+ end # Selenium
@@ -0,0 +1,108 @@
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
+ require 'erb'
21
+ require 'fileutils'
22
+ require 'json'
23
+
24
+ module Selenium
25
+ module WebDriver
26
+ module Support
27
+ class CDPClientGenerator
28
+ # Input JSON files are generated from PDL tasks.
29
+ TEMPLATE_PATH = File.expand_path('cdp/domain.rb.erb', __dir__)
30
+
31
+ RESERVED_KEYWORDS = %w[end].freeze
32
+
33
+ def call(output_dir:, version:, browser_protocol_path: nil, js_protocol_path: nil, loader_path: nil, **)
34
+ @template = ERB.new(File.read(TEMPLATE_PATH))
35
+ @output_dir = output_dir
36
+ @loader_path = loader_path || "#{@output_dir}.rb"
37
+ @version = version
38
+
39
+ browser_protocol_path ||= File.expand_path('cdp/browser_protocol.json', __dir__)
40
+ js_protocol_path ||= File.expand_path('cdp/js_protocol.json', __dir__)
41
+
42
+ browser_protocol = JSON.parse(File.read(browser_protocol_path), symbolize_names: true)
43
+ js_protocol = JSON.parse(File.read(js_protocol_path), symbolize_names: true)
44
+
45
+ FileUtils.mkdir_p(@output_dir)
46
+
47
+ browser_protocol[:domains].each(&method(:process_domain))
48
+ js_protocol[:domains].each(&method(:process_domain))
49
+ require_file
50
+ end
51
+
52
+ def process_domain(domain)
53
+ result = @template.result_with_hash(domain: domain, version: @version.upcase, h: self)
54
+ filename = File.join(@output_dir, "#{snake_case(domain[:domain])}.rb")
55
+ File.write(filename, remove_empty_lines(result))
56
+ end
57
+
58
+ def snake_case(string)
59
+ name = string.gsub('JavaScript', 'Javascript')
60
+ .gsub(/([A-Z]+)([A-Z][a-z]{2,})/, '\1_\2')
61
+ .gsub(/([a-z\d])([A-Z])/, '\1_\2')
62
+ .downcase
63
+ # Certain CDP parameters conflict with Ruby keywords
64
+ # so we prefix the name with underscore.
65
+ name = "_#{name}" if RESERVED_KEYWORDS.include?(name)
66
+
67
+ name
68
+ end
69
+
70
+ def kwargs(parameters)
71
+ parameters = parameters.map do |parameter|
72
+ if parameter[:optional]
73
+ "#{snake_case(parameter[:name])}: nil"
74
+ else
75
+ "#{snake_case(parameter[:name])}:"
76
+ end
77
+ end
78
+ parameters.join(', ')
79
+ end
80
+
81
+ def remove_empty_lines(string)
82
+ string.split("\n").reject { |l| l =~ /^\s+$/ }.join("\n")
83
+ end
84
+
85
+ def require_file
86
+ # rubocop:disable Lint/InterpolationCheck
87
+ dynamic_location = '#{File.dirname(File.absolute_path(__FILE__))}'
88
+ # rubocop:enable Lint/InterpolationCheck
89
+
90
+ require_all = "Dir.glob(\"#{dynamic_location}/#{@version}/*\", &method(:require))"
91
+ File.open(@loader_path, 'w') { |file| file.write(require_all) }
92
+ end
93
+ end
94
+ end
95
+ end
96
+ end
97
+
98
+ if $PROGRAM_NAME == __FILE__
99
+ browser_protocol_path, js_protocol_path, output_dir, loader_path, version = *ARGV
100
+
101
+ Selenium::WebDriver::Support::CDPClientGenerator.new.call(
102
+ browser_protocol_path: browser_protocol_path,
103
+ js_protocol_path: js_protocol_path,
104
+ output_dir: output_dir,
105
+ loader_path: loader_path,
106
+ version: version
107
+ )
108
+ end
@@ -76,7 +76,7 @@ module Selenium
76
76
  @delegate.find_element_by how, what, parent
77
77
  end
78
78
 
79
- Element.new self, e.ref
79
+ Element.new self, e.ref.last
80
80
  end
81
81
 
82
82
  def find_elements_by(how, what, parent = nil)
@@ -84,7 +84,7 @@ module Selenium
84
84
  @delegate.find_elements_by(how, what, parent)
85
85
  end
86
86
 
87
- es.map { |e| Element.new self, e.ref }
87
+ es.map { |e| Element.new self, e.ref.last }
88
88
  end
89
89
 
90
90
  def execute_script(script, *args)
@@ -19,6 +19,6 @@
19
19
 
20
20
  module Selenium
21
21
  module WebDriver
22
- VERSION = '4.0.0.beta2'
22
+ VERSION = '4.0.0.rc2'
23
23
  end # WebDriver
24
24
  end # Selenium
@@ -23,7 +23,7 @@ require 'fileutils'
23
23
  require 'date'
24
24
  require 'json'
25
25
  require 'set'
26
- require 'websocket'
26
+ require 'uri'
27
27
 
28
28
  require 'selenium/webdriver/atoms'
29
29
  require 'selenium/webdriver/common'
@@ -0,0 +1,63 @@
1
+ # frozen_string_literal: true
2
+
3
+ root = File.expand_path(File.dirname(__FILE__))
4
+ raise "cwd must be #{root} when reading gemspec" if root != Dir.pwd
5
+
6
+ $LOAD_PATH.push(File.expand_path('lib', root))
7
+ require 'selenium/webdriver/version'
8
+
9
+ Gem::Specification.new do |s|
10
+ s.name = 'selenium-webdriver'
11
+ s.version = Selenium::WebDriver::VERSION
12
+
13
+ s.authors = ['Alex Rodionov', 'Titus Fortner', 'Thomas Walpole']
14
+ s.email = %w[p0deje@gmail.com titusfortner@gmail.com twalpole@gmail.com]
15
+
16
+ s.summary = 'Selenium is a browser automation tool for automated testing of webapps and more'
17
+ s.description = <<-DESCRIPTION
18
+ Selenium implements the W3C WebDriver protocol to automate popular browsers.
19
+ It aims to mimic the behaviour of a real user as it interacts with the application's HTML.
20
+ It's primarily intended for web application testing, but any web-based task can automated.
21
+ DESCRIPTION
22
+
23
+ s.license = 'Apache-2.0'
24
+ s.homepage = 'https://selenium.dev'
25
+ s.metadata = {
26
+ 'changelog_uri' => 'https://github.com/SeleniumHQ/selenium/blob/trunk/rb/CHANGES',
27
+ 'source_code_uri' => 'https://github.com/SeleniumHQ/selenium/tree/trunk/rb'
28
+ }
29
+
30
+ s.required_rubygems_version = Gem::Requirement.new('> 1.3.1') if s.respond_to? :required_rubygems_version=
31
+ s.required_ruby_version = Gem::Requirement.new('>= 2.5')
32
+
33
+ s.files = [
34
+ 'CHANGES',
35
+ 'LICENSE',
36
+ 'NOTICE',
37
+ 'Gemfile',
38
+ 'README.md',
39
+ 'selenium-webdriver.gemspec',
40
+ 'lib/selenium-webdriver.rb',
41
+ 'lib/selenium/server.rb',
42
+ 'lib/selenium/webdriver.rb'
43
+ ] + Dir['lib/selenium/webdriver/**/*']
44
+
45
+ s.require_paths = ['lib']
46
+
47
+ s.add_runtime_dependency 'childprocess', ['>= 0.5', '< 5.0']
48
+ s.add_runtime_dependency 'rexml', ['~> 3.2']
49
+ s.add_runtime_dependency 'rubyzip', ['>= 1.2.2']
50
+
51
+ # childprocess requires ffi on windows but doesn't declare it in its dependencies
52
+ s.add_development_dependency 'ffi'
53
+ s.add_development_dependency 'pry', ['~> 0.14']
54
+ s.add_development_dependency 'rack', ['~> 2.0']
55
+ s.add_development_dependency 'rake'
56
+ s.add_development_dependency 'rspec', ['~> 3.0']
57
+ s.add_development_dependency 'rubocop', ['~> 1.8.0']
58
+ s.add_development_dependency 'rubocop-performance'
59
+ s.add_development_dependency 'rubocop-rspec'
60
+ s.add_development_dependency 'webmock', ['~> 3.5']
61
+ s.add_development_dependency 'webrick', ['~> 1.7']
62
+ s.add_development_dependency 'yard', ['~> 0.9.11']
63
+ end