Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
SeleniumHQ
GitHub Repository: SeleniumHQ/Selenium
Path: blob/trunk/rb/lib/selenium/webdriver/common/options.rb
4010 views
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
module Selenium
21
module WebDriver
22
class Options
23
W3C_OPTIONS = %i[browser_name browser_version platform_name accept_insecure_certs page_load_strategy proxy
24
set_window_rect timeouts unhandled_prompt_behavior strict_file_interactability
25
web_socket_url].freeze
26
27
GRID_OPTIONS = %i[enable_downloads].freeze
28
29
class << self
30
attr_reader :driver_path
31
32
def chrome(**)
33
Chrome::Options.new(**)
34
end
35
36
def firefox(**)
37
Firefox::Options.new(**)
38
end
39
40
def ie(**)
41
IE::Options.new(**)
42
end
43
alias internet_explorer ie
44
45
def edge(**)
46
Edge::Options.new(**)
47
end
48
alias microsoftedge edge
49
50
def safari(**)
51
Safari::Options.new(**)
52
end
53
54
def set_capabilities
55
(W3C_OPTIONS + GRID_OPTIONS + self::CAPABILITIES.keys).each do |key|
56
next if method_defined? key
57
58
define_method key do
59
@options[key]
60
end
61
62
define_method :"#{key}=" do |value|
63
@options[key] = value
64
end
65
end
66
end
67
end
68
69
attr_accessor :options
70
71
def initialize(**opts)
72
self.class.set_capabilities
73
74
opts[:web_socket_url] = opts.delete(:bidi) if opts.key?(:bidi)
75
76
@options = opts
77
@options[:browser_name] = self.class::BROWSER
78
end
79
80
#
81
# Add a new option not yet handled by bindings.
82
#
83
# @example Leave Chrome open when chromedriver is killed
84
# options = Selenium::WebDriver::Chrome::Options.new
85
# options.add_option(:detach, true)
86
#
87
# @param [String, Symbol] name Name of the option
88
# @param [Boolean, String, Integer] value Value of the option
89
#
90
91
def add_option(name, value = nil)
92
name, value = name.first if value.nil? && name.is_a?(Hash)
93
@options[name] = value
94
end
95
96
def enable_bidi!
97
@options[:web_socket_url] = true
98
end
99
100
def bidi?
101
!!@options[:web_socket_url]
102
end
103
104
def ==(other)
105
return false unless other.is_a? self.class
106
107
as_json == other.as_json
108
end
109
110
alias eql? ==
111
112
#
113
# @api private
114
#
115
116
def as_json(*)
117
options = @options.dup
118
119
downloads = options.delete(:enable_downloads)
120
options['se:downloadsEnabled'] = downloads unless downloads.nil?
121
w3c_options = process_w3c_options(options)
122
123
browser_options = self.class::CAPABILITIES.each_with_object({}) do |(capability_alias, capability_name), hash|
124
capability_value = options.delete(capability_alias)
125
hash[capability_name] = capability_value unless capability_value.nil?
126
end
127
128
raise Error::WebDriverError, "These options are not w3c compliant: #{options}" unless options.empty?
129
130
browser_options = {self.class::KEY => browser_options} if defined?(self.class::KEY)
131
132
process_browser_options(browser_options)
133
generate_as_json(w3c_options.merge(browser_options))
134
end
135
136
private
137
138
def w3c?(key)
139
W3C_OPTIONS.include?(key) || key.to_s.include?(':')
140
end
141
142
def process_w3c_options(options)
143
w3c_options = options.select { |key, val| w3c?(key) && !val.nil? }
144
w3c_options[:unhandled_prompt_behavior] &&=
145
process_unhandled_prompt_behavior_value(w3c_options[:unhandled_prompt_behavior])
146
options.delete_if { |key, _val| w3c?(key) }
147
w3c_options
148
end
149
150
def process_unhandled_prompt_behavior_value(value)
151
if value.is_a?(Hash)
152
value.transform_values { |v| process_unhandled_prompt_behavior_value(v) }
153
else
154
value&.to_s&.tr('_', ' ')
155
end
156
end
157
158
def process_browser_options(_browser_options)
159
nil
160
end
161
162
def camelize?(_key)
163
true
164
end
165
166
def generate_as_json(value, camelize_keys: true)
167
if value.is_a?(Hash)
168
process_json_hash(value, camelize_keys)
169
elsif value.respond_to?(:as_json)
170
value.as_json
171
elsif value.is_a?(Array)
172
value.map { |val| generate_as_json(val, camelize_keys: camelize_keys) }
173
elsif value.is_a?(Symbol)
174
value.to_s
175
else
176
value
177
end
178
end
179
180
def process_json_hash(value, camelize_keys)
181
value.each_with_object({}) do |(key, val), hash|
182
next if val.respond_to?(:empty?) && val.empty?
183
184
camelize = camelize_keys ? camelize?(key) : false
185
key = convert_json_key(key, camelize: camelize)
186
hash[key] = generate_as_json(val, camelize_keys: camelize)
187
end
188
end
189
190
def convert_json_key(key, camelize: true)
191
key = key.to_s if key.is_a?(Symbol)
192
key = camel_case(key) if camelize
193
return key if key.is_a?(String)
194
195
raise TypeError, "expected String or Symbol, got #{key.inspect}:#{key.class}"
196
end
197
198
def camel_case(str)
199
str.gsub(/_([a-z])/) { Regexp.last_match(1)&.upcase }
200
end
201
end # Options
202
end # WebDriver
203
end # Selenium
204
205