selenium-webdriver 3.142.7 → 4.3.0
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.
- checksums.yaml +5 -5
- data/CHANGES +432 -5
- data/Gemfile +3 -1
- data/LICENSE +1 -1
- data/NOTICE +2 -0
- data/README.md +4 -5
- data/lib/selenium/server.rb +75 -64
- data/lib/selenium/webdriver/atoms/findElements.js +122 -0
- data/lib/selenium/webdriver/atoms/getAttribute.js +100 -7
- data/lib/selenium/webdriver/atoms/isDisplayed.js +76 -78
- data/lib/selenium/webdriver/atoms/mutationListener.js +55 -0
- data/lib/selenium/webdriver/bidi/session.rb +38 -0
- data/lib/selenium/webdriver/bidi.rb +55 -0
- data/lib/selenium/webdriver/chrome/driver.rb +26 -83
- data/lib/selenium/webdriver/chrome/{bridge.rb → features.rb} +55 -12
- data/lib/selenium/webdriver/chrome/options.rb +138 -67
- data/lib/selenium/webdriver/chrome/profile.rb +6 -3
- data/lib/selenium/webdriver/chrome/service.rb +8 -15
- data/lib/selenium/webdriver/chrome.rb +5 -18
- data/lib/selenium/webdriver/common/action_builder.rb +171 -236
- data/lib/selenium/webdriver/common/driver.rb +76 -29
- data/lib/selenium/webdriver/common/driver_extensions/full_page_screenshot.rb +43 -0
- data/lib/selenium/webdriver/common/driver_extensions/has_apple_permissions.rb +51 -0
- data/lib/selenium/webdriver/common/driver_extensions/has_authentication.rb +89 -0
- data/lib/selenium/webdriver/common/driver_extensions/{has_touch_screen.rb → has_bidi.rb} +10 -8
- data/lib/selenium/webdriver/common/driver_extensions/has_casting.rb +87 -0
- data/lib/selenium/webdriver/common/driver_extensions/has_cdp.rb +38 -0
- data/lib/selenium/webdriver/common/driver_extensions/has_context.rb +44 -0
- data/lib/selenium/webdriver/common/driver_extensions/has_devtools.rb +43 -0
- data/lib/selenium/webdriver/common/driver_extensions/has_launching.rb +38 -0
- data/lib/selenium/webdriver/common/driver_extensions/has_location.rb +5 -8
- data/lib/selenium/webdriver/common/driver_extensions/has_log_events.rb +144 -0
- data/lib/selenium/webdriver/common/driver_extensions/{has_remote_status.rb → has_logs.rb} +4 -4
- data/lib/selenium/webdriver/common/driver_extensions/has_network_conditions.rb +17 -0
- data/lib/selenium/webdriver/common/driver_extensions/has_network_connection.rb +6 -27
- data/lib/selenium/webdriver/common/driver_extensions/has_network_interception.rb +136 -0
- data/lib/selenium/webdriver/common/driver_extensions/has_permissions.rb +11 -11
- data/lib/selenium/webdriver/common/driver_extensions/has_pinned_scripts.rb +77 -0
- data/lib/selenium/webdriver/common/driver_extensions/{rotatable.rb → prints_page.rb} +18 -20
- data/lib/selenium/webdriver/common/element.rb +83 -23
- data/lib/selenium/webdriver/common/error.rb +32 -196
- data/lib/selenium/webdriver/common/interactions/input_device.rb +10 -4
- data/lib/selenium/webdriver/common/interactions/interaction.rb +12 -22
- data/lib/selenium/webdriver/common/interactions/interactions.rb +24 -4
- data/lib/selenium/webdriver/common/interactions/key_actions.rb +10 -6
- data/lib/selenium/webdriver/common/interactions/key_input.rb +11 -27
- data/lib/selenium/webdriver/common/interactions/none_input.rb +10 -8
- data/lib/selenium/webdriver/common/interactions/pause.rb +49 -0
- data/lib/selenium/webdriver/common/interactions/pointer_actions.rb +68 -78
- data/lib/selenium/webdriver/common/interactions/pointer_cancel.rb +45 -0
- data/lib/selenium/webdriver/common/interactions/pointer_event_properties.rb +63 -0
- data/lib/selenium/webdriver/common/interactions/pointer_input.rb +15 -84
- data/lib/selenium/webdriver/common/interactions/pointer_move.rb +60 -0
- data/lib/selenium/webdriver/common/interactions/pointer_press.rb +85 -0
- data/lib/selenium/webdriver/common/interactions/scroll.rb +57 -0
- data/lib/selenium/webdriver/common/interactions/scroll_origin.rb +48 -0
- data/lib/selenium/webdriver/common/interactions/typing_interaction.rb +54 -0
- data/lib/selenium/webdriver/common/interactions/wheel_actions.rb +113 -0
- data/lib/selenium/webdriver/common/{w3c_manager.rb → interactions/wheel_input.rb} +14 -17
- data/lib/selenium/webdriver/common/keys.rb +1 -0
- data/lib/selenium/webdriver/common/log_entry.rb +2 -2
- data/lib/selenium/webdriver/common/logger.rb +50 -15
- data/lib/selenium/webdriver/common/manager.rb +11 -38
- data/lib/selenium/webdriver/common/options.rb +147 -23
- data/lib/selenium/webdriver/common/platform.rb +10 -5
- data/lib/selenium/webdriver/common/port_prober.rb +4 -6
- data/lib/selenium/webdriver/common/profile_helper.rb +11 -9
- data/lib/selenium/webdriver/common/proxy.rb +6 -3
- data/lib/selenium/webdriver/common/search_context.rb +7 -9
- data/lib/selenium/webdriver/common/service.rb +17 -125
- data/lib/selenium/webdriver/common/service_manager.rb +150 -0
- data/lib/selenium/webdriver/common/shadow_root.rb +87 -0
- data/lib/selenium/webdriver/common/socket_lock.rb +2 -2
- data/lib/selenium/webdriver/common/socket_poller.rb +3 -3
- data/lib/selenium/webdriver/common/takes_screenshot.rb +66 -0
- data/lib/selenium/webdriver/common/target_locator.rb +32 -4
- data/lib/selenium/webdriver/common/timeouts.rb +31 -4
- data/lib/selenium/webdriver/common/wait.rb +1 -1
- data/lib/selenium/webdriver/common/websocket_connection.rb +149 -0
- data/lib/selenium/webdriver/common/window.rb +0 -4
- data/lib/selenium/webdriver/common/zipper.rb +3 -9
- data/lib/selenium/webdriver/common.rb +35 -18
- data/lib/selenium/webdriver/devtools/console_event.rb +38 -0
- data/lib/selenium/webdriver/devtools/exception_event.rb +36 -0
- data/lib/selenium/webdriver/devtools/mutation_event.rb +37 -0
- data/lib/selenium/webdriver/devtools/pinned_script.rb +59 -0
- data/lib/selenium/webdriver/devtools/request.rb +67 -0
- data/lib/selenium/webdriver/devtools/response.rb +66 -0
- data/lib/selenium/webdriver/devtools.rb +86 -0
- data/lib/selenium/webdriver/edge/driver.rb +7 -29
- data/lib/selenium/webdriver/edge/features.rb +45 -0
- data/lib/selenium/webdriver/edge/options.rb +11 -48
- data/lib/selenium/webdriver/edge/profile.rb +33 -0
- data/lib/selenium/webdriver/edge/service.rb +10 -26
- data/lib/selenium/webdriver/edge.rb +11 -14
- data/lib/selenium/webdriver/firefox/driver.rb +32 -19
- data/lib/selenium/webdriver/firefox/extension.rb +8 -0
- data/lib/selenium/webdriver/firefox/features.rb +63 -0
- data/lib/selenium/webdriver/firefox/options.rb +73 -50
- data/lib/selenium/webdriver/firefox/profile.rb +16 -70
- data/lib/selenium/webdriver/firefox/service.rb +5 -9
- data/lib/selenium/webdriver/firefox/util.rb +1 -1
- data/lib/selenium/webdriver/firefox.rb +17 -28
- data/lib/selenium/webdriver/ie/driver.rb +1 -47
- data/lib/selenium/webdriver/ie/options.rb +15 -46
- data/lib/selenium/webdriver/ie/service.rb +13 -15
- data/lib/selenium/webdriver/ie.rb +3 -16
- data/lib/selenium/webdriver/remote/bridge.rb +563 -86
- data/lib/selenium/webdriver/remote/capabilities.rb +159 -123
- data/lib/selenium/webdriver/remote/commands.rb +158 -0
- data/lib/selenium/webdriver/remote/driver.rb +22 -13
- data/lib/selenium/webdriver/remote/http/common.rb +0 -5
- data/lib/selenium/webdriver/remote/http/default.rb +22 -31
- data/lib/selenium/webdriver/remote/response.rb +18 -49
- data/lib/selenium/webdriver/remote.rb +15 -12
- data/lib/selenium/webdriver/safari/driver.rb +3 -31
- data/lib/selenium/webdriver/safari/{bridge.rb → features.rb} +3 -3
- data/lib/selenium/webdriver/safari/options.rb +10 -29
- data/lib/selenium/webdriver/safari/service.rb +4 -8
- data/lib/selenium/webdriver/safari.rb +13 -19
- data/lib/selenium/webdriver/support/block_event_listener.rb +1 -1
- data/lib/selenium/webdriver/support/cdp/domain.rb.erb +63 -0
- data/lib/selenium/webdriver/support/cdp_client_generator.rb +108 -0
- data/lib/selenium/webdriver/support/color.rb +9 -9
- data/lib/selenium/webdriver/support/event_firing_bridge.rb +4 -4
- data/lib/selenium/webdriver/support/guards/guard.rb +89 -0
- data/lib/selenium/webdriver/{firefox/marionette/bridge.rb → support/guards/guard_condition.rb} +22 -19
- data/lib/selenium/webdriver/support/guards.rb +95 -0
- data/lib/selenium/webdriver/support/relative_locator.rb +51 -0
- data/lib/selenium/webdriver/support/select.rb +3 -3
- data/lib/selenium/webdriver/support.rb +1 -0
- data/lib/selenium/webdriver/version.rb +1 -1
- data/lib/selenium/webdriver.rb +14 -13
- data/selenium-webdriver.gemspec +32 -13
- metadata +176 -69
- data/lib/selenium/webdriver/common/bridge_helper.rb +0 -82
- data/lib/selenium/webdriver/common/driver_extensions/takes_screenshot.rb +0 -64
- data/lib/selenium/webdriver/common/keyboard.rb +0 -70
- data/lib/selenium/webdriver/common/mouse.rb +0 -89
- data/lib/selenium/webdriver/common/touch_action_builder.rb +0 -78
- data/lib/selenium/webdriver/common/touch_screen.rb +0 -123
- data/lib/selenium/webdriver/common/w3c_action_builder.rb +0 -212
- data/lib/selenium/webdriver/edge/bridge.rb +0 -76
- data/lib/selenium/webdriver/firefox/binary.rb +0 -187
- data/lib/selenium/webdriver/firefox/extension/prefs.json +0 -69
- data/lib/selenium/webdriver/firefox/extension/webdriver.xpi +0 -0
- data/lib/selenium/webdriver/firefox/launcher.rb +0 -111
- data/lib/selenium/webdriver/firefox/legacy/driver.rb +0 -83
- data/lib/selenium/webdriver/firefox/marionette/driver.rb +0 -90
- data/lib/selenium/webdriver/firefox/native/linux/amd64/x_ignore_nofocus.so +0 -0
- data/lib/selenium/webdriver/firefox/native/linux/x86/x_ignore_nofocus.so +0 -0
- data/lib/selenium/webdriver/remote/http/persistent.rb +0 -60
- data/lib/selenium/webdriver/remote/oss/bridge.rb +0 -594
- data/lib/selenium/webdriver/remote/oss/commands.rb +0 -223
- data/lib/selenium/webdriver/remote/w3c/bridge.rb +0 -605
- data/lib/selenium/webdriver/remote/w3c/capabilities.rb +0 -310
- data/lib/selenium/webdriver/remote/w3c/commands.rb +0 -157
|
@@ -40,13 +40,17 @@ module Selenium
|
|
|
40
40
|
:close,
|
|
41
41
|
:debug, :debug?,
|
|
42
42
|
:info, :info?,
|
|
43
|
-
:warn
|
|
43
|
+
:warn?,
|
|
44
44
|
:error, :error?,
|
|
45
45
|
:fatal, :fatal?,
|
|
46
46
|
:level, :level=
|
|
47
47
|
|
|
48
|
-
|
|
49
|
-
|
|
48
|
+
#
|
|
49
|
+
# @param [String] progname Allow child projects to use Selenium's Logger pattern
|
|
50
|
+
#
|
|
51
|
+
def initialize(progname = 'Selenium')
|
|
52
|
+
@logger = create_logger(progname)
|
|
53
|
+
@ignored = []
|
|
50
54
|
end
|
|
51
55
|
|
|
52
56
|
#
|
|
@@ -73,28 +77,63 @@ module Selenium
|
|
|
73
77
|
@logger.instance_variable_get(:@logdev).dev
|
|
74
78
|
end
|
|
75
79
|
|
|
80
|
+
#
|
|
81
|
+
# Will not log the provided ID.
|
|
82
|
+
#
|
|
83
|
+
# @param [Array, Symbol] id
|
|
84
|
+
#
|
|
85
|
+
def ignore(id)
|
|
86
|
+
Array(id).each { |ignore| @ignored << ignore }
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
#
|
|
90
|
+
# Overrides default #warn to skip ignored messages by provided id
|
|
91
|
+
#
|
|
92
|
+
# @param [String] message
|
|
93
|
+
# @param [Symbol, Array<Sybmol>] id
|
|
94
|
+
# @yield see #deprecate
|
|
95
|
+
#
|
|
96
|
+
def warn(message, id: [])
|
|
97
|
+
id = Array(id)
|
|
98
|
+
return if (@ignored & id).any?
|
|
99
|
+
|
|
100
|
+
msg = id.empty? ? message : "[#{id.map(&:inspect).join(', ')}] #{message} "
|
|
101
|
+
msg += " #{yield}" if block_given?
|
|
102
|
+
|
|
103
|
+
@logger.warn { msg }
|
|
104
|
+
end
|
|
105
|
+
|
|
76
106
|
#
|
|
77
107
|
# Marks code as deprecated with/without replacement.
|
|
78
108
|
#
|
|
79
109
|
# @param [String] old
|
|
80
110
|
# @param [String, nil] new
|
|
111
|
+
# @param [Symbol, Array<Symbol>] id
|
|
112
|
+
# @param [String] reference
|
|
113
|
+
# @yield appends additional message to end of provided template
|
|
81
114
|
#
|
|
82
|
-
def deprecate(old, new = nil)
|
|
83
|
-
|
|
115
|
+
def deprecate(old, new = nil, id: [], reference: '', &block)
|
|
116
|
+
id = Array(id)
|
|
117
|
+
return if @ignored.include?(:deprecations) || (@ignored & id).any?
|
|
118
|
+
|
|
119
|
+
ids = id.empty? ? '' : "[#{id.map(&:inspect).join(', ')}] "
|
|
120
|
+
|
|
121
|
+
message = +"[DEPRECATION] #{ids}#{old} is deprecated"
|
|
84
122
|
message << if new
|
|
85
123
|
". Use #{new} instead."
|
|
86
124
|
else
|
|
87
|
-
' and will be removed in
|
|
125
|
+
' and will be removed in a future release.'
|
|
88
126
|
end
|
|
127
|
+
message << " See explanation for this deprecation: #{reference}." unless reference.empty?
|
|
89
128
|
|
|
90
|
-
warn message
|
|
129
|
+
warn message, &block
|
|
91
130
|
end
|
|
92
131
|
|
|
93
132
|
private
|
|
94
133
|
|
|
95
|
-
def create_logger(
|
|
96
|
-
logger = ::Logger.new(
|
|
97
|
-
logger.progname =
|
|
134
|
+
def create_logger(name)
|
|
135
|
+
logger = ::Logger.new($stdout)
|
|
136
|
+
logger.progname = name
|
|
98
137
|
logger.level = default_level
|
|
99
138
|
logger.formatter = proc do |severity, time, progname, msg|
|
|
100
139
|
"#{time.strftime('%F %T')} #{severity} #{progname} #{msg}\n"
|
|
@@ -104,11 +143,7 @@ module Selenium
|
|
|
104
143
|
end
|
|
105
144
|
|
|
106
145
|
def default_level
|
|
107
|
-
|
|
108
|
-
:debug
|
|
109
|
-
else
|
|
110
|
-
:warn
|
|
111
|
-
end
|
|
146
|
+
$DEBUG || ENV.key?('DEBUG') ? :debug : :warn
|
|
112
147
|
end
|
|
113
148
|
end # Logger
|
|
114
149
|
end # WebDriver
|
|
@@ -36,6 +36,7 @@ module Selenium
|
|
|
36
36
|
# @option opts [String] :value A value
|
|
37
37
|
# @option opts [String] :path ('/') A path
|
|
38
38
|
# @option opts [String] :secure (false) A boolean
|
|
39
|
+
# @option opts [String] :same_site (Strict or Lax) currently supported only in chrome 80+ versions
|
|
39
40
|
# @option opts [Time,DateTime,Numeric,nil] :expires (nil) Expiry date, either as a Time, DateTime, or seconds since epoch.
|
|
40
41
|
#
|
|
41
42
|
# @raise [ArgumentError] if :name or :value is not specified
|
|
@@ -45,9 +46,15 @@ module Selenium
|
|
|
45
46
|
raise ArgumentError, 'name is required' unless opts[:name]
|
|
46
47
|
raise ArgumentError, 'value is required' unless opts[:value]
|
|
47
48
|
|
|
48
|
-
|
|
49
|
+
# NOTE: This is required because of https://bugs.chromium.org/p/chromedriver/issues/detail?id=3732
|
|
49
50
|
opts[:secure] ||= false
|
|
50
51
|
|
|
52
|
+
same_site = opts.delete(:same_site)
|
|
53
|
+
opts[:sameSite] = same_site if same_site
|
|
54
|
+
|
|
55
|
+
http_only = opts.delete(:http_only)
|
|
56
|
+
opts[:httpOnly] = http_only if http_only
|
|
57
|
+
|
|
51
58
|
obj = opts.delete(:expires)
|
|
52
59
|
opts[:expiry] = seconds_from(obj).to_i if obj
|
|
53
60
|
|
|
@@ -62,7 +69,7 @@ module Selenium
|
|
|
62
69
|
#
|
|
63
70
|
|
|
64
71
|
def cookie_named(name)
|
|
65
|
-
|
|
72
|
+
convert_cookie(@bridge.cookie(name))
|
|
66
73
|
end
|
|
67
74
|
|
|
68
75
|
#
|
|
@@ -97,42 +104,6 @@ module Selenium
|
|
|
97
104
|
@timeouts ||= Timeouts.new(@bridge)
|
|
98
105
|
end
|
|
99
106
|
|
|
100
|
-
#
|
|
101
|
-
# @api beta This API may be changed or removed in a future release.
|
|
102
|
-
#
|
|
103
|
-
|
|
104
|
-
def logs
|
|
105
|
-
@logs ||= Logs.new(@bridge)
|
|
106
|
-
end
|
|
107
|
-
|
|
108
|
-
#
|
|
109
|
-
# Create a new top-level browsing context
|
|
110
|
-
# https://w3c.github.io/webdriver/#new-window
|
|
111
|
-
# @param type [Symbol] Supports two values: :tab and :window.
|
|
112
|
-
# Use :tab if you'd like the new window to share an OS-level window
|
|
113
|
-
# with the current browsing context.
|
|
114
|
-
# Use :window otherwise
|
|
115
|
-
# @return [String] The value of the window handle
|
|
116
|
-
#
|
|
117
|
-
def new_window(type = :tab)
|
|
118
|
-
case type
|
|
119
|
-
when :tab, :window
|
|
120
|
-
result = @bridge.new_window(type)
|
|
121
|
-
unless result.key?('handle')
|
|
122
|
-
raise UnknownError, "the driver did not return a handle. " \
|
|
123
|
-
"The returned result: #{result.inspect}"
|
|
124
|
-
end
|
|
125
|
-
result['handle']
|
|
126
|
-
else
|
|
127
|
-
raise ArgumentError, "invalid argument for type. Got: '#{type.inspect}'. " \
|
|
128
|
-
"Try :tab or :window"
|
|
129
|
-
end
|
|
130
|
-
end
|
|
131
|
-
|
|
132
|
-
#
|
|
133
|
-
# @api beta This API may be changed or removed in a future release.
|
|
134
|
-
#
|
|
135
|
-
|
|
136
107
|
def window
|
|
137
108
|
@window ||= Window.new(@bridge)
|
|
138
109
|
end
|
|
@@ -169,6 +140,8 @@ module Selenium
|
|
|
169
140
|
path: cookie['path'],
|
|
170
141
|
domain: cookie['domain'] && strip_port(cookie['domain']),
|
|
171
142
|
expires: cookie['expiry'] && datetime_at(cookie['expiry']),
|
|
143
|
+
same_site: cookie['sameSite'],
|
|
144
|
+
http_only: cookie['httpOnly'],
|
|
172
145
|
secure: cookie['secure']
|
|
173
146
|
}
|
|
174
147
|
end
|
|
@@ -19,35 +19,159 @@
|
|
|
19
19
|
|
|
20
20
|
module Selenium
|
|
21
21
|
module WebDriver
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
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
|
+
class << self
|
|
28
|
+
attr_reader :driver_path
|
|
29
|
+
|
|
30
|
+
def chrome(**opts)
|
|
31
|
+
Chrome::Options.new(**opts)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def firefox(**opts)
|
|
35
|
+
Firefox::Options.new(**opts)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def ie(**opts)
|
|
39
|
+
IE::Options.new(**opts)
|
|
40
|
+
end
|
|
41
|
+
alias_method :internet_explorer, :ie
|
|
42
|
+
|
|
43
|
+
def edge(**opts)
|
|
44
|
+
Edge::Options.new(**opts)
|
|
45
|
+
end
|
|
46
|
+
alias_method :microsoftedge, :edge
|
|
47
|
+
|
|
48
|
+
def safari(**opts)
|
|
49
|
+
Safari::Options.new(**opts)
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def set_capabilities
|
|
53
|
+
(W3C_OPTIONS + self::CAPABILITIES.keys).each do |key|
|
|
54
|
+
next if method_defined? key
|
|
55
|
+
|
|
56
|
+
define_method key do
|
|
57
|
+
@options[key]
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
define_method "#{key}=" do |value|
|
|
61
|
+
@options[key] = value
|
|
62
|
+
end
|
|
37
63
|
end
|
|
38
64
|
end
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
attr_accessor :options
|
|
68
|
+
|
|
69
|
+
def initialize(**opts)
|
|
70
|
+
self.class.set_capabilities
|
|
71
|
+
|
|
72
|
+
@options = opts
|
|
73
|
+
@options[:browser_name] = self.class::BROWSER
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
#
|
|
77
|
+
# Add a new option not yet handled by bindings.
|
|
78
|
+
#
|
|
79
|
+
# @example Leave Chrome open when chromedriver is killed
|
|
80
|
+
# options = Selenium::WebDriver::Chrome::Options.new
|
|
81
|
+
# options.add_option(:detach, true)
|
|
82
|
+
#
|
|
83
|
+
# @param [String, Symbol] name Name of the option
|
|
84
|
+
# @param [Boolean, String, Integer] value Value of the option
|
|
85
|
+
#
|
|
86
|
+
|
|
87
|
+
def add_option(name, value = nil)
|
|
88
|
+
@options[name.keys.first] = name.values.first if value.nil? && name.is_a?(Hash)
|
|
89
|
+
@options[name] = value
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def ==(other)
|
|
93
|
+
return false unless other.is_a? self.class
|
|
94
|
+
|
|
95
|
+
as_json == other.as_json
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
alias_method :eql?, :==
|
|
99
|
+
|
|
100
|
+
#
|
|
101
|
+
# @api private
|
|
102
|
+
#
|
|
103
|
+
|
|
104
|
+
def as_json(*)
|
|
105
|
+
options = @options.dup
|
|
106
|
+
|
|
107
|
+
w3c_options = process_w3c_options(options)
|
|
108
|
+
|
|
109
|
+
self.class::CAPABILITIES.each do |capability_alias, capability_name|
|
|
110
|
+
capability_value = options.delete(capability_alias)
|
|
111
|
+
options[capability_name] = capability_value if !capability_value.nil? && !options.key?(capability_name)
|
|
112
|
+
end
|
|
113
|
+
browser_options = defined?(self.class::KEY) ? {self.class::KEY => options} : options
|
|
39
114
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
115
|
+
process_browser_options(browser_options)
|
|
116
|
+
generate_as_json(w3c_options.merge(browser_options))
|
|
117
|
+
end
|
|
43
118
|
|
|
44
|
-
|
|
119
|
+
private
|
|
120
|
+
|
|
121
|
+
def w3c?(key)
|
|
122
|
+
W3C_OPTIONS.include?(key) || key.to_s.include?(':')
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
def process_w3c_options(options)
|
|
126
|
+
w3c_options = options.select { |key, _val| w3c?(key) }
|
|
127
|
+
w3c_options[:unhandled_prompt_behavior] &&= w3c_options[:unhandled_prompt_behavior]&.to_s&.tr('_', ' ')
|
|
128
|
+
options.delete_if { |key, _val| w3c?(key) }
|
|
129
|
+
w3c_options
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
def process_browser_options(_browser_options)
|
|
133
|
+
nil
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
def camelize?(_key)
|
|
137
|
+
true
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
def generate_as_json(value, camelize_keys: true)
|
|
141
|
+
if value.is_a?(Hash)
|
|
142
|
+
process_json_hash(value, camelize_keys)
|
|
143
|
+
elsif value.respond_to?(:as_json)
|
|
144
|
+
value.as_json
|
|
145
|
+
elsif value.is_a?(Array)
|
|
146
|
+
value.map { |val| generate_as_json(val, camelize_keys: camelize_keys) }
|
|
147
|
+
elsif value.is_a?(Symbol)
|
|
148
|
+
value.to_s
|
|
149
|
+
else
|
|
150
|
+
value
|
|
45
151
|
end
|
|
152
|
+
end
|
|
46
153
|
|
|
47
|
-
|
|
48
|
-
|
|
154
|
+
def process_json_hash(value, camelize_keys)
|
|
155
|
+
value.each_with_object({}) do |(key, val), hash|
|
|
156
|
+
next if val.respond_to?(:empty?) && val.empty?
|
|
157
|
+
|
|
158
|
+
camelize = camelize_keys ? camelize?(key) : false
|
|
159
|
+
key = convert_json_key(key, camelize: camelize)
|
|
160
|
+
hash[key] = generate_as_json(val, camelize_keys: camelize)
|
|
49
161
|
end
|
|
50
|
-
end
|
|
51
|
-
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
def convert_json_key(key, camelize: true)
|
|
165
|
+
key = key.to_s if key.is_a?(Symbol)
|
|
166
|
+
key = camel_case(key) if camelize
|
|
167
|
+
return key if key.is_a?(String)
|
|
168
|
+
|
|
169
|
+
raise TypeError, "expected String or Symbol, got #{key.inspect}:#{key.class}"
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
def camel_case(str)
|
|
173
|
+
str.gsub(/_([a-z])/) { Regexp.last_match(1).upcase }
|
|
174
|
+
end
|
|
175
|
+
end # Options
|
|
52
176
|
end # WebDriver
|
|
53
177
|
end # Selenium
|
|
@@ -57,6 +57,8 @@ module Selenium
|
|
|
57
57
|
:jenkins
|
|
58
58
|
elsif ENV['APPVEYOR']
|
|
59
59
|
:appveyor
|
|
60
|
+
elsif ENV['GITHUB_ACTIONS']
|
|
61
|
+
:github
|
|
60
62
|
end
|
|
61
63
|
end
|
|
62
64
|
|
|
@@ -95,11 +97,14 @@ module Selenium
|
|
|
95
97
|
def wsl?
|
|
96
98
|
return false unless linux?
|
|
97
99
|
|
|
98
|
-
File.read('/proc/version').include?('
|
|
100
|
+
File.read('/proc/version').downcase.include?('microsoft')
|
|
101
|
+
rescue Errno::EACCES
|
|
102
|
+
# the file cannot be accessed on Linux on DeX
|
|
103
|
+
false
|
|
99
104
|
end
|
|
100
105
|
|
|
101
106
|
def cygwin?
|
|
102
|
-
RUBY_PLATFORM
|
|
107
|
+
RUBY_PLATFORM.include?('cygwin')
|
|
103
108
|
!Regexp.last_match.nil?
|
|
104
109
|
end
|
|
105
110
|
|
|
@@ -172,9 +177,9 @@ module Selenium
|
|
|
172
177
|
|
|
173
178
|
def find_in_program_files(*binary_names)
|
|
174
179
|
paths = [
|
|
175
|
-
ENV
|
|
176
|
-
ENV
|
|
177
|
-
ENV
|
|
180
|
+
ENV.fetch('PROGRAMFILES', '\\Program Files'),
|
|
181
|
+
ENV.fetch('ProgramFiles(x86)', '\\Program Files (x86)'),
|
|
182
|
+
ENV.fetch('ProgramW6432', '\\Program Files')
|
|
178
183
|
]
|
|
179
184
|
|
|
180
185
|
paths.each do |root|
|
|
@@ -32,12 +32,10 @@ module Selenium
|
|
|
32
32
|
|
|
33
33
|
def self.free?(port)
|
|
34
34
|
Platform.interfaces.each do |host|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
# ignored - some machines appear unable to bind to some of their interfaces
|
|
40
|
-
end
|
|
35
|
+
TCPServer.new(host, port).close
|
|
36
|
+
rescue *IGNORED_ERRORS => e
|
|
37
|
+
WebDriver.logger.debug("port prober could not bind to #{host}:#{port} (#{e.message})")
|
|
38
|
+
# ignored - some machines appear unable to bind to some of their interfaces
|
|
41
39
|
end
|
|
42
40
|
|
|
43
41
|
true
|
|
@@ -31,8 +31,16 @@ module Selenium
|
|
|
31
31
|
base.extend ClassMethods
|
|
32
32
|
end
|
|
33
33
|
|
|
34
|
+
def self.decoded(json)
|
|
35
|
+
JSON.parse(json).fetch('zip')
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def encoded
|
|
39
|
+
Zipper.zip(layout_on_disk)
|
|
40
|
+
end
|
|
41
|
+
|
|
34
42
|
def as_json(*)
|
|
35
|
-
{"zip" =>
|
|
43
|
+
{"zip" => encoded}
|
|
36
44
|
end
|
|
37
45
|
|
|
38
46
|
def to_json(*)
|
|
@@ -63,18 +71,12 @@ module Selenium
|
|
|
63
71
|
|
|
64
72
|
module ClassMethods
|
|
65
73
|
def from_json(json)
|
|
66
|
-
data =
|
|
74
|
+
data = decoded(json)
|
|
67
75
|
|
|
68
|
-
|
|
69
|
-
# can't use Dir.mktmpdir(&blk) because of http://jira.codehaus.org/browse/JRUBY-4082
|
|
70
|
-
tmp_dir = Dir.mktmpdir
|
|
71
|
-
begin
|
|
72
|
-
zip_path = File.join(tmp_dir, "webdriver-profile-duplicate-#{json.hash}.zip")
|
|
76
|
+
Tempfile.create do |zip_path|
|
|
73
77
|
File.open(zip_path, 'wb') { |zip_file| zip_file << Base64.decode64(data) }
|
|
74
78
|
|
|
75
79
|
new Zipper.unzip(zip_path)
|
|
76
|
-
ensure
|
|
77
|
-
FileUtils.rm_rf tmp_dir
|
|
78
80
|
end
|
|
79
81
|
end
|
|
80
82
|
end # ClassMethods
|
|
@@ -127,7 +127,10 @@ module Selenium
|
|
|
127
127
|
end
|
|
128
128
|
|
|
129
129
|
def type=(type)
|
|
130
|
-
|
|
130
|
+
unless TYPES.key? type
|
|
131
|
+
raise ArgumentError,
|
|
132
|
+
"invalid proxy type: #{type.inspect}, expected one of #{TYPES.keys.inspect}"
|
|
133
|
+
end
|
|
131
134
|
|
|
132
135
|
if defined?(@type) && type != @type
|
|
133
136
|
raise ArgumentError, "incompatible proxy type #{type.inspect} (already set to #{@type.inspect})"
|
|
@@ -138,10 +141,10 @@ module Selenium
|
|
|
138
141
|
|
|
139
142
|
def as_json(*)
|
|
140
143
|
json_result = {
|
|
141
|
-
'proxyType' => TYPES[type],
|
|
144
|
+
'proxyType' => TYPES[type].downcase,
|
|
142
145
|
'ftpProxy' => ftp,
|
|
143
146
|
'httpProxy' => http,
|
|
144
|
-
'noProxy' => no_proxy,
|
|
147
|
+
'noProxy' => no_proxy.is_a?(String) ? no_proxy.split(', ') : no_proxy,
|
|
145
148
|
'proxyAutoconfigUrl' => pac,
|
|
146
149
|
'sslProxy' => ssl,
|
|
147
150
|
'autodetect' => auto_detect,
|
|
@@ -30,6 +30,7 @@ module Selenium
|
|
|
30
30
|
link_text: 'link text',
|
|
31
31
|
name: 'name',
|
|
32
32
|
partial_link_text: 'partial link text',
|
|
33
|
+
relative: 'relative',
|
|
33
34
|
tag_name: 'tag name',
|
|
34
35
|
xpath: 'xpath'
|
|
35
36
|
}.freeze
|
|
@@ -59,10 +60,7 @@ module Selenium
|
|
|
59
60
|
by = FINDERS[how.to_sym]
|
|
60
61
|
raise ArgumentError, "cannot find element by #{how.inspect}" unless by
|
|
61
62
|
|
|
62
|
-
bridge.find_element_by by, what
|
|
63
|
-
rescue Selenium::WebDriver::Error::TimeoutError
|
|
64
|
-
# Implicit Wait times out in Edge
|
|
65
|
-
raise Selenium::WebDriver::Error::NoSuchElementError
|
|
63
|
+
bridge.find_element_by by, what, ref
|
|
66
64
|
end
|
|
67
65
|
|
|
68
66
|
#
|
|
@@ -77,10 +75,7 @@ module Selenium
|
|
|
77
75
|
by = FINDERS[how.to_sym]
|
|
78
76
|
raise ArgumentError, "cannot find elements by #{how.inspect}" unless by
|
|
79
77
|
|
|
80
|
-
bridge.find_elements_by by, what
|
|
81
|
-
rescue Selenium::WebDriver::Error::TimeoutError
|
|
82
|
-
# Implicit Wait times out in Edge
|
|
83
|
-
[]
|
|
78
|
+
bridge.find_elements_by by, what, ref
|
|
84
79
|
end
|
|
85
80
|
|
|
86
81
|
private
|
|
@@ -92,7 +87,10 @@ module Selenium
|
|
|
92
87
|
when 1
|
|
93
88
|
arg = args.first
|
|
94
89
|
|
|
95
|
-
|
|
90
|
+
unless arg.respond_to?(:shift)
|
|
91
|
+
raise ArgumentError,
|
|
92
|
+
"expected #{arg.inspect}:#{arg.class} to respond to #shift"
|
|
93
|
+
end
|
|
96
94
|
|
|
97
95
|
# this will be a single-entry hash, so use #shift over #first or #[]
|
|
98
96
|
arr = arg.dup.shift
|