selenium-webdriver 3.141.0 → 3.142.7

Sign up to get free protection for your applications and to get access to all the features.
Files changed (127) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGES +150 -0
  3. data/Gemfile +2 -0
  4. data/LICENSE +1 -1
  5. data/lib/selenium/server.rb +9 -7
  6. data/lib/selenium/webdriver/atoms/getAttribute.js +6 -7
  7. data/lib/selenium/webdriver/atoms/isDisplayed.js +60 -59
  8. data/lib/selenium/webdriver/atoms.rb +20 -1
  9. data/lib/selenium/webdriver/chrome/bridge.rb +23 -3
  10. data/lib/selenium/webdriver/chrome/driver.rb +30 -20
  11. data/lib/selenium/webdriver/chrome/options.rb +11 -7
  12. data/lib/selenium/webdriver/chrome/profile.rb +6 -5
  13. data/lib/selenium/webdriver/chrome/service.rb +13 -13
  14. data/lib/selenium/webdriver/chrome.rb +10 -4
  15. data/lib/selenium/webdriver/common/action_builder.rb +2 -0
  16. data/lib/selenium/webdriver/common/alert.rb +2 -0
  17. data/lib/selenium/webdriver/common/bridge_helper.rb +8 -5
  18. data/lib/selenium/webdriver/common/driver.rb +22 -7
  19. data/lib/selenium/webdriver/common/driver_extensions/downloads_files.rb +2 -0
  20. data/lib/selenium/webdriver/common/driver_extensions/has_addons.rb +2 -0
  21. data/lib/selenium/webdriver/common/driver_extensions/has_debugger.rb +2 -0
  22. data/lib/selenium/webdriver/common/driver_extensions/has_location.rb +3 -3
  23. data/lib/selenium/webdriver/common/driver_extensions/has_network_conditions.rb +2 -0
  24. data/lib/selenium/webdriver/common/driver_extensions/has_network_connection.rb +3 -1
  25. data/lib/selenium/webdriver/common/driver_extensions/has_permissions.rb +2 -0
  26. data/lib/selenium/webdriver/common/driver_extensions/has_remote_status.rb +2 -0
  27. data/lib/selenium/webdriver/common/driver_extensions/has_session_id.rb +2 -0
  28. data/lib/selenium/webdriver/common/driver_extensions/has_touch_screen.rb +2 -0
  29. data/lib/selenium/webdriver/common/driver_extensions/has_web_storage.rb +2 -0
  30. data/lib/selenium/webdriver/common/driver_extensions/rotatable.rb +3 -1
  31. data/lib/selenium/webdriver/common/driver_extensions/takes_screenshot.rb +2 -0
  32. data/lib/selenium/webdriver/common/driver_extensions/uploads_files.rb +3 -3
  33. data/lib/selenium/webdriver/common/element.rb +3 -1
  34. data/lib/selenium/webdriver/common/error.rb +74 -18
  35. data/lib/selenium/webdriver/common/file_reaper.rb +3 -3
  36. data/lib/selenium/webdriver/common/html5/local_storage.rb +2 -0
  37. data/lib/selenium/webdriver/common/html5/session_storage.rb +2 -0
  38. data/lib/selenium/webdriver/common/html5/shared_web_storage.rb +4 -1
  39. data/lib/selenium/webdriver/common/interactions/input_device.rb +3 -0
  40. data/lib/selenium/webdriver/common/interactions/interaction.rb +3 -0
  41. data/lib/selenium/webdriver/common/interactions/interactions.rb +3 -1
  42. data/lib/selenium/webdriver/common/interactions/key_actions.rb +2 -0
  43. data/lib/selenium/webdriver/common/interactions/key_input.rb +4 -0
  44. data/lib/selenium/webdriver/common/interactions/none_input.rb +3 -0
  45. data/lib/selenium/webdriver/common/interactions/pointer_actions.rb +2 -0
  46. data/lib/selenium/webdriver/common/interactions/pointer_input.rb +7 -0
  47. data/lib/selenium/webdriver/common/keyboard.rb +4 -1
  48. data/lib/selenium/webdriver/common/keys.rb +3 -0
  49. data/lib/selenium/webdriver/common/log_entry.rb +4 -2
  50. data/lib/selenium/webdriver/common/logger.rb +15 -40
  51. data/lib/selenium/webdriver/common/logs.rb +2 -0
  52. data/lib/selenium/webdriver/common/manager.rb +177 -0
  53. data/lib/selenium/webdriver/common/mouse.rb +3 -0
  54. data/lib/selenium/webdriver/common/navigation.rb +2 -0
  55. data/lib/selenium/webdriver/common/options.rb +28 -126
  56. data/lib/selenium/webdriver/common/platform.rb +26 -30
  57. data/lib/selenium/webdriver/common/port_prober.rb +6 -19
  58. data/lib/selenium/webdriver/common/profile_helper.rb +2 -0
  59. data/lib/selenium/webdriver/common/proxy.rb +13 -5
  60. data/lib/selenium/webdriver/common/search_context.rb +6 -8
  61. data/lib/selenium/webdriver/common/service.rb +87 -29
  62. data/lib/selenium/webdriver/common/socket_lock.rb +10 -3
  63. data/lib/selenium/webdriver/common/socket_poller.rb +26 -18
  64. data/lib/selenium/webdriver/common/target_locator.rb +6 -4
  65. data/lib/selenium/webdriver/common/timeouts.rb +2 -0
  66. data/lib/selenium/webdriver/common/touch_action_builder.rb +5 -6
  67. data/lib/selenium/webdriver/common/touch_screen.rb +4 -1
  68. data/lib/selenium/webdriver/common/w3c_action_builder.rb +3 -0
  69. data/lib/selenium/webdriver/common/{w3c_options.rb → w3c_manager.rb} +3 -1
  70. data/lib/selenium/webdriver/common/wait.rb +13 -5
  71. data/lib/selenium/webdriver/common/window.rb +2 -0
  72. data/lib/selenium/webdriver/common/zipper.rb +3 -3
  73. data/lib/selenium/webdriver/common.rb +5 -2
  74. data/lib/selenium/webdriver/edge/bridge.rb +2 -0
  75. data/lib/selenium/webdriver/edge/driver.rb +6 -13
  76. data/lib/selenium/webdriver/edge/options.rb +3 -0
  77. data/lib/selenium/webdriver/edge/service.rb +8 -12
  78. data/lib/selenium/webdriver/edge.rb +11 -5
  79. data/lib/selenium/webdriver/firefox/binary.rb +9 -8
  80. data/lib/selenium/webdriver/firefox/driver.rb +2 -0
  81. data/lib/selenium/webdriver/firefox/extension.rb +4 -4
  82. data/lib/selenium/webdriver/firefox/launcher.rb +3 -0
  83. data/lib/selenium/webdriver/firefox/legacy/driver.rb +7 -3
  84. data/lib/selenium/webdriver/firefox/marionette/bridge.rb +4 -2
  85. data/lib/selenium/webdriver/firefox/marionette/driver.rb +6 -12
  86. data/lib/selenium/webdriver/firefox/options.rb +22 -9
  87. data/lib/selenium/webdriver/firefox/profile.rb +7 -8
  88. data/lib/selenium/webdriver/firefox/profiles_ini.rb +3 -0
  89. data/lib/selenium/webdriver/firefox/service.rb +8 -19
  90. data/lib/selenium/webdriver/firefox/util.rb +2 -0
  91. data/lib/selenium/webdriver/firefox.rb +10 -4
  92. data/lib/selenium/webdriver/ie/driver.rb +5 -11
  93. data/lib/selenium/webdriver/ie/options.rb +6 -4
  94. data/lib/selenium/webdriver/ie/service.rb +8 -12
  95. data/lib/selenium/webdriver/ie.rb +10 -4
  96. data/lib/selenium/webdriver/remote/bridge.rb +8 -6
  97. data/lib/selenium/webdriver/remote/capabilities.rb +23 -10
  98. data/lib/selenium/webdriver/remote/driver.rb +2 -0
  99. data/lib/selenium/webdriver/remote/http/common.rb +11 -4
  100. data/lib/selenium/webdriver/remote/http/curb.rb +4 -2
  101. data/lib/selenium/webdriver/remote/http/default.rb +31 -25
  102. data/lib/selenium/webdriver/remote/http/persistent.rb +3 -1
  103. data/lib/selenium/webdriver/remote/oss/bridge.rb +5 -2
  104. data/lib/selenium/webdriver/remote/oss/commands.rb +106 -104
  105. data/lib/selenium/webdriver/remote/response.rb +11 -3
  106. data/lib/selenium/webdriver/remote/server_error.rb +2 -0
  107. data/lib/selenium/webdriver/remote/w3c/bridge.rb +28 -13
  108. data/lib/selenium/webdriver/remote/w3c/capabilities.rb +37 -21
  109. data/lib/selenium/webdriver/remote/w3c/commands.rb +61 -58
  110. data/lib/selenium/webdriver/remote.rb +2 -0
  111. data/lib/selenium/webdriver/safari/bridge.rb +5 -3
  112. data/lib/selenium/webdriver/safari/driver.rb +9 -11
  113. data/lib/selenium/webdriver/safari/options.rb +2 -0
  114. data/lib/selenium/webdriver/safari/service.rb +6 -25
  115. data/lib/selenium/webdriver/safari.rb +11 -4
  116. data/lib/selenium/webdriver/support/abstract_event_listener.rb +2 -0
  117. data/lib/selenium/webdriver/support/block_event_listener.rb +3 -1
  118. data/lib/selenium/webdriver/support/color.rb +11 -9
  119. data/lib/selenium/webdriver/support/escaper.rb +2 -0
  120. data/lib/selenium/webdriver/support/event_firing_bridge.rb +3 -1
  121. data/lib/selenium/webdriver/support/select.rb +19 -18
  122. data/lib/selenium/webdriver/support.rb +2 -0
  123. data/lib/selenium/webdriver/version.rb +3 -1
  124. data/lib/selenium/webdriver.rb +3 -1
  125. data/lib/selenium-webdriver.rb +2 -0
  126. data/selenium-webdriver.gemspec +15 -8
  127. metadata +86 -27
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # Licensed to the Software Freedom Conservancy (SFC) under one
2
4
  # or more contributor license agreements. See the NOTICE file
