selenium-webdriver 4.1.0 → 4.13.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (158) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGES +287 -1
  3. data/Gemfile +2 -0
  4. data/LICENSE +1 -1
  5. data/NOTICE +1 -1
  6. data/README.md +2 -2
  7. data/bin/linux/selenium-manager +0 -0
  8. data/bin/macos/selenium-manager +0 -0
  9. data/bin/windows/selenium-manager.exe +0 -0
  10. data/lib/selenium/server.rb +36 -39
  11. data/lib/selenium/webdriver/atoms/findElements.js +3 -4
  12. data/lib/selenium/webdriver/atoms/getAttribute.js +0 -0
  13. data/lib/selenium/webdriver/atoms/isDisplayed.js +0 -0
  14. data/lib/selenium/webdriver/atoms/mutationListener.js +0 -0
  15. data/lib/selenium/webdriver/atoms.rb +2 -3
  16. data/lib/selenium/webdriver/bidi/browsing_context.rb +88 -0
  17. data/lib/selenium/webdriver/bidi/browsing_context_info.rb +35 -0
  18. data/lib/selenium/webdriver/bidi/log/base_log_entry.rb +35 -0
  19. data/lib/selenium/webdriver/bidi/log/console_log_entry.rb +35 -0
  20. data/lib/selenium/webdriver/{common/driver_extensions/has_location.rb → bidi/log/filter_by.rb} +14 -11
  21. data/lib/selenium/webdriver/bidi/log/generic_log_entry.rb +33 -0
  22. data/lib/selenium/webdriver/bidi/log/javascript_log_entry.rb +33 -0
  23. data/lib/selenium/webdriver/bidi/log_inspector.rb +143 -0
  24. data/lib/selenium/webdriver/bidi/navigate_result.rb +33 -0
  25. data/lib/selenium/webdriver/bidi/session.rb +51 -0
  26. data/lib/selenium/webdriver/bidi.rb +56 -0
  27. data/lib/selenium/webdriver/chrome/driver.rb +9 -29
  28. data/lib/selenium/webdriver/chrome/features.rb +6 -68
  29. data/lib/selenium/webdriver/chrome/options.rb +3 -223
  30. data/lib/selenium/webdriver/chrome/profile.rb +3 -83
  31. data/lib/selenium/webdriver/chrome/service.rb +4 -19
  32. data/lib/selenium/webdriver/chrome.rb +0 -16
  33. data/lib/selenium/webdriver/chromium/driver.rb +60 -0
  34. data/lib/selenium/webdriver/chromium/features.rb +103 -0
  35. data/lib/selenium/webdriver/chromium/options.rb +243 -0
  36. data/lib/selenium/webdriver/chromium/profile.rb +113 -0
  37. data/lib/selenium/webdriver/chromium.rb +29 -0
  38. data/lib/selenium/webdriver/common/action_builder.rb +62 -22
  39. data/lib/selenium/webdriver/common/child_process.rb +124 -0
  40. data/lib/selenium/webdriver/common/driver.rb +31 -81
  41. data/lib/selenium/webdriver/common/driver_extensions/downloads_files.rb +0 -2
  42. data/lib/selenium/webdriver/common/driver_extensions/full_page_screenshot.rb +0 -1
  43. data/lib/selenium/webdriver/common/driver_extensions/has_addons.rb +0 -2
  44. data/lib/selenium/webdriver/common/driver_extensions/has_apple_permissions.rb +0 -2
  45. data/lib/selenium/webdriver/common/driver_extensions/has_authentication.rb +0 -2
  46. data/lib/selenium/webdriver/common/driver_extensions/{has_remote_status.rb → has_bidi.rb} +10 -5
  47. data/lib/selenium/webdriver/common/driver_extensions/has_casting.rb +10 -1
  48. data/lib/selenium/webdriver/common/driver_extensions/has_cdp.rb +0 -2
  49. data/lib/selenium/webdriver/common/driver_extensions/has_context.rb +1 -4
  50. data/lib/selenium/webdriver/common/driver_extensions/has_debugger.rb +0 -2
  51. data/lib/selenium/webdriver/common/driver_extensions/has_devtools.rb +0 -2
  52. data/lib/selenium/webdriver/common/driver_extensions/has_launching.rb +0 -2
  53. data/lib/selenium/webdriver/common/driver_extensions/has_log_events.rb +1 -2
  54. data/lib/selenium/webdriver/common/driver_extensions/has_network_conditions.rb +0 -2
  55. data/lib/selenium/webdriver/common/driver_extensions/has_network_interception.rb +2 -69
  56. data/lib/selenium/webdriver/common/driver_extensions/has_permissions.rb +0 -2
  57. data/lib/selenium/webdriver/common/driver_extensions/has_pinned_scripts.rb +1 -3
  58. data/lib/selenium/webdriver/common/driver_finder.rb +45 -0
  59. data/lib/selenium/webdriver/common/element.rb +8 -8
  60. data/lib/selenium/webdriver/common/error.rb +28 -5
  61. data/lib/selenium/webdriver/common/html5/shared_web_storage.rb +2 -2
  62. data/lib/selenium/webdriver/common/interactions/input_device.rb +10 -4
  63. data/lib/selenium/webdriver/common/interactions/interaction.rb +12 -25
  64. data/lib/selenium/webdriver/common/interactions/interactions.rb +24 -4
  65. data/lib/selenium/webdriver/common/interactions/key_actions.rb +5 -1
  66. data/lib/selenium/webdriver/common/interactions/key_input.rb +11 -27
  67. data/lib/selenium/webdriver/common/interactions/none_input.rb +10 -8
  68. data/lib/selenium/webdriver/common/interactions/pause.rb +49 -0
  69. data/lib/selenium/webdriver/common/interactions/pointer_actions.rb +59 -70
  70. data/lib/selenium/webdriver/common/{driver_extensions/has_network_connection.rb → interactions/pointer_cancel.rb} +19 -11
  71. data/lib/selenium/webdriver/common/interactions/pointer_event_properties.rb +63 -0
  72. data/lib/selenium/webdriver/common/interactions/pointer_input.rb +15 -84
  73. data/lib/selenium/webdriver/common/interactions/pointer_move.rb +60 -0
  74. data/lib/selenium/webdriver/common/interactions/pointer_press.rb +85 -0
  75. data/lib/selenium/webdriver/common/interactions/scroll.rb +59 -0
  76. data/lib/selenium/webdriver/common/interactions/scroll_origin.rb +48 -0
  77. data/lib/selenium/webdriver/common/interactions/typing_interaction.rb +54 -0
  78. data/lib/selenium/webdriver/common/interactions/wheel_actions.rb +113 -0
  79. data/lib/selenium/webdriver/common/interactions/wheel_input.rb +42 -0
  80. data/lib/selenium/webdriver/common/keys.rb +1 -0
  81. data/lib/selenium/webdriver/common/local_driver.rb +46 -0
  82. data/lib/selenium/webdriver/common/logger.rb +90 -25
  83. data/lib/selenium/webdriver/common/manager.rb +0 -27
  84. data/lib/selenium/webdriver/common/options.rb +13 -17
  85. data/lib/selenium/webdriver/common/platform.rb +5 -51
  86. data/lib/selenium/webdriver/common/port_prober.rb +1 -1
  87. data/lib/selenium/webdriver/common/profile_helper.rb +1 -1
  88. data/lib/selenium/webdriver/common/proxy.rb +2 -2
  89. data/lib/selenium/webdriver/common/search_context.rb +0 -6
  90. data/lib/selenium/webdriver/common/selenium_manager.rb +134 -0
  91. data/lib/selenium/webdriver/common/service.rb +21 -30
  92. data/lib/selenium/webdriver/common/service_manager.rb +8 -15
  93. data/lib/selenium/webdriver/common/shadow_root.rb +2 -3
  94. data/lib/selenium/webdriver/common/socket_lock.rb +3 -3
  95. data/lib/selenium/webdriver/common/socket_poller.rb +2 -2
  96. data/lib/selenium/webdriver/common/takes_screenshot.rb +2 -3
  97. data/lib/selenium/webdriver/common/target_locator.rb +2 -3
  98. data/lib/selenium/webdriver/common/timeouts.rb +2 -2
  99. data/lib/selenium/webdriver/common/virtual_authenticator/credential.rb +85 -0
  100. data/lib/selenium/webdriver/common/virtual_authenticator/virtual_authenticator.rb +72 -0
  101. data/lib/selenium/webdriver/common/virtual_authenticator/virtual_authenticator_options.rb +62 -0
  102. data/lib/selenium/webdriver/common/websocket_connection.rb +164 -0
  103. data/lib/selenium/webdriver/common/window.rb +6 -6
  104. data/lib/selenium/webdriver/common/zipper.rb +1 -1
  105. data/lib/selenium/webdriver/common.rb +21 -5
  106. data/lib/selenium/webdriver/devtools/console_event.rb +0 -2
  107. data/lib/selenium/webdriver/devtools/exception_event.rb +0 -2
  108. data/lib/selenium/webdriver/devtools/mutation_event.rb +0 -2
  109. data/lib/selenium/webdriver/devtools/network_interceptor.rb +173 -0
  110. data/lib/selenium/webdriver/devtools/pinned_script.rb +0 -2
  111. data/lib/selenium/webdriver/devtools/request.rb +1 -3
  112. data/lib/selenium/webdriver/devtools/response.rb +1 -3
  113. data/lib/selenium/webdriver/devtools.rb +17 -114
  114. data/lib/selenium/webdriver/edge/driver.rb +9 -3
  115. data/lib/selenium/webdriver/edge/features.rb +4 -4
  116. data/lib/selenium/webdriver/edge/options.rb +17 -5
  117. data/lib/selenium/webdriver/edge/profile.rb +2 -2
  118. data/lib/selenium/webdriver/edge/service.rb +8 -7
  119. data/lib/selenium/webdriver/edge.rb +0 -2
  120. data/lib/selenium/webdriver/firefox/driver.rb +9 -2
  121. data/lib/selenium/webdriver/firefox/features.rb +6 -6
  122. data/lib/selenium/webdriver/firefox/options.rb +7 -16
  123. data/lib/selenium/webdriver/firefox/profile.rb +8 -12
  124. data/lib/selenium/webdriver/firefox/service.rb +0 -18
  125. data/lib/selenium/webdriver/firefox/util.rb +46 -0
  126. data/lib/selenium/webdriver/firefox.rb +1 -14
  127. data/lib/selenium/webdriver/ie/driver.rb +7 -1
  128. data/lib/selenium/webdriver/ie/options.rb +4 -3
  129. data/lib/selenium/webdriver/ie/service.rb +0 -22
  130. data/lib/selenium/webdriver/ie.rb +0 -14
  131. data/lib/selenium/webdriver/remote/{commands.rb → bridge/commands.rb} +15 -8
  132. data/lib/selenium/webdriver/remote/bridge.rb +65 -35
  133. data/lib/selenium/webdriver/remote/capabilities.rb +3 -53
  134. data/lib/selenium/webdriver/remote/driver.rb +31 -14
  135. data/lib/selenium/webdriver/remote/http/common.rb +3 -3
  136. data/lib/selenium/webdriver/remote/http/curb.rb +1 -3
  137. data/lib/selenium/webdriver/remote/http/default.rb +8 -14
  138. data/lib/selenium/webdriver/remote/response.rb +2 -3
  139. data/lib/selenium/webdriver/remote/server_error.rb +1 -1
  140. data/lib/selenium/webdriver/remote.rb +0 -1
  141. data/lib/selenium/webdriver/safari/driver.rb +7 -1
  142. data/lib/selenium/webdriver/safari/features.rb +0 -2
  143. data/lib/selenium/webdriver/safari/options.rb +5 -1
  144. data/lib/selenium/webdriver/safari/service.rb +10 -4
  145. data/lib/selenium/webdriver/safari.rb +1 -15
  146. data/lib/selenium/webdriver/support/color.rb +22 -22
  147. data/lib/selenium/webdriver/support/guards/guard.rb +0 -2
  148. data/lib/selenium/webdriver/support/guards/guard_condition.rb +1 -3
  149. data/lib/selenium/webdriver/support/guards.rb +1 -1
  150. data/lib/selenium/webdriver/support/relative_locator.rb +0 -1
  151. data/lib/selenium/webdriver/support/select.rb +3 -1
  152. data/lib/selenium/webdriver/version.rb +1 -1
  153. data/lib/selenium/webdriver.rb +6 -4
  154. data/selenium-webdriver.gemspec +14 -12
  155. metadata +73 -65
  156. data/lib/selenium/webdriver/remote/http/persistent.rb +0 -65
  157. data/lib/selenium/webdriver/support/cdp/domain.rb.erb +0 -63
  158. data/lib/selenium/webdriver/support/cdp_client_generator.rb +0 -108
