Path: blob/trunk/rb/lib/selenium/webdriver/common/options.rb
1865 views
# frozen_string_literal: true12# Licensed to the Software Freedom Conservancy (SFC) under one3# or more contributor license agreements. See the NOTICE file4# distributed with this work for additional information5# regarding copyright ownership. The SFC licenses this file6# to you under the Apache License, Version 2.0 (the7# "License"); you may not use this file except in compliance8# with the License. You may obtain a copy of the License at9#10# http://www.apache.org/licenses/LICENSE-2.011#12# Unless required by applicable law or agreed to in writing,13# software distributed under the License is distributed on an14# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY15# KIND, either express or implied. See the License for the16# specific language governing permissions and limitations17# under the License.1819module Selenium20module WebDriver21class Options22W3C_OPTIONS = %i[browser_name browser_version platform_name accept_insecure_certs page_load_strategy proxy23set_window_rect timeouts unhandled_prompt_behavior strict_file_interactability24web_socket_url].freeze2526GRID_OPTIONS = %i[enable_downloads].freeze2728class << self29attr_reader :driver_path3031def chrome(**)32Chrome::Options.new(**)33end3435def firefox(**)36Firefox::Options.new(**)37end3839def ie(**)40IE::Options.new(**)41end42alias internet_explorer ie4344def edge(**)45Edge::Options.new(**)46end47alias microsoftedge edge4849def safari(**)50Safari::Options.new(**)51end5253def set_capabilities54(W3C_OPTIONS + GRID_OPTIONS + self::CAPABILITIES.keys).each do |key|55next if method_defined? key5657define_method key do58@options[key]59end6061define_method :"#{key}=" do |value|62@options[key] = value63end64end65end66end6768attr_accessor :options6970def initialize(**opts)71self.class.set_capabilities7273@options = opts74@options[:browser_name] = self.class::BROWSER75end7677#78# Add a new option not yet handled by bindings.79#80# @example Leave Chrome open when chromedriver is killed81# options = Selenium::WebDriver::Chrome::Options.new82# options.add_option(:detach, true)83#84# @param [String, Symbol] name Name of the option85# @param [Boolean, String, Integer] value Value of the option86#8788def add_option(name, value = nil)89name, value = name.first if value.nil? && name.is_a?(Hash)90@options[name] = value91end9293def ==(other)94return false unless other.is_a? self.class9596as_json == other.as_json97end9899alias eql? ==100101#102# @api private103#104105def as_json(*)106options = @options.dup107108downloads = options.delete(:enable_downloads)109options['se:downloadsEnabled'] = downloads unless downloads.nil?110w3c_options = process_w3c_options(options)111112browser_options = self.class::CAPABILITIES.each_with_object({}) do |(capability_alias, capability_name), hash|113capability_value = options.delete(capability_alias)114hash[capability_name] = capability_value unless capability_value.nil?115end116117raise Error::WebDriverError, "These options are not w3c compliant: #{options}" unless options.empty?118119browser_options = {self.class::KEY => browser_options} if defined?(self.class::KEY)120121process_browser_options(browser_options)122generate_as_json(w3c_options.merge(browser_options))123end124125private126127def w3c?(key)128W3C_OPTIONS.include?(key) || key.to_s.include?(':')129end130131def process_w3c_options(options)132w3c_options = options.select { |key, val| w3c?(key) && !val.nil? }133w3c_options[:unhandled_prompt_behavior] &&= w3c_options[:unhandled_prompt_behavior]&.to_s&.tr('_', ' ')134options.delete_if { |key, _val| w3c?(key) }135w3c_options136end137138def process_browser_options(_browser_options)139nil140end141142def camelize?(_key)143true144end145146def generate_as_json(value, camelize_keys: true)147if value.is_a?(Hash)148process_json_hash(value, camelize_keys)149elsif value.respond_to?(:as_json)150value.as_json151elsif value.is_a?(Array)152value.map { |val| generate_as_json(val, camelize_keys: camelize_keys) }153elsif value.is_a?(Symbol)154value.to_s155else156value157end158end159160def process_json_hash(value, camelize_keys)161value.each_with_object({}) do |(key, val), hash|162next if val.respond_to?(:empty?) && val.empty?163164camelize = camelize_keys ? camelize?(key) : false165key = convert_json_key(key, camelize: camelize)166hash[key] = generate_as_json(val, camelize_keys: camelize)167end168end169170def convert_json_key(key, camelize: true)171key = key.to_s if key.is_a?(Symbol)172key = camel_case(key) if camelize173return key if key.is_a?(String)174175raise TypeError, "expected String or Symbol, got #{key.inspect}:#{key.class}"176end177178def camel_case(str)179str.gsub(/_([a-z])/) { Regexp.last_match(1)&.upcase }180end181end # Options182end # WebDriver183end # Selenium184185186