3
5
  # distributed with this work for additional information
@@ -23,25 +25,10 @@ module Selenium
23
25
  port
24
26
  end
25
27
 
26
- def self.random
27
- # TODO: Avoid this
28
- #
29
- # (a) should pick a port that's guaranteed to be free on all interfaces
30
- # (b) should pick a random port outside the ephemeral port range
31
- #
32
- WebDriver.logger.deprecate 'PortProber.random', 'PortProber.above(port)'
33
-
34
- server = TCPServer.new(Platform.localhost, 0)
35
- port = server.addr[1]
36
- server.close
37
-
38
- port
39
- end
40
-
41
- IGNORED_ERRORS = [Errno::EADDRNOTAVAIL, Errno::EAFNOSUPPORT]
42
- IGNORED_ERRORS << Errno::EBADF if Platform.cygwin?
43
- IGNORED_ERRORS << Errno::EACCES if Platform.windows?
44
- IGNORED_ERRORS.freeze
28
+ IGNORED_ERRORS = [Errno::EADDRNOTAVAIL, Errno::EAFNOSUPPORT].tap { |arr|
29
+ arr << Errno::EBADF if Platform.cygwin?
30
+ arr << Errno::EACCES if Platform.windows?
31
+ }.freeze
45
32
 
46
33
  def self.free?(port)