@@ -0,0 +1,46 @@
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
+ module LocalDriver
23
+ def initialize_local_driver(options, service, url)
24
+ raise ArgumentError, "Can't initialize #{self.class} with :url" if url
25
+
26
+ service ||= Service.send(browser)
27
+ caps = process_options(options, service)
28
+ url = service_url(service)
29
+
30
+ [caps, url]
31
+ end
32
+
33
+ def process_options(options, service)
34
+ default_options = Options.send(browser)
35
+ options ||= default_options
36
+
37
+ unless options.is_a?(default_options.class)
38
+ raise ArgumentError, ":options must be an instance of #{default_options.class}"
39
+ end
40
+
41
+ service.executable_path ||= WebDriver::DriverFinder.path(options, service.class)
42
+ options.as_json
43
+ end
44
+ end
45
+ end
46
+ end
@@ -38,19 +38,31 @@ module Selenium
38
38
 
39
39
  def_delegators :@logger,
40
40
  :close,
41
- :debug, :debug?,
42
- :info, :info?,
41
+ :debug?,
42
+ :info?,
43
43
  :warn?,
44
- :error, :error?,
44
+ :error?,
45
45
  :fatal, :fatal?,
46
- :level, :level=
46
+ :level
47
47
 
48
48
  #
49
49
  # @param [String] progname Allow child projects to use Selenium's Logger pattern
