selenium-webdriver 3.141.0 → 3.142.7

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.
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