selenium-webdriver 4.0.0.alpha2 → 4.0.0.alpha3

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 (42) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGES +38 -0
  3. data/lib/selenium/server.rb +2 -2
  4. data/lib/selenium/webdriver.rb +9 -7
  5. data/lib/selenium/webdriver/chrome.rb +6 -7
  6. data/lib/selenium/webdriver/chrome/bridge.rb +21 -3
  7. data/lib/selenium/webdriver/chrome/driver.rb +3 -41
  8. data/lib/selenium/webdriver/chrome/options.rb +87 -52
  9. data/lib/selenium/webdriver/chrome/profile.rb +2 -2
  10. data/lib/selenium/webdriver/common.rb +1 -0
  11. data/lib/selenium/webdriver/common/driver.rb +7 -0
  12. data/lib/selenium/webdriver/common/options.rb +92 -0
  13. data/lib/selenium/webdriver/common/profile_helper.rb +10 -2
  14. data/lib/selenium/webdriver/common/service.rb +35 -11
  15. data/lib/selenium/webdriver/edge.rb +25 -7
  16. data/lib/selenium/webdriver/edge_chrome/bridge.rb +30 -0
  17. data/lib/selenium/webdriver/edge_chrome/driver.rb +38 -0
  18. data/lib/selenium/webdriver/edge_chrome/options.rb +34 -0
  19. data/lib/selenium/webdriver/edge_chrome/profile.rb +33 -0
  20. data/lib/selenium/webdriver/edge_chrome/service.rb +40 -0
  21. data/lib/selenium/webdriver/{edge → edge_html}/driver.rb +2 -19
  22. data/lib/selenium/webdriver/{edge → edge_html}/options.rb +26 -15
  23. data/lib/selenium/webdriver/{edge → edge_html}/service.rb +1 -1
  24. data/lib/selenium/webdriver/firefox.rb +9 -12
  25. data/lib/selenium/webdriver/firefox/binary.rb +2 -2
  26. data/lib/selenium/webdriver/firefox/driver.rb +3 -19
  27. data/lib/selenium/webdriver/firefox/extension.rb +8 -0
  28. data/lib/selenium/webdriver/firefox/options.rb +45 -48
  29. data/lib/selenium/webdriver/firefox/profile.rb +5 -3
  30. data/lib/selenium/webdriver/ie.rb +4 -5
  31. data/lib/selenium/webdriver/ie/driver.rb +3 -20
  32. data/lib/selenium/webdriver/ie/options.rb +9 -29
  33. data/lib/selenium/webdriver/remote.rb +16 -10
  34. data/lib/selenium/webdriver/remote/capabilities.rb +10 -0
  35. data/lib/selenium/webdriver/remote/http/default.rb +6 -1
  36. data/lib/selenium/webdriver/remote/http/persistent.rb +5 -6
  37. data/lib/selenium/webdriver/safari.rb +5 -6
  38. data/lib/selenium/webdriver/safari/bridge.rb +3 -3
  39. data/lib/selenium/webdriver/safari/driver.rb +4 -18
  40. data/lib/selenium/webdriver/safari/options.rb +18 -12
  41. data/lib/selenium/webdriver/version.rb +1 -1
  42. metadata +11 -5
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: bfdda64a93649dd407e9a99d0547280f33492826
4
- data.tar.gz: 7c643c63e461f17cabb016812cffa21e3001f813
3
+ metadata.gz: da9450a24f91be2d365f304db93f1b3fbbb6d6e1
4
+ data.tar.gz: 61bec02fa4350770cab7be2fe53e090d2a082f60
5
5
  SHA512:
6
- metadata.gz: a5b8faba158cabc734b9f0fa8e7fc00bdea0b127bafc2b6f363cefd3bc2aea78d176cc5d042eda9c2271d1dd52d951bd93c8449fdb381e7fa35ebafab3ffe88f
7
- data.tar.gz: 113f4c13373c915447172e43cc5da4435bc785693c06e6a119f9ecdd5fcd3efc01a43b8d295f655be00e5176e3a901f721d6cfa053a606639e5c0b5d5092ecc5
6
+ metadata.gz: a80117bb49c8dcb0525a792adb68c55c76859e4773a3897b7c202a424dcc14e5b928034efd0fc6592098391c9a2a4b66ab034d7b5b84609bfaf59c742fb46441
7
+ data.tar.gz: 22c50b02ac458fe02a3a45bb8709dff6e3913b7d5727c82932a959c3fca9a4e41eeb808a71d1d5c5fd2b039ce4ca866a29a3d5b0e3fc829dd02b2c055d37a367
data/CHANGES CHANGED
@@ -1,3 +1,16 @@
1
+ 4.0.0.alpha3 (2019-07-08)
2
+ =========================
3
+
4
+ Ruby:
5
+ * All documented driver capabilities supported in respective browser Options class by constructor and accessor
6
+ * driver constructor :options and :desired_capabilities generate the same capabilities for local and remote execution
7
+
8
+ Chrome:
9
+ * Add support for browser logging with latest versions of chromedriver
10
+
11
+ Edge:
12
+ * Add support for Chromium based implementation
13
+
1
14
  4.0.0.alpha2 (2019-05-02)
2
15
  =========================
3
16
 
@@ -34,6 +47,31 @@ Firefox:
34
47
  result in NoMethodError. Now it will find a profile with such name on your