50
50
  #
51
- def initialize(progname = 'Selenium')
52
- @logger = create_logger(progname)
53
- @ignored = []
51
+ def initialize(progname = 'Selenium', default_level: nil, ignored: nil, allowed: nil)
52
+ default_level ||= $DEBUG || ENV.key?('DEBUG') ? :debug : :warn
53
+
54
+ @logger = create_logger(progname, level: default_level)
55
+ @ignored = Array(ignored)
56
+ @allowed = Array(allowed)
57
+ @first_warning = false
58
+ end
59
+
60
+ def level=(level)
61
+ if level == :info && @logger.level == :info
62
+ info(':info is now the default log level, to see additional logging, set log level to :debug')
63
+ end
64
+
65
+ @logger.level = level
54
66
  end
55
67
 
56
68
  #
@@ -80,27 +92,64 @@ module Selenium
80
92
  #
81
93
  # Will not log the provided ID.
82
94
  #
83
- # @param [Array, Symbol] id
95
+ # @param [Array, Symbol] ids
96
+ #
97
+ def ignore(*ids)
98
+ @ignored += Array(ids).flatten
99
+ end
100
+
101
+ #
102
+ # Will only log the provided ID.
84
103
  #
85
- def ignore(id)
86
- Array(id).each { |ignore| @ignored << ignore }
104
+ # @param [Array, Symbol] ids
105
+ #
106
+ def allow(ids)
107
+ @allowed += Array(ids).flatten
87
108
  end