47
34
  Platform.interfaces.each do |host|
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # Licensed to the Software Freedom Conservancy (SFC) under one
2
4
  # or more contributor license agreements. See the NOTICE file
3
5
  # distributed with this work for additional information
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # Licensed to the Software Freedom Conservancy (SFC) under one
2
4
  # or more contributor license agreements. See the NOTICE file
3
5
  # distributed with this work for additional information
@@ -35,7 +37,8 @@ module Selenium
35
37
  auto_detect: 'autodetect',
36
38
  socks: 'socksProxy',
37
39
  socks_username: 'socksUsername',
38
- socks_password: 'socksPassword'}.freeze
40
+ socks_password: 'socksPassword',
41
+ socks_version: 'socksVersion'}.freeze
39
42
 
40
43
  ALLOWED.each_key { |t| attr_reader t }
41
44
 
@@ -64,6 +67,7 @@ module Selenium
64
67
  end
65
68
 
66
69
  return if not_allowed.empty?
70
+
67
71
  raise ArgumentError, "unknown option#{'s' if not_allowed.size != 1}: #{not_allowed.inspect}"
68
72
  end
69
73
 
@@ -117,10 +121,13 @@ module Selenium
117
121
  @socks_password = value
118
122
  end
119
123
 
124
+ def socks_version=(value)
125
+ self.type = :manual
126
+ @socks_version = value
127
+ end
128
+
120
129
  def type=(type)