35
48
  system and use it accordingly (issue #7119)
36
49
 
50
+ 3.142.3 (2019-05-21)
51
+ ====================
52
+
53
+ Firefox:
54
+ * Fixed a regression when Firefox binary path was not sent to GeckoDriver
55
+ by default and browser could not be located (issue #7219)
56
+
57
+ 3.142.2 (2019-05-11)
58
+ ====================
59
+
60
+ Chrome:
61
+ * Fixed an issue when getting/setting network conditions and sending CDP
62
+ commands didn't work with Grid (issue #7174)
63
+
64
+ Safari:
65
+ * Fixed an issue when getting/setting permissions and attaching debugger
66
+ didn't work with Grid (issue #7174)
67
+
68
+ 3.142.1 (2019-05-07)
69
+ ====================
70
+
71
+ Firefox:
72
+ * Fixed an issue when processing error in legacy driver would result
73
+ in NoMethodError (issue #7178)
74
+
37
75
  3.142.0 (2019-04-24)
38
76
  ====================
39
77
 
@@ -85,7 +85,7 @@ module Selenium
85
85
  segment_count += 1
86
86
 
87
87
  if (segment_count % 15).zero?
88
- percent = (progress.to_f / total.to_f) * 100
88
+ percent = progress.fdiv(total) * 100
89
89
  print "#{CL_RESET}Downloading #{download_file_name}: #{percent.to_i}% (#{progress} / #{total})"
90
90
  segment_count = 0
91
91
  end
@@ -179,7 +179,7 @@ module Selenium
179
179
  @timeout = opts.fetch(:timeout, 30)
180
180
  @background = opts.fetch(:background, false)
181
181
  @log = opts[:log]
182
-
182
+ @log_file = nil
183
183
  @additional_args = []
184
184
  end
185
185
 
@@ -35,13 +35,15 @@ module Selenium
35
35
  Rectangle = Struct.new(:x, :y, :width, :height)
36
36
  Location = Struct.new(:latitude, :longitude, :altitude)
37
37
 
38
- autoload :Chrome, 'selenium/webdriver/chrome'
39
- autoload :Edge, 'selenium/webdriver/edge'
40
- autoload :Firefox, 'selenium/webdriver/firefox'
41
- autoload :IE, 'selenium/webdriver/ie'
42
- autoload :Remote, 'selenium/webdriver/remote'
43
- autoload :Safari, 'selenium/webdriver/safari'
44
- autoload :Support, 'selenium/webdriver/support'
38
+ autoload :Chrome, 'selenium/webdriver/chrome'
39
+ autoload :Edge, 'selenium/webdriver/edge'
40
+ autoload :EdgeHtml, 'selenium/webdriver/edge'
41
+ autoload :EdgeChrome, 'selenium/webdriver/edge'
42
+ autoload :Firefox, 'selenium/webdriver/firefox'
43
+ autoload :IE, 'selenium/webdriver/ie'
44
+ autoload :Remote, 'selenium/webdriver/remote'
45
+ autoload :Safari, 'selenium/webdriver/safari'
46
+ autoload :Support, 'selenium/webdriver/support'
45
47
 
46
48
  # @api private
47
49
 
@@ -19,14 +19,15 @@
19
19
 
20
20
  require 'net/http'
21
21
 
22
- require 'selenium/webdriver/chrome/bridge'
23
- require 'selenium/webdriver/chrome/driver'
24
- require 'selenium/webdriver/chrome/profile'
25
- require 'selenium/webdriver/chrome/options'
26
-
27
22
  module Selenium
28
23
  module WebDriver
29
24
  module Chrome
25
+ autoload :Bridge, 'selenium/webdriver/chrome/bridge'
26
+ autoload :Driver, 'selenium/webdriver/chrome/driver'
27
+ autoload :Profile, 'selenium/webdriver/chrome/profile'
28
+ autoload :Options, 'selenium/webdriver/chrome/options'
29
+ autoload :Service, 'selenium/webdriver/chrome/service'
30
+
30
31
  def self.driver_path=(path)
31
32
  WebDriver.logger.deprecate 'Selenium::WebDriver::Chrome#driver_path=',
32
33
  'Selenium::WebDriver::Chrome::Service#driver_path='
@@ -50,5 +51,3 @@ module Selenium
50
51
  end # Chrome
51
52
  end # WebDriver
52
53
  end # Selenium
53
-
54
- require 'selenium/webdriver/chrome/service'
@@ -23,9 +23,11 @@ module Selenium
23
23
  module Bridge
24
24
 
25
25
  COMMANDS = {
26
- get_network_conditions: [:get, '/session/:session_id/chromium/network_conditions'],
27
- set_network_conditions: [:post, '/session/:session_id/chromium/network_conditions'],
28
- send_command: [:post, '/session/:session_id/goog/cdp/execute']
26
+ get_network_conditions: [:get, 'session/:session_id/chromium/network_conditions'],
27
+ set_network_conditions: [:post, 'session/:session_id/chromium/network_conditions'],
28
+ send_command: [:post, 'session/:session_id/goog/cdp/execute'],
29
+ get_available_log_types: [:get, 'session/:session_id/se/log/types'],
30
+ get_log: [:post, 'session/:session_id/se/log']
29
31
  }.freeze
30
32
 
31
33
  def commands(command)
@@ -44,6 +46,22 @@ module Selenium
44
46
  execute :set_network_conditions, {}, {network_conditions: conditions}
45
47
  end
46
48
 
49
+ def available_log_types
50
+ types = execute :get_available_log_types
51
+ Array(types).map(&:to_sym)
52
+ end
53
+
54
+ def log(type)
55
+ data = execute :get_log, {}, {type: type.to_s}
56
+
57
+ Array(data).map do |l|
58
+ begin
59
+ LogEntry.new l.fetch('level', 'UNKNOWN'), l.fetch('timestamp'), l.fetch('message')
60
+ rescue KeyError
61
+ next
62
+ end
63
+ end
64
+ end
47
65
  end # Bridge
48
66
  end # Chrome
49
67
  end # WebDriver
@@ -34,16 +34,17 @@ module Selenium
34
34
  include DriverExtensions::DownloadsFiles
35
35
 
36
36
  def initialize(opts = {})
37
- opts[:desired_capabilities] = create_capabilities(opts)
37
+ opts[:desired_capabilities] ||= Remote::Capabilities.send(browser)
38
38
 
39
39
  opts[:url] ||= service_url(opts)
40
40
 
41
41
  listener = opts.delete(:listener)
42
42
  desired_capabilities = opts.delete(:desired_capabilities)
43
+ options = opts.delete(:options)
43
44
 
44
45
  @bridge = Remote::Bridge.new(opts)
45
46
  @bridge.extend Bridge
46
- @bridge.create_session(desired_capabilities)
47
+ @bridge.create_session(desired_capabilities, options)
47
48
 
48
49
  super(@bridge, listener: listener)
49
50
  end
@@ -52,48 +53,9 @@ module Selenium
52
53
  :chrome
53
54
  end
54
55
 
55
- def quit
56
- super
57
- ensure
58
- @service&.stop
59
- end
60
-
61
56
  def execute_cdp(cmd, **params)
62
57
  @bridge.send_command(cmd: cmd, params: params)
63
58
  end
64
-
65
- private
66
-
67
- def create_capabilities(opts)
68
- caps = opts.delete(:desired_capabilities) { Remote::Capabilities.chrome }
69
- options = opts.delete(:options) { Options.new }
70
-
71
- profile = opts.delete(:profile)
72
- if profile
73
- profile = profile.as_json
74
-
75
- options.add_argument("--user-data-dir=#{profile[:directory]}") if options.args.none?(&/user-data-dir/.method(:match?))
76
-
77
- if profile[:extensions]
78
- WebDriver.logger.deprecate 'Using Selenium::WebDriver::Chrome::Profile#extensions',
79
- 'Selenium::WebDriver::Chrome::Options#add_extension'
80
- profile[:extensions].each do |extension|
81
- options.add_encoded_extension(extension)
82
- end
83
- end
84
- end
85
-
86
- detach = opts.delete(:detach)
87
- options.add_option(:detach, true) if detach
88
-
89
- options = options.as_json
90
- caps.merge!(options) unless options[Options::KEY].empty?
91
-
92
- caps[:proxy] = opts.delete(:proxy) if opts.key?(:proxy)
93
- caps[:proxy] ||= opts.delete('proxy') if opts.key?('proxy')
94
-
95
- caps
96
- end
97
59
  end # Driver
98
60
  end # Chrome
99
61
  end # WebDriver
@@ -20,19 +20,43 @@
20
20
  module Selenium
21
21
  module WebDriver
22
22
  module Chrome
23
- class Options
24
- attr_reader :args, :prefs, :options, :emulation, :extensions, :encoded_extensions
25
- attr_accessor :binary
23
+ class Options < WebDriver::Options
24
+ attr_accessor :profile
26
25
 
27
26
  KEY = 'goog:chromeOptions'
28
27
 
29
- #
28
+ # see: http://chromedriver.chromium.org/capabilities
29
+ CAPABILITIES = {args: 'args',
30
+ binary: 'binary',
31
+ extensions: 'extensions',
32
+ local_state: 'localState',
33
+ prefs: 'prefs',
34
+ detach: 'detach',
35
+ debugger_address: 'debuggerAddress',
36
+ exclude_switches: 'excludeSwitches',
37
+ minidump_path: 'minidumpPath',
38
+ emulation: 'mobileEmulation',
39
+ perf_logging_prefs: 'perfLoggingPrefs',
40
+ window_types: 'windowTypes'}.freeze
41
+
42
+ CAPABILITIES.each_key do |key|
43
+ define_method key do
44
+ @options[key]
45
+ end
46
+
47
+ define_method "#{key}=" do |value|
48
+ @options[key] = value
49
+ end
50
+ end
51
+
30
52
  # Create a new Options instance.
31
53
  #
32
54
  # @example
33
55
  # options = Selenium::WebDriver::Chrome::Options.new(args: ['start-maximized', 'user-data-dir=/tmp/temp_profile'])
34
56
  # driver = Selenium::WebDriver.for(:chrome, options: options)
35
57
  #
58
+ # @param [Profile] :profile An instance of a Chrome::Profile Class
59
+ # @param [Array] :encoded_extensions List of extensions that do not need to be Base64 encoded
36
60
  # @param [Hash] opts the pre-defined options to create the Chrome::Options with
37
61
  # @option opts [Array<String>] :args List of command-line arguments to use when starting Chrome
38
62
  # @option opts [String] :binary Path to the Chrome executable to use
@@ -40,16 +64,21 @@ module Selenium
40
64
  # @option opts [Array<String>] :extensions A list of paths to (.crx) Chrome extensions to install on startup
41
65
  # @option opts [Hash] :options A hash for raw options
42
66
  # @option opts [Hash] :emulation A hash for raw emulation options
67
+ # @option opts [Hash] :local_state A hash for the Local State file in the user data folder
68
+ # @option opts [Boolean] :detach whether browser is closed when the driver is sent the quit command
69
+ # @option opts [String] :debugger_address address of a Chrome debugger server to connect to
70
+ # @option opts [Array<String>] :exclude_switches command line switches to exclude
71
+ # @option opts [String] :minidump_path Directory to store Chrome minidumps (linux only)
72
+ # @option opts [Hash] :perf_logging_prefs A hash for performance logging preferences
73
+ # @option opts [Array<String>] :window_types A list of window types to appear in the list of window handles
43
74
  #
44
75
 
45
- def initialize(**opts)
46
- @args = Set.new(opts.delete(:args) || [])
47
- @binary = opts.delete(:binary) || Chrome.path
48
- @prefs = opts.delete(:prefs) || {}
49
- @extensions = opts.delete(:extensions) || []
50
- @options = opts.delete(:options) || {}
51
- @emulation = opts.delete(:emulation) || {}
52
- @encoded_extensions = []
76
+ def initialize(profile: nil, encoded_extensions: nil, **opts)
77
+ super(opts)
78
+
79
+ @profile = profile
80
+ @options[:encoded_extensions] = encoded_extensions if encoded_extensions
81
+ @options[:extensions]&.each(&method(:validate_extension))
53
82
  end
54
83
 
55
84
  #
@@ -63,10 +92,9 @@ module Selenium
63
92
  #
64
93
 
65
94
  def add_extension(path)
66
- raise Error::WebDriverError, "could not find extension at #{path.inspect}" unless File.file?(path)
67
- raise Error::WebDriverError, "file was not an extension #{path.inspect}" unless File.extname(path) == '.crx'
68
-
69
- @extensions << path
95
+ validate_extension(path)
96
+ @options[:extensions] ||= []
97
+ @options[:extensions] << path
70
98
  end
71
99
 
72
100
  #
@@ -80,8 +108,10 @@ module Selenium
80
108
  #
81
109
 
82
110
  def add_encoded_extension(encoded)
83
- @encoded_extensions << encoded
111
+ @options[:encoded_extensions] ||= []
112
+ @options[:encoded_extensions] << encoded
84
113
  end
114
+ alias_method :encoded_extension=, :add_encoded_extension
85
115
 
86
116
  #
87
117
  # Add a command-line argument to use when starting Chrome.
@@ -94,22 +124,8 @@ module Selenium
94
124
  #
95
125
 
96
126
  def add_argument(arg)
97
- @args << arg
98
- end
99
-
100
- #
101
- # Add a new option not yet handled by bindings.
102
- #
103
- # @example Leave Chrome open when chromedriver is killed
104
- # options = Selenium::WebDriver::Chrome::Options.new
105
- # options.add_option(:detach, true)
106
- #
107
- # @param [String, Symbol] name Name of the option
108
- # @param [Boolean, String, Integer] value Value of the option
109
- #
110
-
111
- def add_option(name, value)
112
- @options[name] = value
127
+ @options[:args] ||= []
128
+ @options[:args] << arg
113
129
  end
114
130
 
115
131
  #
@@ -124,7 +140,8 @@ module Selenium
124
140
  #
125
141
 
126
142
  def add_preference(name, value)
127
- prefs[name] = value
143
+ @options[:prefs] ||= {}
144
+ @options[:prefs][name] = value
128
145
  end
129
146
 
130
147
  #
@@ -140,7 +157,9 @@ module Selenium
140
157
  end
141
158
 
142
159
  #
143
- # Add an emulation device name
160
+ # Add emulation device information
161
+ #
162
+ # see: http://chromedriver.chromium.org/mobile-emulation
144
163
  #
145
164
  # @example Start Chrome in mobile emulation mode by device name
146
165
  # options = Selenium::WebDriver::Chrome::Options.new
@@ -150,15 +169,14 @@ module Selenium
150
169
  # options = Selenium::WebDriver::Chrome::Options.new
151
170
  # options.add_emulation(device_metrics: {width: 400, height: 800, pixelRatio: 1, touch: true})
152
171
  #
153
- # @param [String] device_name Name of the device or a hash containing width, height, pixelRatio, touch
154
- # @param [Hash] device_metrics Hash containing width, height, pixelRatio, touch
155
- # @param [String] user_agent Full user agent
172
+ # @param [Hash] opts the pre-defined options for adding mobilie emulation values
173
+ # @option opts [String] :device_name A valid device name from the Chrome DevTools Emulation panel
174
+ # @option opts [Hash] :device_metrics Hash containing width, height, pixelRatio, touch
175
+ # @option opts [String] :user_agent Full user agent
156
176
  #
157
177
 
158
- def add_emulation(device_name: nil, device_metrics: nil, user_agent: nil)
159
- @emulation[:deviceName] = device_name if device_name
160
- @emulation[:deviceMetrics] = device_metrics if device_metrics
161
- @emulation[:userAgent] = user_agent if user_agent
178
+ def add_emulation(**opts)
179
+ @options[:emulation] = opts
162
180
  end
163
181
 
164
182
  #
@@ -166,19 +184,36 @@ module Selenium
166
184
  #
167
185
 
168
186
  def as_json(*)
169
- extensions = @extensions.map do |crx_path|
170
- File.open(crx_path, 'rb') { |crx_file| Base64.strict_encode64 crx_file.read }
187
+ options = super
188
+
189
+ if @profile
190
+ options['args'] ||= []
191
+ options['args'] << "--user-data-dir=#{@profile[:directory]}"
171
192
  end
172
- extensions.concat(@encoded_extensions)
173
193
 
174
- opts = @options
175
- opts[:binary] = @binary if @binary
176
- opts[:args] = @args.to_a if @args.any?
177
- opts[:extensions] = extensions if extensions.any?
178
- opts[:mobileEmulation] = @emulation unless @emulation.empty?
179
- opts[:prefs] = @prefs unless @prefs.empty?
194
+ options['binary'] ||= binary_path if binary_path
195
+ extensions = options['extensions'] || []
196
+ encoded_extensions = options.delete(:encoded_extensions) || []
197
+
198
+ options['extensions'] = extensions.map(&method(:encode_extension)) + encoded_extensions
199
+ options.delete('extensions') if options['extensions'].empty?
200
+
201
+ {KEY => generate_as_json(options)}
202
+ end
180
203
 
181
- {KEY => opts}
204
+ private
205
+
206
+ def binary_path
207
+ Chrome.path
208
+ end
209
+
210
+ def encode_extension(path)
211
+ File.open(path, 'rb') { |crx_file| Base64.strict_encode64 crx_file.read }
212
+ end
213
+
214
+ def validate_extension(path)
215
+ raise Error::WebDriverError, "could not find extension at #{path.inspect}" unless File.file?(path)
216
+ raise Error::WebDriverError, "file was not an extension #{path.inspect}" unless File.extname(path) == '.crx'
182
217
  end
183
218
  end # Options
184
219
  end # Chrome