88
109
 
89
110
  #
90
- # Overrides default #warn to skip ignored messages by provided id
111
+ # Used to supply information of interest for debugging a problem
112
+ # Overrides default #debug to skip ignored messages by provided id
91
113
  #
92
114
  # @param [String] message
93
115
  # @param [Symbol, Array<Sybmol>] id
94
116
  # @yield see #deprecate
95
117
  #
96
- def warn(message, id: [])
97
- id = Array(id)
98
- return if (@ignored & id).any?
118
+ def debug(message, id: [], &block)
119
+ discard_or_log(:debug, message, id, &block)
120
+ end
99
121
 
100
- msg = id.empty? ? message : "[#{id.map(&:inspect).join(', ')}] #{message} "
101
- msg += " #{yield}" if block_given?
122
+ #
123
+ # Used to supply information of general interest
124
+ #
125
+ # @param [String] message
126
+ # @param [Symbol, Array<Sybmol>] id
127
+ # @yield see #deprecate
128
+ #
129
+ def info(message, id: [], &block)
130
+ discard_or_log(:info, message, id, &block)
131
+ end
102
132
 
103
- @logger.warn { msg }
133
+ #
134
+ # Used to supply information that suggests an error occurred
135
+ #
136
+ # @param [String] message
137
+ # @param [Symbol, Array<Sybmol>] id
138
+ # @yield see #deprecate
139
+ #
140
+ def error(message, id: [], &block)
141
+ discard_or_log(:error, message, id, &block)
142
+ end
143
+
144
+ #
145
+ # Used to supply information that suggests action be taken by user
146
+ #
147
+ # @param [String] message
148
+ # @param [Symbol, Array<Sybmol>] id
149
+ # @yield see #deprecate
150
+ #
151
+ def warn(message, id: [], &block)
152
+ discard_or_log(:warn, message, id, &block)
104
153
  end