121
- unless TYPES.key? type
122
- raise ArgumentError, "invalid proxy type: #{type.inspect}, expected one of #{TYPES.keys.inspect}"
123
- end
130
+ raise ArgumentError, "invalid proxy type: #{type.inspect}, expected one of #{TYPES.keys.inspect}" unless TYPES.key? type
124
131
 
125
132
  if defined?(@type) && type != @type
126
133
  raise ArgumentError, "incompatible proxy type #{type.inspect} (already set to #{@type.inspect})"
@@ -140,7 +147,8 @@ module Selenium
140
147
  'autodetect' => auto_detect,
141
148
  'socksProxy' => socks,
142
149
  'socksUsername' => socks_username,
143
- 'socksPassword' => socks_password
150
+ 'socksPassword' => socks_password,
151
+ 'socksVersion' => socks_version
144
152
  }.delete_if { |_k, v| v.nil? }
145
153
 
146
154
  json_result if json_result.length > 1
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # Licensed to the Software Freedom Conservancy (SFC) under one
2
4
  # or more contributor license agreements. See the NOTICE file
3
5
  # distributed with this work for additional information
@@ -58,7 +60,7 @@ module Selenium
58
60
  raise ArgumentError, "cannot find element by #{how.inspect}" unless by
59
61
 
60
62
  bridge.find_element_by by, what.to_s, ref
61
- rescue Selenium::WebDriver::Error::TimeOutError
63
+ rescue Selenium::WebDriver::Error::TimeoutError
62
64
  # Implicit Wait times out in Edge
63
65
  raise Selenium::WebDriver::Error::NoSuchElementError
64
66
  end
@@ -76,7 +78,7 @@ module Selenium
76
78
  raise ArgumentError, "cannot find elements by #{how.inspect}" unless by
77
79
 
78
80
  bridge.find_elements_by by, what.to_s, ref
79
- rescue Selenium::WebDriver::Error::TimeOutError
81
+ rescue Selenium::WebDriver::Error::TimeoutError
80
82
  # Implicit Wait times out in Edge
81
83
  []
82
84
  end
@@ -90,15 +92,11 @@ module Selenium
90
92
  when 1
91
93
  arg = args.first
92
94
 
93
- unless arg.respond_to?(:shift)
94
- raise ArgumentError, "expected #{arg.inspect}:#{arg.class} to respond to #shift"
95
- end
95
+ raise ArgumentError, "expected #{arg.inspect}:#{arg.class} to respond to #shift" unless arg.respond_to?(:shift)
96
96
 
97
97
  # this will be a single-entry hash, so use #shift over #first or #[]
98
98
  arr = arg.dup.shift
99
- unless arr.size == 2
100
- raise ArgumentError, "expected #{arr.inspect} to have 2 elements"
101
- end
99
+ raise ArgumentError, "expected #{arr.inspect} to have 2 elements" unless arr.size == 2
102
100
 
103
101
  arr
104
102
  else
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # Licensed to the Software Freedom Conservancy (SFC) under one
2
4
  # or more contributor license agreements. See the NOTICE file
3
5
  # distributed with this work for additional information
@@ -21,50 +23,87 @@ module Selenium
21
23
  # Base class implementing default behavior of service object,
22
24
  # responsible for starting and stopping driver implementations.
23
25
  #
24
- # Subclasses must implement the following private methods:
25
- # * #start_process
26
- # * #stop_server
27
- # * #cannot_connect_error_text
28
- #
29
- # @api private
30
- #
31
26
 
32
27
  class Service
33
- START_TIMEOUT = 20
28
+ START_TIMEOUT = 20
34
29
  SOCKET_LOCK_TIMEOUT = 45
35
- STOP_TIMEOUT = 20
30
+ STOP_TIMEOUT = 20
36
31
 
32
+ @default_port = nil
33
+ @driver_path = nil
37
34
  @executable = nil
38
35
  @missing_text = nil
39
36
 
40
37
  class << self
