From 4b6de168e47107480cfa76f1dd37bcca05efd38b Mon Sep 17 00:00:00 2001 From: Titus Fortner Date: Mon, 17 Jun 2019 16:54:55 +0200 Subject: [PATCH] [rb] move common browser option methods into superclass --- rb/lib/selenium/webdriver/chrome/options.rb | 79 ++++++------------- rb/lib/selenium/webdriver/common/options.rb | 41 ++++++++++ .../selenium/webdriver/edge_html/options.rb | 11 +-- rb/lib/selenium/webdriver/firefox/options.rb | 54 +++++-------- rb/lib/selenium/webdriver/ie/options.rb | 36 ++------- rb/lib/selenium/webdriver/safari/options.rb | 11 +-- .../selenium/webdriver/chrome/options_spec.rb | 7 +- 7 files changed, 100 insertions(+), 139 deletions(-) diff --git a/rb/lib/selenium/webdriver/chrome/options.rb b/rb/lib/selenium/webdriver/chrome/options.rb index cafb3d6e6662e..c558d961541fd 100755 --- a/rb/lib/selenium/webdriver/chrome/options.rb +++ b/rb/lib/selenium/webdriver/chrome/options.rb @@ -25,10 +25,20 @@ class Options < WebDriver::Common::Options KEY = 'goog:chromeOptions' # see: http://chromedriver.chromium.org/capabilities - CAPABILITIES = %i[args binary extensions local_state prefs detach debugger_address exclude_switches - minidump_path mobile_emulation perf_logging_prefs window_types].freeze - - (CAPABILITIES + %i[options emulation encoded_extensions]).each do |key| + CAPABILITIES = {args: 'args', + binary: 'binary', + extensions: 'extensions', + local_state: 'localState', + prefs: 'prefs', + detach: 'detach', + debugger_address: 'debuggerAddress', + exclude_switches: 'excludeSwitches', + minidump_path: 'minidumpPath', + emulation: 'mobileEmulation', + perf_logging_prefs: 'perfLoggingPrefs', + window_types: 'windowTypes'}.freeze + + CAPABILITIES.each_key do |key| define_method key do @options[key] end @@ -60,22 +70,13 @@ class Options < WebDriver::Common::Options # @option opts [Array] :window_types A list of window types to appear in the list of window handles # - def initialize(emulation: nil, encoded_extensions: nil, options: nil, **opts) - @options = if options - WebDriver.logger.deprecate(":options as keyword for initializing #{self.class}", - "values directly in #new constructor") - opts.merge(options) - else - opts - end - @options[:mobile_emulation] ||= emulation if emulation + def initialize(encoded_extensions: nil, **opts) + super(opts) + @options[:encoded_extensions] = encoded_extensions if encoded_extensions @options[:extensions]&.each(&method(:validate_extension)) end - alias_method :emulation, :mobile_emulation - alias_method :emulation=, :mobile_emulation= - # # Add an extension by local path. # @@ -106,6 +107,7 @@ def add_encoded_extension(encoded) @options[:encoded_extensions] ||= [] @options[:encoded_extensions] << encoded end + alias_method :encoded_extension=, :add_encoded_extension # # Add a command-line argument to use when starting Chrome. @@ -122,21 +124,6 @@ def add_argument(arg) @options[:args] << arg end - # - # Add a new option not yet handled by bindings. - # - # @example Leave Chrome open when chromedriver is killed - # options = Selenium::WebDriver::Chrome::Options.new - # options.add_option(:detach, true) - # - # @param [String, Symbol] name Name of the option - # @param [Boolean, String, Integer] value Value of the option - # - - def add_option(name, value) - @options[name] = value - end - # # Add a preference that is only applied to the user profile in use. # @@ -182,7 +169,7 @@ def headless! # def add_emulation(**opt) - @options[:mobile_emulation] = opt + @options[:emulation] = opt end # @@ -190,34 +177,20 @@ def add_emulation(**opt) # def as_json(*) - options = @options.dup + options = super - opts = CAPABILITIES.each_with_object({}) do |capability_name, hash| - capability_value = options.delete(capability_name) - hash[capability_name] = capability_value unless capability_value.nil? - end + options['binary'] ||= Chrome.path if Chrome.path + extensions = options['extensions'] || [] + encoded_extensions = options.delete(:encoded_extensions) || [] - opts[:binary] ||= Chrome.path if Chrome.path - extensions = opts[:extensions] || [] - opts[:extensions] = extensions.map(&method(:encode_extension)) + - (options.delete(:encoded_extensions) || []) - opts.delete(:extensions) if opts[:extensions].empty? - opts[:mobile_emulation] = process_emulation(opts[:mobile_emulation] || options.delete(:emulation) || {}) - opts.delete(:mobile_emulation) if opts[:mobile_emulation].empty? + options['extensions'] = extensions.map(&method(:encode_extension)) + encoded_extensions + options.delete('extensions') if options['extensions'].empty? - {KEY => generate_as_json(opts.merge(options))} + {KEY => generate_as_json(options)} end private - def process_emulation(device_name: nil, device_metrics: nil, user_agent: nil) - emulation = {} - emulation[:device_name] = device_name if device_name - emulation[:device_metrics] = device_metrics if device_metrics - emulation[:user_agent] = user_agent if user_agent - emulation - end - def encode_extension(path) File.open(path, 'rb') { |crx_file| Base64.strict_encode64 crx_file.read } end diff --git a/rb/lib/selenium/webdriver/common/options.rb b/rb/lib/selenium/webdriver/common/options.rb index c384c07cfa99d..50462242bd78c 100644 --- a/rb/lib/selenium/webdriver/common/options.rb +++ b/rb/lib/selenium/webdriver/common/options.rb @@ -21,6 +21,47 @@ module Selenium module WebDriver module Common class Options + attr_accessor :options + + def initialize(options: nil, **opts) + @options = if options + WebDriver.logger.deprecate(":options as keyword for initializing #{self.class}", + "custom values directly in #new constructor") + opts.merge(options) + else + opts + end + end + + # + # Add a new option not yet handled by bindings. + # + # @example Leave Chrome open when chromedriver is killed + # options = Selenium::WebDriver::Chrome::Options.new + # options.add_option(:detach, true) + # + # @param [String, Symbol] name Name of the option + # @param [Boolean, String, Integer] value Value of the option + # + + def add_option(name, value) + @options[name] = value + end + + # + # @api private + # + + def as_json(*) + options = @options.dup + + opts = self.class::CAPABILITIES.each_with_object({}) do |(capability_alias, capability_name), hash| + capability_value = options.delete(capability_alias) + hash[capability_name] = capability_value unless capability_value.nil? + end + opts.merge(options) + end + private def generate_as_json(value) diff --git a/rb/lib/selenium/webdriver/edge_html/options.rb b/rb/lib/selenium/webdriver/edge_html/options.rb index 335c2db81aced..97e346aed1d33 100644 --- a/rb/lib/selenium/webdriver/edge_html/options.rb +++ b/rb/lib/selenium/webdriver/edge_html/options.rb @@ -52,7 +52,7 @@ class Options < WebDriver::Common::Options # def initialize(**opts) - @options = opts + super @options[:extensions]&.each(&method(:validate_extension)) end @@ -77,14 +77,7 @@ def add_extension_path(path) # def as_json(*) - options = @options.dup - - opts = CAPABILITIES.each_with_object({}) do |(capability_alias, capability_name), hash| - capability_value = options.delete(capability_alias) - hash[capability_name] = capability_value unless capability_value.nil? - end - - generate_as_json(opts.merge(options)) + generate_as_json(super) end private diff --git a/rb/lib/selenium/webdriver/firefox/options.rb b/rb/lib/selenium/webdriver/firefox/options.rb index 02dfb141a43cd..3194209880df4 100644 --- a/rb/lib/selenium/webdriver/firefox/options.rb +++ b/rb/lib/selenium/webdriver/firefox/options.rb @@ -24,9 +24,13 @@ class Options < WebDriver::Common::Options KEY = 'moz:firefoxOptions' # see: https://firefox-source-docs.mozilla.org/testing/geckodriver/Capabilities.html - CAPABILITIES = %i[binary args profile log prefs].freeze + CAPABILITIES = {binary: 'binary', + args: 'args', + profile: 'profile', + log: 'log', + prefs: 'prefs'}.freeze - (CAPABILITIES + %i[log_level]).each do |key| + CAPABILITIES.each_key do |key| define_method key do @options[key] end @@ -52,14 +56,10 @@ class Options < WebDriver::Common::Options # @option opts [Hash] :options A hash for raw options # - def initialize(options: nil, **opts) - @options = if options - WebDriver.logger.deprecate(":options as keyword for initializing #{self.class}", - "values directly in #new constructor") - opts.merge(options) - else - opts - end + def initialize(log_level: nil, **opts) + super(opts) + + @options[:log] ||= {level: log_level} if log_level process_profile(@options[:profile]) if @options.key?(:profile) end @@ -78,21 +78,6 @@ def add_argument(arg) @options[:args] << arg end - # - # Add a new option not yet handled by these bindings. - # - # @example - # options = Selenium::WebDriver::Firefox::Options.new - # options.add_option(:foo, 'bar') - # - # @param [String, Symbol] name Name of the option - # @param [Boolean, String, Integer] value Value of the option - # - - def add_option(name, value) - @options[name] = value - end - # # Add a preference that is only applied to the user profile in use. # @@ -140,21 +125,20 @@ def profile=(profile) process_profile(profile) end + def log_level + @options.dig(:log, :level) + end + + def log_level=(level) + @options[:log] = {level: level} + end + # # @api private # def as_json(*) - options = @options.dup - - opts = CAPABILITIES.each_with_object({}) do |capability_name, hash| - capability_value = options.delete(capability_name) - hash[capability_name] = capability_value unless capability_value.nil? - end - - opts[:log] ||= {level: options.delete(:log_level)} if options.key?(:log_level) - - {KEY => generate_as_json(opts.merge(options))} + {KEY => generate_as_json(super)} end private diff --git a/rb/lib/selenium/webdriver/ie/options.rb b/rb/lib/selenium/webdriver/ie/options.rb index 7b292fa3be0a1..df8e658aa3f06 100644 --- a/rb/lib/selenium/webdriver/ie/options.rb +++ b/rb/lib/selenium/webdriver/ie/options.rb @@ -52,7 +52,7 @@ class Options < WebDriver::Common::Options end end - attr_reader :args, :options + attr_reader :args # # Create a new Options instance @@ -85,9 +85,10 @@ class Options < WebDriver::Common::Options # @option opts [Boolean] validate_cookie_document_type # - def initialize(**opts) - @args = Set.new(opts.delete(:args) || []) - @options = opts + def initialize(args: nil, **opts) + super(opts) + + @args = (args || []).to_set @options[:native_events] = true if @options[:native_events].nil? end @@ -101,36 +102,15 @@ def add_argument(arg) @args << arg end - # - # Add a new option not yet handled by these bindings. - # - # @example - # options = Selenium::WebDriver::IE::Options.new - # options.add_option(:foo, 'bar') - # - # @param [String, Symbol] name Name of the option - # @param [Boolean, String, Integer] value Value of the option - # - - def add_option(name, value) - @options[name] = value - end - # # @api private # def as_json(*) - opts = {} - options = @options.dup - - CAPABILITIES.each do |capability_alias, capability_name| - capability_value = options.delete(capability_alias) - opts[capability_name] = capability_value unless capability_value.nil? - end - opts['ie.browserCommandLineSwitches'] = @args.to_a.join(' ') if @args.any? + options = super + options['ie.browserCommandLineSwitches'] = @args.to_a.join(' ') if @args.any? - {KEY => generate_as_json(opts.merge(options))} + {KEY => generate_as_json(options)} end end # Options end # IE diff --git a/rb/lib/selenium/webdriver/safari/options.rb b/rb/lib/selenium/webdriver/safari/options.rb index 629648b7ebbce..611a4543f8e9b 100644 --- a/rb/lib/selenium/webdriver/safari/options.rb +++ b/rb/lib/selenium/webdriver/safari/options.rb @@ -50,7 +50,7 @@ class Options < WebDriver::Common::Options # def initialize(**opts) - @options = opts + super end # @@ -58,14 +58,7 @@ def initialize(**opts) # def as_json(*) - options = @options.dup - - opts = CAPABILITIES.each_with_object({}) do |(capability_alias, capability_name), hash| - capability_value = options.delete(capability_alias) - hash[capability_name] = capability_value unless capability_value.nil? - end - - generate_as_json(opts.merge(options)) + generate_as_json(super) end end # Options end # Safari diff --git a/rb/spec/unit/selenium/webdriver/chrome/options_spec.rb b/rb/spec/unit/selenium/webdriver/chrome/options_spec.rb index 921c780526a73..4c39e58a89cfa 100644 --- a/rb/spec/unit/selenium/webdriver/chrome/options_spec.rb +++ b/rb/spec/unit/selenium/webdriver/chrome/options_spec.rb @@ -28,8 +28,6 @@ module Chrome describe '#initialize' do it 'accepts defined parameters' do allow(File).to receive(:file?).and_return(true) - # allow_any_instance_of(Options).to receive(:encode_file).with('foo.crx').and_return("encoded_foo") - # allow_any_instance_of(Options).to receive(:encode_file).with('bar.crx').and_return("encoded_bar") opt = Options.new(args: %w[foo bar], prefs: {foo: 'bar'}, @@ -50,9 +48,8 @@ module Chrome expect(opt.prefs[:foo]).to eq('bar') expect(opt.binary).to eq('/foo/bar') expect(opt.extensions).to eq(['foo.crx', 'bar.crx']) - expect(opt.encoded_extensions).to eq(%w[encoded_foobar]) expect(opt.instance_variable_get('@options')[:foo]).to eq('bar') - expect(opt.mobile_emulation[:device_name]).to eq(:bar) + expect(opt.emulation[:device_name]).to eq(:bar) expect(opt.local_state[:foo]).to eq('bar') expect(opt.detach).to eq(true) expect(opt.debugger_address).to eq('127.0.0.1:8181') @@ -89,7 +86,7 @@ module Chrome describe '#add_encoded_extension' do it 'adds an encoded extension' do options.add_encoded_extension('foo') - expect(options.encoded_extensions).to include('foo') + expect(options.instance_variable_get('@options')[:encoded_extensions]).to include('foo') end end