105
154
 
106
155
  #
@@ -114,11 +163,11 @@ module Selenium
114
163
  #
115
164
  def deprecate(old, new = nil, id: [], reference: '', &block)
116
165
  id = Array(id)
117
- return if @ignored.include?(:deprecations) || (@ignored & id).any?
166
+ return if @ignored.include?(:deprecations)
118
167
 
119
- ids = id.empty? ? '' : "[#{id.map(&:inspect).join(', ')}] "
168
+ id << :deprecations if @allowed.include?(:deprecations)
120
169
 
121
- message = +"[DEPRECATION] #{ids}#{old} is deprecated"
170
+ message = +"[DEPRECATION] #{old} is deprecated"
122
171
  message << if new
123
172
  ". Use #{new} instead."
124
173
  else
@@ -126,15 +175,15 @@ module Selenium
126
175
  end
127
176
  message << " See explanation for this deprecation: #{reference}." unless reference.empty?
128
177
 
129
- warn message, &block
178
+ discard_or_log(:warn, message, id, &block)
130
179
  end
131
180
 
132
181
  private
133
182
 
134
- def create_logger(name)
183
+ def create_logger(name, level:)
135
184
  logger = ::Logger.new($stdout)
136
185
  logger.progname = name
137
- logger.level = default_level
186
+ logger.level = level
138
187
  logger.formatter = proc do |severity, time, progname, msg|
139
188
  "#{time.strftime('%F %T')} #{severity} #{progname} #{msg}\n"
140
189
  end
@@ -142,8 +191,24 @@ module Selenium
142
191
  logger
143
192
  end
144
193
 
145
- def default_level
146
- $DEBUG || ENV.key?('DEBUG') ? :debug : :warn
194
+ def discard_or_log(level, message, id)
195
+ id = Array(id)
196
+ return if (@ignored & id).any?
197
+ return if @allowed.any? && (@allowed & id).none?
198
+
199
+ return if ::Logger::Severity.const_get(level.upcase) < @logger.level
200
+
201
+ unless @first_warning
202
+ @first_warning = true
203
+ info("Details on how to use and modify Selenium logger:\n", id: [:logger_info]) do
204
+ "https://selenium.dev/documentation/webdriver/troubleshooting/logging\n"
205
+ end
206
+ end
207
+
208
+ msg = id.empty? ? message : "[#{id.map(&:inspect).join(', ')}] #{message} "
209
+ msg += " #{yield}" if block_given?
210
+
211
+ @logger.send(level) { msg }
147
212
  end
148
213
  end # Logger
149
214
  end # WebDriver
@@ -104,33 +104,6 @@ module Selenium
104
104
  @timeouts ||= Timeouts.new(@bridge)
105
105
  end
106
106
 
107
- def logs
108
- WebDriver.logger.deprecate('Manager#logs', 'Chrome::Driver#logs')
109
- @logs ||= Logs.new(@bridge)
110
- end
111
-
112
- #
113
- # @param type [Symbol] Supports two values: :tab and :window.
114
- # @return [String] The value of the window handle
115
- #
116
- def new_window(type = :tab)
117
- WebDriver.logger.deprecate('Manager#new_window', 'TargetLocator#new_window', id: :new_window) do
118
- 'e.g., `driver.switch_to.new_window(:tab)`'
119
- end
120
- case type
121
- when :tab, :window
122
- result = @bridge.new_window(type)
123
- unless result.key?('handle')
124
- raise UnknownError, "the driver did not return a handle. " \
125
- "The returned result: #{result.inspect}"
126
- end
127
- result['handle']
128
- else
129
- raise ArgumentError, "invalid argument for type. Got: '#{type.inspect}'. " \
130
- "Try :tab or :window"
131
- end
132
- end
133
-
134
107
  def window