41
- attr_reader :executable, :missing_text
38
+ attr_reader :default_port, :driver_path, :executable, :missing_text, :shutdown_supported
39
+
40
+ def chrome(**opts)
41
+ Chrome::Service.new(**opts)
42
+ end
43
+
44
+ def firefox(**opts)
45
+ binary_path = Firefox::Binary.path
46
+ args = opts.delete(:args)
47
+ case args
48
+ when Hash
49
+ args[:binary] ||= binary_path
50
+ opts[:args] = args
51
+ when Array
52
+ opts[:args] = ["--binary=#{binary_path}"]
53
+ opts[:args] += args
54
+ else
55
+ opts[:args] = ["--binary=#{binary_path}"]
56
+ end
57
+
58
+ Firefox::Service.new(**opts)
59
+ end
60
+
61
+ def ie(**opts)
62
+ IE::Service.new(**opts)
63
+ end
64
+ alias_method :internet_explorer, :ie
65
+
66
+ def edge(**opts)
67
+ Edge::Service.new(**opts)
68
+ end
69
+
70
+ def safari(**opts)
71
+ Safari::Service.new(**opts)
72
+ end
73
+
74
+ def driver_path=(path)
75
+ Platform.assert_executable path if path.is_a?(String)
76
+ @driver_path = path
77
+ end
42
78
  end
43
79
 
44
80
  attr_accessor :host
81
+ attr_reader :executable_path
45
82
 
46
- def initialize(executable_path, port, driver_opts)
47
- @executable_path = binary_path(executable_path)
48
- @host = Platform.localhost
49
- @port = Integer(port)
50
- @extra_args = extract_service_args(driver_opts)
83
+ #
84
+ # End users should use a class method for the desired driver, rather than using this directly.
85
+ #
86
+ # @api private
87
+ #
51
88
 
52
- raise Error::WebDriverError, "invalid port: #{@port}" if @port < 1
53
- end
89
+ def initialize(path: nil, port: nil, args: nil)
90
+ path ||= self.class.driver_path
91
+ port ||= self.class.default_port
92
+ args ||= []
54
93
 
55
- def binary_path(path)
56
- path = Platform.find_binary(self.class.executable) if path.nil?
57
- raise Error::WebDriverError, self.class.missing_text unless path
58
- Platform.assert_executable path
59
- path
94
+ @executable_path = binary_path(path)
95
+ @host = Platform.localhost
96
+ @port = Integer(port)
97
+
98
+ @extra_args = args.is_a?(Hash) ? extract_service_args(args) : args
99
+
100
+ raise Error::WebDriverError, "invalid port: #{@port}" if @port < 1
60
101
  end
61
102
 
62
103
  def start
63
- if process_running?
64
- raise "already started: #{uri.inspect} #{@executable_path.inspect}"
65
- end
104
+ raise "already started: #{uri.inspect} #{@executable_path.inspect}" if process_running?
66
105
 
67
- Platform.exit_hook { stop } # make sure we don't leave the server running
106
+ Platform.exit_hook(&method(:stop)) # make sure we don't leave the server running
68
107
 
69
108
  socket_lock.locked do
70
109
  find_free_port
@@ -74,9 +113,12 @@ module Selenium
74
113
  end
75
114
 
76
115
  def stop
116
+ return unless self.class.shutdown_supported
117
+
77
118
  stop_server
78
119
  @process.poll_for_exit STOP_TIMEOUT
79
120
  rescue ChildProcess::TimeoutError
121
+ nil # noop
80
122
  ensure
81
123
  stop_process
82
124
  end
@@ -87,6 +129,16 @@ module Selenium
87
129
 
88
130
  private
89
131
 
132
+ def binary_path(path = nil)
133
+ path = path.call if path.is_a?(Proc)
134
+ path ||= Platform.find_binary(self.class.executable)
135
+
136
+ raise Error::WebDriverError, self.class.missing_text unless path
137
+
138
+ Platform.assert_executable path
139
+ path
140
+ end
141
+
90
142
  def build_process(*command)
91
143
  WebDriver.logger.debug("Executing Process #{command}")
92
144
  @process = ChildProcess.build(*command)
@@ -114,22 +166,27 @@ module Selenium
114
166
  end
115
167
 
116
168
  def start_process
117
- raise NotImplementedError, 'subclass responsibility'
169
+ @process = build_process(@executable_path, "--port=#{@port}", *@extra_args)
170
+ # Note: this is a bug only in Windows 7
171
+ @process.leader = true unless Platform.windows?
172
+ @process.start
118
173
  end
119
174
 
120
175
  def stop_process
121
176
  return if process_exited?
177
+
122
178
  @process.stop STOP_TIMEOUT
123
179
  @process.io.stdout.close if Platform.jruby? && !WebDriver.logger.debug?
124
180
  end
125
181
 
126
182
  def stop_server
127
183
  return if process_exited?
184
+
128
185
  connect_to_server { |http| http.get('/shutdown') }
129
186
  end
130
187
 
131
188
  def process_running?
132
- defined?(@process) && @process && @process.alive?
189
+ defined?(@process) && @process&.alive?
133
190
  end
134
191
 
135
192
  def process_exited?
@@ -139,11 +196,12 @@ module Selenium
139
196
  def connect_until_stable
140
197
  socket_poller = SocketPoller.new @host, @port, START_TIMEOUT
141
198
  return if socket_poller.connected?
199
+
142
200
  raise Error::WebDriverError, cannot_connect_error_text
143
201
  end
144
202
 
145
203
  def cannot_connect_error_text
146
- raise NotImplementedError, 'subclass responsibility'
204
+ "unable to connect to #{self.class.executable} #{@host}:#{@port}"
147
205
  end
148
206
 
149
207
  def socket_lock
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # Licensed to the Software Freedom Conservancy (SFC) under one
2
4
  # or more contributor license agreements. See the NOTICE file
3
5
  # distributed with this work for additional information
@@ -45,16 +47,21 @@ module Selenium
45
47
  private
46
48
 
47
49
  def lock
48
- max_time = Time.now + @timeout
50
+ max_time = current_time + @timeout
49
51
 
50
- sleep 0.1 until can_lock? || Time.now >= max_time
52
+ sleep 0.1 until can_lock? || current_time >= max_time
51
53
 
52
54
  return if did_lock?
55
+
53
56
  raise Error::WebDriverError, "unable to bind to locking port #{@port} within #{@timeout} seconds"
54
57
  end
55
58
 
59
+ def current_time
60
+ Process.clock_gettime(Process::CLOCK_MONOTONIC)
61
+ end
62
+
56
63
  def release
57
- @server && @server.close
64
+ @server&.close
58
65
  end
59
66
 
60
67
  def can_lock?
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # Licensed to the Software Freedom Conservancy (SFC) under one
2
4
  # or more contributor license agreements. See the NOTICE file
3
5
  # distributed with this work for additional information
@@ -54,12 +56,14 @@ module Selenium
54
56
 
55
57
  CONNECT_TIMEOUT = 5
56
58
 
57
- NOT_CONNECTED_ERRORS = [Errno::ECONNREFUSED, Errno::ENOTCONN, SocketError]
58
- NOT_CONNECTED_ERRORS << Errno::EPERM if Platform.cygwin?
59
+ NOT_CONNECTED_ERRORS = [Errno::ECONNREFUSED, Errno::ENOTCONN, SocketError].tap { |arr|
60
+ arr << Errno::EPERM if Platform.cygwin?
61
+ }.freeze
59
62
 
60
- CONNECTED_ERRORS = [Errno::EISCONN]
61
- CONNECTED_ERRORS << Errno::EINVAL if Platform.windows?
62
- CONNECTED_ERRORS << Errno::EALREADY if Platform.wsl?
63
+ CONNECTED_ERRORS = [Errno::EISCONN].tap { |arr|
64
+ arr << Errno::EINVAL if Platform.windows?
65
+ arr << Errno::EALREADY if Platform.wsl?
66
+ }.freeze
63
67
 
64
68
  if Platform.jruby?
65
69
  # we use a plain TCPSocket here since JRuby has issues select()ing on a connecting socket
@@ -79,7 +83,7 @@ module Selenium
79
83
  begin
80
84
  sock.connect_nonblock sockaddr
81
85
  rescue Errno::EINPROGRESS
82
- retry if IO.select(nil, [sock], nil, CONNECT_TIMEOUT)
86
+ retry if socket_writable?(sock) && conn_completed?(sock)
83
87
  raise Errno::ECONNREFUSED
84
88
  rescue *CONNECTED_ERRORS
85
89
  # yay!
@@ -88,30 +92,34 @@ module Selenium
88
92
  sock.close
89
93
  true
90
94
  rescue *NOT_CONNECTED_ERRORS
91
- sock.close if sock
95
+ sock&.close
92
96
  WebDriver.logger.debug("polling for socket on #{[@host, @port].inspect}")
93
97
  false
94
98
  end
95
99
  end
96
100
 
101
+ def socket_writable?(sock)
102
+ IO.select(nil, [sock], nil, CONNECT_TIMEOUT)
103
+ end
104
+
105
+ def conn_completed?(sock)
106
+ sock.getsockopt(Socket::SOL_SOCKET, Socket::SO_ERROR).int.zero?
107
+ end
108
+
97
109
  def with_timeout