135
108
  @window ||= Window.new(@bridge)
136
109
  end
@@ -38,12 +38,12 @@ module Selenium
38
38
  def ie(**opts)
39
39
  IE::Options.new(**opts)
40
40
  end
41
- alias_method :internet_explorer, :ie
41
+ alias internet_explorer ie
42
42
 
43
43
  def edge(**opts)
44
44
  Edge::Options.new(**opts)
45
45
  end
46
- alias_method :microsoftedge, :edge
46
+ alias microsoftedge edge
47
47
 
48
48
  def safari(**opts)
49
49
  Safari::Options.new(**opts)
@@ -66,17 +66,10 @@ module Selenium
66
66
 
67
67
  attr_accessor :options
68
68
 
69
- def initialize(options: nil, **opts)
69
+ def initialize(**opts)
70
70
  self.class.set_capabilities
71
71
 
72
- @options = if options
73
- WebDriver.logger.deprecate(":options as keyword for initializing #{self.class}",
74
- "custom values directly in #new constructor",
75
- id: :options_options)
76
- opts.merge(options)
77
- else
78
- opts
79
- end
72
+ @options = opts
80
73
  @options[:browser_name] = self.class::BROWSER
81
74
  end
82
75
 
@@ -92,7 +85,7 @@ module Selenium
92
85
  #
93
86
 
94
87
  def add_option(name, value = nil)
95
- @options[name.keys.first] = name.values.first if value.nil? && name.is_a?(Hash)
88
+ name, value = name.first if value.nil? && name.is_a?(Hash)
96
89
  @options[name] = value
97
90
  end
98
91
 
@@ -102,7 +95,7 @@ module Selenium
102
95
  as_json == other.as_json
103
96
  end
104
97
 
105
- alias_method :eql?, :==
98
+ alias eql? ==
106
99
 
107
100
  #
108
101
  # @api private
@@ -113,11 +106,14 @@ module Selenium
113
106
 
114
107
  w3c_options = process_w3c_options(options)
115
108
 
116
- self.class::CAPABILITIES.each do |capability_alias, capability_name|
109
+ browser_options = self.class::CAPABILITIES.each_with_object({}) do |(capability_alias, capability_name), hash|
117
110
  capability_value = options.delete(capability_alias)
118
- options[capability_name] = capability_value if !capability_value.nil? && !options.key?(capability_name)
111
+ hash[capability_name] = capability_value unless capability_value.nil?
119
112
  end
120
- browser_options = defined?(self.class::KEY) ? {self.class::KEY => options} : options
113
+
114
+ raise Error::WebDriverError, "These options are not w3c compliant: #{options}" unless options.empty?
115
+
116
+ browser_options = {self.class::KEY => browser_options} if defined?(self.class::KEY)
121
117
 
122
118
  process_browser_options(browser_options)
123
119
  generate_as_json(w3c_options.merge(browser_options))
@@ -130,7 +126,7 @@ module Selenium
130
126
  end
131
127
 
132
128
  def process_w3c_options(options)
133
- w3c_options = options.select { |key, _val| w3c?(key) }
129
+ w3c_options = options.select { |key, val| w3c?(key) && !val.nil? }
134
130
  w3c_options[:unhandled_prompt_behavior] &&= w3c_options[:unhandled_prompt_behavior]&.to_s&.tr('_', ' ')
135
131
  options.delete_if { |key, _val| w3c?(key) }
136
132
  w3c_options
@@ -62,22 +62,14 @@ module Selenium
62
62
  end
63
63
  end
64
64
 
65
- def bitsize
66
- @bitsize ||= if defined?(FFI::Platform::ADDRESS_SIZE)
67
- FFI::Platform::ADDRESS_SIZE
68
- elsif defined?(FFI)
69
- FFI.type_size(:pointer) == 4 ? 32 : 64
70
- elsif jruby?
71
- Integer(ENV_JAVA['sun.arch.data.model'])
72
- else
73
- 1.size == 4 ? 32 : 64
74
- end
75
- end
76
-
77
65
  def jruby?