98
- max_time = time_now + @timeout
110
+ max_time = current_time + @timeout
99
111
 
100
- (
112
+ until current_time > max_time
101
113
  return true if yield
102
- wait
103
- ) until time_now > max_time
104
114
 
105
- false
106
- end
115
+ sleep @interval
116
+ end
107
117
 
108
- def wait
109
- sleep @interval
118
+ false
110
119
  end
111
120
 
112
- # for testability
113
- def time_now
114
- Time.now
121
+ def current_time
122
+ Process.clock_gettime(Process::CLOCK_MONOTONIC)
115
123
  end
116
124
  end # SocketPoller
117
125
  end # WebDriver
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # Licensed to the Software Freedom Conservancy (SFC) under one
2
4
  # or more contributor license agreements. See the NOTICE file
3
5
  # distributed with this work for additional information
@@ -55,10 +57,10 @@ module Selenium
55
57
  def window(id)
56
58
  if block_given?
57
59
  original = begin
58
- @bridge.window_handle
59
- rescue Error::NoSuchWindowError
60
- nil
61
- end
60
+ @bridge.window_handle
61
+ rescue Error::NoSuchWindowError
62
+ nil
63
+ end
62
64
 
63
65
  unless @bridge.window_handles.include? id
64
66
  raise Error::NoSuchWindowError, "The specified identifier '#{id}' is not found in the window handle list"
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # Licensed to the Software Freedom Conservancy (SFC) under one
2
4
  # or more contributor license agreements. See the NOTICE file
3
5
  # distributed with this work for additional information
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # Licensed to the Software Freedom Conservancy (SFC) under one
2
4
  # or more contributor license agreements. See the NOTICE file
3
5
  # distributed with this work for additional information
@@ -23,23 +25,20 @@ module Selenium
23
25
  #
24
26
 
25
27
  def initialize(mouse, keyboard, touch_screen)
28
+ WebDriver.logger.deprecate(self.class.name)
26
29
  super(mouse, keyboard)
27
30
  @devices[:touch_screen] = touch_screen
28
31
  end
29
32
 
30
33
  def scroll(*args)
31
- unless [2, 3].include? args.size
32
- raise ArgumentError, "wrong number of arguments, expected 2..3, got #{args.size}"
33
- end
34
+ raise ArgumentError, "wrong number of arguments, expected 2..3, got #{args.size}" unless [2, 3].include? args.size
34
35
 
35
36
  @actions << [:touch_screen, :scroll, args]
36
37
  self
37
38
  end
38
39
 
39
40
  def flick(*args)
40
- unless [2, 4].include? args.size
41
- raise ArgumentError, "wrong number of arguments, expected 2 or 4, got #{args.size}"
42
- end
41
+ raise ArgumentError, "wrong number of arguments, expected 2 or 4, got #{args.size}" unless [2, 4].include? args.size
43
42
 
44
43
  @actions << [:touch_screen, :flick, args]
45
44
  self
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # Licensed to the Software Freedom Conservancy (SFC) under one
2
4
  # or more contributor license agreements. See the NOTICE file
3
5
  # distributed with this work for additional information
@@ -82,7 +84,7 @@ module Selenium
82
84
 
83
85
  assert_element element
84
86
 
85
- if (speed.is_a?(String) || speed.is_a?(Symbol)) && FLICK_SPEED.keys.include?(speed.to_sym)
87
+ if (speed.is_a?(String) || speed.is_a?(Symbol)) && FLICK_SPEED.key?(speed.to_sym)
86
88
  WebDriver.logger.deprecate "Passing #{speed.inspect} speed",
87
89
  "Integer or Selenium::WebDriver::TouchScreen::FLICK_SPEED[:#{speed}]"
88
90
  speed = FLICK_SPEED[speed.to_sym]
@@ -113,6 +115,7 @@ module Selenium
113
115
 
114
116
  def assert_element(element)
115
117
  return if element.is_a? Element
118
+
116
119
  raise TypeError, "expected #{Element}, got #{element.inspect}:#{element.class}"
117
120
  end
118
121
  end # TouchScreen
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # Licensed to the Software Freedom Conservancy (SFC) under one
2
4
  # or more contributor license agreements. See the NOTICE file
3
5
  # distributed with this work for additional information
@@ -190,6 +192,7 @@ module Selenium
190
192
 
191
193
  def tick(*action_devices)
192
194
  return if @async
195
+
193
196
  @devices.each { |device| device.create_pause unless action_devices.include? device }
194
197
  end
195
198
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # Licensed to the Software Freedom Conservancy (SFC) under one
2
4
  # or more contributor license agreements. See the NOTICE file
3
5
  # distributed with this work for additional information
@@ -17,7 +19,7 @@
17
19
 
18
20
  module Selenium
19
21
  module WebDriver
20
- class W3COptions < Options
22
+ class W3CManager < Manager
21
23
 
22
24
  #
23
25
  # Get the cookie with the given name
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # Licensed to the Software Freedom Conservancy (SFC) under one
2
4
  # or more contributor license agreements. See the NOTICE file
3
5
  # distributed with this work for additional information
@@ -41,15 +43,15 @@ module Selenium
41
43
  #
42
44
  # Wait until the given block returns a true value.
43
45
  #
44
- # @raise [Error::TimeOutError]
46
+ # @raise [Error::TimeoutError]
45
47
  # @return [Object] the result of the block
46
48
  #
47
49
 
48
50
  def until
49
- end_time = Time.now + @timeout
51
+ end_time = current_time + @timeout
50
52
  last_error = nil
51
53
 
52
- until Time.now > end_time
54
+ until current_time > end_time
53
55
  begin
54
56
  result = yield
55
57
  return result if result
@@ -63,12 +65,18 @@ module Selenium
63
65
  msg = if @message
64
66
  @message.dup
65
67
  else
66
- "timed out after #{@timeout} seconds"
68
+ +"timed out after #{@timeout} seconds"
67
69
  end
68
70
 
69
71
  msg << " (#{last_error.message})" if last_error
70
72
 
71
- raise Error::TimeOutError, msg
73
+ raise Error::TimeoutError, msg
74
+ end
75
+
76
+ private
77
+
78
+ def current_time
79
+ Process.clock_gettime(Process::CLOCK_MONOTONIC)
72
80
  end
73
81
  end # Wait
74
82
  end # WebDriver
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # Licensed to the Software Freedom Conservancy (SFC) under one
2
4
  # or more contributor license agreements. See the NOTICE file
3
5
  # distributed with this work for additional information
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # Licensed to the Software Freedom Conservancy (SFC) under one
2
4
  # or more contributor license agreements. See the NOTICE file
3
5
  # distributed with this work for additional information
@@ -50,9 +52,7 @@ module Selenium
50
52
  def zip(path)
51
53
  with_tmp_zip do |zip|
52
54
  ::Find.find(path) do |file|
53
- unless File.directory?(file)
54
- add_zip_entry zip, file, file.sub("#{path}/", '')
55
- end
55
+ add_zip_entry zip, file, file.sub("#{path}/", '') unless File.directory?(file)
56
56
  end
57
57
 
58
58
  zip.commit
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # Licensed to the Software Freedom Conservancy (SFC) under one
2
4
  # or more contributor license agreements. See the NOTICE file
3
5
  # distributed with this work for additional information
@@ -36,8 +38,8 @@ require 'selenium/webdriver/common/timeouts'
36
38
  require 'selenium/webdriver/common/window'
37
39
  require 'selenium/webdriver/common/logger'
38
40
  require 'selenium/webdriver/common/logs'
39
- require 'selenium/webdriver/common/options'
40
- require 'selenium/webdriver/common/w3c_options'
41
+ require 'selenium/webdriver/common/manager'
42
+ require 'selenium/webdriver/common/w3c_manager'
41
43
  require 'selenium/webdriver/common/search_context'
42
44
  require 'selenium/webdriver/common/action_builder'
43
45
  require 'selenium/webdriver/common/interactions/key_actions'
@@ -70,5 +72,6 @@ require 'selenium/webdriver/common/interactions/pointer_input'
70
72
  require 'selenium/webdriver/common/keys'
71
73
  require 'selenium/webdriver/common/bridge_helper'
72
74
  require 'selenium/webdriver/common/profile_helper'
75
+ require 'selenium/webdriver/common/options'
73
76
  require 'selenium/webdriver/common/driver'
74
77
  require 'selenium/webdriver/common/element'
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # Licensed to the Software Freedom Conservancy (SFC) under one
2
4
  # or more contributor license agreements. See the NOTICE file
3
5
  # distributed with this work for additional information