78
66
  engine == :jruby
79
67
  end
80
68
 
69
+ def truffleruby?
70
+ engine == :truffleruby
71
+ end
72
+
81
73
  def ruby_version
82
74
  RUBY_VERSION
83
75
  end
@@ -104,8 +96,7 @@ module Selenium
104
96
  end
105
97
 
106
98
  def cygwin?
107
- RUBY_PLATFORM =~ /cygwin/
108
- !Regexp.last_match.nil?
99
+ RUBY_PLATFORM.include?('cygwin')
109
100
  end
110
101
 
111
102
  def null_device
@@ -155,43 +146,6 @@ module Selenium
155
146
  at_exit { yield if Process.pid == pid }
156
147
  end
157
148
 
158
- def find_binary(*binary_names)
159
- paths = ENV['PATH'].split(File::PATH_SEPARATOR)
160
-
161
- if windows?
162
- binary_names.map! { |n| "#{n}.exe" }
163
- binary_names.dup.each { |n| binary_names << n.gsub('exe', 'bat') }
164
- end
165
-
166
- binary_names.each do |binary_name|
167
- paths.each do |path|
168
- full_path = File.join(path, binary_name)
169
- full_path = unix_path(full_path) if windows?
170
- exe = Dir.glob(full_path).find { |f| File.executable?(f) }
171
- return exe if exe
172
- end
173
- end
174
-
175
- nil
176
- end
177
-
178
- def find_in_program_files(*binary_names)
179
- paths = [
180
- ENV['PROGRAMFILES'] || '\\Program Files',
181
- ENV['ProgramFiles(x86)'] || '\\Program Files (x86)',
182
- ENV['ProgramW6432'] || '\\Program Files'
183
- ]
184
-
185
- paths.each do |root|
186
- binary_names.each do |name|
187
- exe = File.join(root, name)
188
- return exe if File.executable?(exe)
189
- end
190
- end
191
-
192
- nil
193
- end
194
-
195
149
  def localhost
196
150
  info = Socket.getaddrinfo 'localhost', 80, Socket::AF_INET, Socket::SOCK_STREAM
197
151
 
@@ -34,7 +34,7 @@ module Selenium
34
34
  Platform.interfaces.each do |host|
35
35
  TCPServer.new(host, port).close
36
36
  rescue *IGNORED_ERRORS => e
37
- WebDriver.logger.debug("port prober could not bind to #{host}:#{port} (#{e.message})")
37
+ WebDriver.logger.debug("port prober could not bind to #{host}:#{port} (#{e.message})", id: :driver_service)
38
38
  # ignored - some machines appear unable to bind to some of their interfaces
39
39
  end
40
40
 
@@ -40,7 +40,7 @@ module Selenium
40
40
  end
41
41
 
42
42
  def as_json(*)
43
- {"zip" => encoded}
43
+ {'zip' => encoded}
44
44
  end
45
45
 
46
46
  def to_json(*)
@@ -74,7 +74,7 @@ module Selenium
74
74
  def ==(other)
75
75
  other.is_a?(self.class) && as_json == other.as_json
76
76
  end
77
- alias_method :eql?, :==
77
+ alias eql? ==
78
78
 
79
79
  def ftp=(value)
80
80
  self.type = :manual
@@ -152,7 +152,7 @@ module Selenium
152
152
  'socksUsername' => socks_username,
153
153
  'socksPassword' => socks_password,
154
154
  'socksVersion' => socks_version
155
- }.delete_if { |_k, v| v.nil? }
155
+ }.compact
156
156
 
157
157
  json_result if json_result.length > 1
158
158
  end
@@ -61,9 +61,6 @@ module Selenium
61
61
  raise ArgumentError, "cannot find element by #{how.inspect}" unless by
62
62
 
63
63
  bridge.find_element_by by, what, ref
64
- rescue Selenium::WebDriver::Error::TimeoutError
65
- # Implicit Wait times out in Edge
66
- raise Selenium::WebDriver::Error::NoSuchElementError
67
64
  end
68
65
 
69
66
  #
@@ -79,9 +76,6 @@ module Selenium
79
76
  raise ArgumentError, "cannot find elements by #{how.inspect}" unless by
80
77
 
81
78
  bridge.find_elements_by by, what, ref
82
- rescue Selenium::WebDriver::Error::TimeoutError
83
- # Implicit Wait times out in Edge
84
- []
85
79
  end
86
80
 
87
81
  private
@@ -0,0 +1,134 @@
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
+ require 'open3'
21
+
22
+ module Selenium
23
+ module WebDriver
24
+ #
25
+ # Wrapper for getting information from the Selenium Manager binaries.
26
+ # This implementation is still in beta, and may change.
27
+ # @api private
28
+ #
29
+ class SeleniumManager
30
+ class << self
31
+ attr_writer :bin_path
32
+
33
+ def bin_path
34
+ @bin_path ||= '../../../../../bin'
35
+ end
36
+
37
+ # @param [Options] options browser options.
38
+ # @return [String] the path to the correct driver.
39
+ def driver_path(options)
40
+ command = generate_command(binary, options)
41
+
42
+ output = run(*command)
43
+
44
+ browser_path = output['browser_path']
45
+ driver_path = output['driver_path']
46
+ Platform.assert_executable driver_path
47
+
48
+ if options.respond_to? :binary
49
+ options.binary = browser_path
50
+ options.browser_version = nil
51
+ end
52
+
53
+ driver_path
54
+ end
55
+
56
+ private
57
+
58
+ def generate_command(binary, options)
59
+ command = [binary, '--browser', options.browser_name]
60
+ if options.browser_version
61
+ command << '--browser-version'
62
+ command << options.browser_version
63
+ end
64
+ if options.respond_to?(:binary) && !options.binary.nil?
65
+ command << '--browser-path'
66
+ command << options.binary.gsub('\\', '\\\\\\')
67
+ end
68
+ if options.proxy
69
+ command << '--proxy'
70
+ (command << options.proxy.ssl) || options.proxy.http
71
+ end
72
+ command
73
+ end
74
+
75
+ # @return [String] the path to the correct selenium manager
76
+ def binary
77
+ @binary ||= begin
78
+ location = ENV.fetch('SE_MANAGER_PATH', begin
79
+ directory = File.expand_path(bin_path, __FILE__)
80
+ if Platform.windows?
81
+ "#{directory}/windows/selenium-manager.exe"
82
+ elsif Platform.mac?
83
+ "#{directory}/macos/selenium-manager"
84
+ elsif Platform.linux?
85
+ "#{directory}/linux/selenium-manager"
86
+ end
87
+ end)
88
+
89
+ validate_location(location)
90
+ location
91
+ end
92
+ end
93
+
94
+ def validate_location(location)
95
+ begin
96
+ Platform.assert_file(location)
97
+ Platform.assert_executable(location)
98
+ rescue TypeError
99
+ raise Error::WebDriverError,
100
+ "Unable to locate or obtain Selenium Manager binary; #{location} is not a valid file object"
101
+ rescue Error::WebDriverError => e
102
+ raise Error::WebDriverError, "Selenium Manager binary located, but #{e.message}"
103
+ end
104
+
105
+ WebDriver.logger.debug("Selenium Manager binary found at #{location}", id: :selenium_manager)
106
+ end
107
+
108
+ def run(*command)
109
+ command += %w[--output json]
110
+ command << '--debug' if WebDriver.logger.debug?
111
+
112
+ WebDriver.logger.debug("Executing Process #{command}", id: :selenium_manager)
113
+
114
+ begin
115
+ stdout, stderr, status = Open3.capture3(*command)
116
+ rescue StandardError => e
117
+ raise Error::WebDriverError, "Unsuccessful command executed: #{command}; #{e.message}"
118
+ end
119
+
120
+ json_output = stdout.empty? ? {} : JSON.parse(stdout)
121
+ (json_output['logs'] || []).each do |log|
122
+ level = log['level'].casecmp('info').zero? ? 'debug' : log['level'].downcase
123
+ WebDriver.logger.send(level, log['message'], id: :selenium_manager)
124
+ end
125
+
126
+ result = json_output['result']
127
+ return result unless status.exitstatus.positive?
128
+
129
+ raise Error::WebDriverError, "Unsuccessful command executed: #{command}\n#{result}#{stderr}"
130
+ end
131
+ end
132
+ end # SeleniumManager
133
+ end # WebDriver
134
+ end # Selenium