selenium-webdriver 4.0.0.alpha3 → 4.0.0.alpha4
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 +50 -1
- data/lib/selenium/server.rb +1 -1
- data/lib/selenium/webdriver.rb +2 -0
- data/lib/selenium/webdriver/atoms/findElements.js +122 -0
- data/lib/selenium/webdriver/atoms/getAttribute.js +84 -7
- data/lib/selenium/webdriver/atoms/isDisplayed.js +75 -77
- data/lib/selenium/webdriver/chrome.rb +4 -2
- data/lib/selenium/webdriver/chrome/driver.rb +1 -16
- data/lib/selenium/webdriver/chrome/options.rb +1 -1
- data/lib/selenium/webdriver/chrome/service.rb +0 -4
- data/lib/selenium/webdriver/common.rb +1 -0
- data/lib/selenium/webdriver/common/driver.rb +25 -5
- data/lib/selenium/webdriver/common/driver_extensions/has_devtools.rb +38 -0
- data/lib/selenium/webdriver/common/driver_extensions/takes_screenshot.rb +2 -1
- data/lib/selenium/webdriver/common/logger.rb +47 -15
- data/lib/selenium/webdriver/common/options.rb +2 -1
- data/lib/selenium/webdriver/common/platform.rb +3 -0
- data/lib/selenium/webdriver/common/port_prober.rb +2 -2
- data/lib/selenium/webdriver/common/proxy.rb +0 -0
- data/lib/selenium/webdriver/common/search_context.rb +3 -2
- data/lib/selenium/webdriver/common/service.rb +0 -13
- data/lib/selenium/webdriver/common/socket_lock.rb +2 -2
- data/lib/selenium/webdriver/common/wait.rb +1 -1
- data/lib/selenium/webdriver/edge.rb +4 -2
- data/lib/selenium/webdriver/edge_chrome/driver.rb +1 -1
- data/lib/selenium/webdriver/edge_chrome/service.rb +0 -4
- data/lib/selenium/webdriver/edge_html/driver.rb +1 -15
- data/lib/selenium/webdriver/edge_html/options.rb +1 -1
- data/lib/selenium/webdriver/edge_html/service.rb +1 -5
- data/lib/selenium/webdriver/firefox.rb +10 -4
- data/lib/selenium/webdriver/firefox/driver.rb +0 -16
- data/lib/selenium/webdriver/firefox/options.rb +4 -1
- data/lib/selenium/webdriver/firefox/profile.rb +4 -77
- data/lib/selenium/webdriver/firefox/service.rb +0 -4
- data/lib/selenium/webdriver/ie.rb +4 -2
- data/lib/selenium/webdriver/ie/driver.rb +0 -15
- data/lib/selenium/webdriver/ie/service.rb +5 -9
- data/lib/selenium/webdriver/remote/bridge.rb +31 -29
- data/lib/selenium/webdriver/remote/capabilities.rb +1 -0
- data/lib/selenium/webdriver/remote/driver.rb +6 -12
- data/lib/selenium/webdriver/remote/http/default.rb +3 -3
- data/lib/selenium/webdriver/safari.rb +4 -2
- data/lib/selenium/webdriver/safari/driver.rb +0 -16
- data/lib/selenium/webdriver/safari/service.rb +0 -4
- data/lib/selenium/webdriver/support.rb +1 -0
- data/lib/selenium/webdriver/support/event_firing_bridge.rb +1 -1
- data/lib/selenium/webdriver/support/relative_locator.rb +51 -0
- data/lib/selenium/webdriver/version.rb +1 -1
- data/selenium-webdriver.gemspec +4 -3
- metadata +24 -15
- data/lib/selenium/webdriver/firefox/binary.rb +0 -110
- data/lib/selenium/webdriver/firefox/extension/prefs.json +0 -69
@@ -30,13 +30,15 @@ module Selenium
|
|
30
30
|
|
31
31
|
def self.driver_path=(path)
|
32
32
|
WebDriver.logger.deprecate 'Selenium::WebDriver::Chrome#driver_path=',
|
33
|
-
'Selenium::WebDriver::Chrome::Service#driver_path='
|
33
|
+
'Selenium::WebDriver::Chrome::Service#driver_path=',
|
34
|
+
id: :driver_path
|
34
35
|
Selenium::WebDriver::Chrome::Service.driver_path = path
|
35
36
|
end
|
36
37
|
|
37
38
|
def self.driver_path
|
38
39
|
WebDriver.logger.deprecate 'Selenium::WebDriver::Chrome#driver_path',
|
39
|
-
'Selenium::WebDriver::Chrome::Service#driver_path'
|
40
|
+
'Selenium::WebDriver::Chrome::Service#driver_path',
|
41
|
+
id: :driver_path
|
40
42
|
Selenium::WebDriver::Chrome::Service.driver_path
|
41
43
|
end
|
42
44
|
|
@@ -32,22 +32,7 @@ module Selenium
|
|
32
32
|
include DriverExtensions::HasLocation
|
33
33
|
include DriverExtensions::TakesScreenshot
|
34
34
|
include DriverExtensions::DownloadsFiles
|
35
|
-
|
36
|
-
def initialize(opts = {})
|
37
|
-
opts[:desired_capabilities] ||= Remote::Capabilities.send(browser)
|
38
|
-
|
39
|
-
opts[:url] ||= service_url(opts)
|
40
|
-
|
41
|
-
listener = opts.delete(:listener)
|
42
|
-
desired_capabilities = opts.delete(:desired_capabilities)
|
43
|
-
options = opts.delete(:options)
|
44
|
-
|
45
|
-
@bridge = Remote::Bridge.new(opts)
|
46
|
-
@bridge.extend Bridge
|
47
|
-
@bridge.create_session(desired_capabilities, options)
|
48
|
-
|
49
|
-
super(@bridge, listener: listener)
|
50
|
-
end
|
35
|
+
include DriverExtensions::HasDevTools
|
51
36
|
|
52
37
|
def browser
|
53
38
|
:chrome
|
@@ -169,7 +169,7 @@ module Selenium
|
|
169
169
|
# options = Selenium::WebDriver::Chrome::Options.new
|
170
170
|
# options.add_emulation(device_metrics: {width: 400, height: 800, pixelRatio: 1, touch: true})
|
171
171
|
#
|
172
|
-
# @param [Hash] opts the pre-defined options for adding
|
172
|
+
# @param [Hash] opts the pre-defined options for adding mobile emulation values
|
173
173
|
# @option opts [String] :device_name A valid device name from the Chrome DevTools Emulation panel
|
174
174
|
# @option opts [Hash] :device_metrics Hash containing width, height, pixelRatio, touch
|
175
175
|
# @option opts [String] :user_agent Full user agent
|
@@ -62,6 +62,7 @@ require 'selenium/webdriver/common/driver_extensions/has_permissions'
|
|
62
62
|
require 'selenium/webdriver/common/driver_extensions/has_debugger'
|
63
63
|
require 'selenium/webdriver/common/driver_extensions/uploads_files'
|
64
64
|
require 'selenium/webdriver/common/driver_extensions/has_addons'
|
65
|
+
require 'selenium/webdriver/common/driver_extensions/has_devtools'
|
65
66
|
require 'selenium/webdriver/common/keys'
|
66
67
|
require 'selenium/webdriver/common/profile_helper'
|
67
68
|
require 'selenium/webdriver/common/options'
|
@@ -71,10 +71,10 @@ module Selenium
|
|
71
71
|
# @api private
|
72
72
|
#
|
73
73
|
|
74
|
-
def initialize(bridge, listener: nil)
|
74
|
+
def initialize(bridge: nil, listener: nil, **opts)
|
75
75
|
@service = nil
|
76
|
-
|
77
|
-
@bridge = Support::EventFiringBridge.new(bridge, listener)
|
76
|
+
bridge ||= create_bridge(opts)
|
77
|
+
@bridge = listener ? Support::EventFiringBridge.new(bridge, listener) : bridge
|
78
78
|
end
|
79
79
|
|
80
80
|
def inspect
|
@@ -276,7 +276,7 @@ module Selenium
|
|
276
276
|
end
|
277
277
|
|
278
278
|
def browser
|
279
|
-
bridge
|
279
|
+
bridge&.browser
|
280
280
|
end
|
281
281
|
|
282
282
|
def capabilities
|
@@ -294,12 +294,32 @@ module Selenium
|
|
294
294
|
|
295
295
|
attr_reader :bridge
|
296
296
|
|
297
|
+
def create_bridge(**opts)
|
298
|
+
opts[:url] ||= service_url(opts)
|
299
|
+
|
300
|
+
desired_capabilities = opts.delete(:desired_capabilities) || Remote::Capabilities.send(browser || :new)
|
301
|
+
options = opts.delete(:options)
|
302
|
+
|
303
|
+
bridge = Remote::Bridge.new(http_client: opts.delete(:http_client), url: opts.delete(:url))
|
304
|
+
raise ArgumentError, "Unable to create a driver with parameters: #{opts}" unless opts.empty?
|
305
|
+
|
306
|
+
namespacing = self.class.to_s.split('::')
|
307
|
+
|
308
|
+
if Object.const_defined?("#{namespacing[0..-2].join('::')}::Bridge") && !namespacing.include?('Remote')
|
309
|
+
bridge.extend Object.const_get("#{namespacing[0, namespacing.length - 1].join('::')}::Bridge")
|
310
|
+
end
|
311
|
+
|
312
|
+
bridge.create_session(desired_capabilities, options)
|
313
|
+
bridge
|
314
|
+
end
|
315
|
+
|
297
316
|
def service_url(opts)
|
298
317
|
@service = opts.delete(:service)
|
299
318
|
%i[driver_opts driver_path port].each do |key|
|
300
319
|
next unless opts.key? key
|
301
320
|
|
302
|
-
WebDriver.logger.deprecate(":#{key}", ':service with an instance of Selenium::WebDriver::Service'
|
321
|
+
WebDriver.logger.deprecate(":#{key}", ':service with an instance of Selenium::WebDriver::Service',
|
322
|
+
id: "service_#{key}".to_sym)
|
303
323
|
end
|
304
324
|
@service ||= Service.send(browser,
|
305
325
|
args: opts.delete(:driver_opts),
|
@@ -0,0 +1,38 @@
|
|
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 DriverExtensions
|
23
|
+
module HasDevTools
|
24
|
+
|
25
|
+
#
|
26
|
+
# Retrieves connection to DevTools.
|
27
|
+
#
|
28
|
+
# @return [DevTools]
|
29
|
+
#
|
30
|
+
|
31
|
+
def devtools
|
32
|
+
@devtools ||= DevTools.new(capabilities['goog:chromeOptions']['debuggerAddress'])
|
33
|
+
end
|
34
|
+
|
35
|
+
end # HasDevTools
|
36
|
+
end # DriverExtensions
|
37
|
+
end # WebDriver
|
38
|
+
end # Selenium
|
@@ -35,7 +35,8 @@ module Selenium
|
|
35
35
|
extension = File.extname(png_path).downcase
|
36
36
|
if extension != '.png'
|
37
37
|
WebDriver.logger.warn "name used for saved screenshot does not match file type. "\
|
38
|
-
"It should end with .png extension"
|
38
|
+
"It should end with .png extension",
|
39
|
+
id: :screenshot
|
39
40
|
end
|
40
41
|
File.open(png_path, 'wb') { |f| f << screenshot_as(:png) }
|
41
42
|
end
|
@@ -45,8 +45,12 @@ module Selenium
|
|
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,60 @@ 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<Sybmol>] id
|
112
|
+
# @yield appends additional message to end of provided template
|
81
113
|
#
|
82
|
-
def deprecate(old, new = nil)
|
83
|
-
|
114
|
+
def deprecate(old, new = nil, id: [], &block)
|
115
|
+
id = Array(id)
|
116
|
+
return if @ignored.include?(:deprecations) || (@ignored & id).any?
|
117
|
+
|
118
|
+
ids = id.empty? ? '' : "[#{id.map(&:inspect).join(', ')}] "
|
119
|
+
|
120
|
+
message = +"[DEPRECATION] #{ids}#{old} is deprecated"
|
84
121
|
message << if new
|
85
122
|
". Use #{new} instead."
|
86
123
|
else
|
87
|
-
' and will be removed in
|
124
|
+
' and will be removed in a future release.'
|
88
125
|
end
|
89
|
-
|
90
|
-
warn message
|
126
|
+
warn message, &block
|
91
127
|
end
|
92
128
|
|
93
129
|
private
|
94
130
|
|
95
|
-
def create_logger(
|
96
|
-
logger = ::Logger.new(
|
97
|
-
logger.progname =
|
131
|
+
def create_logger(name)
|
132
|
+
logger = ::Logger.new($stdout)
|
133
|
+
logger.progname = name
|
98
134
|
logger.level = default_level
|
99
135
|
logger.formatter = proc do |severity, time, progname, msg|
|
100
136
|
"#{time.strftime('%F %T')} #{severity} #{progname} #{msg}\n"
|
@@ -104,11 +140,7 @@ module Selenium
|
|
104
140
|
end
|
105
141
|
|
106
142
|
def default_level
|
107
|
-
|
108
|
-
:debug
|
109
|
-
else
|
110
|
-
:warn
|
111
|
-
end
|
143
|
+
$DEBUG || ENV.key?('DEBUG') ? :debug : :warn
|
112
144
|
end
|
113
145
|
end # Logger
|
114
146
|
end # WebDriver
|
@@ -25,7 +25,8 @@ module Selenium
|
|
25
25
|
def initialize(options: nil, **opts)
|
26
26
|
@options = if options
|
27
27
|
WebDriver.logger.deprecate(":options as keyword for initializing #{self.class}",
|
28
|
-
"custom values directly in #new constructor"
|
28
|
+
"custom values directly in #new constructor",
|
29
|
+
id: :options_options)
|
29
30
|
opts.merge(options)
|
30
31
|
else
|
31
32
|
opts
|
@@ -34,8 +34,8 @@ module Selenium
|
|
34
34
|
Platform.interfaces.each do |host|
|
35
35
|
begin
|
36
36
|
TCPServer.new(host, port).close
|
37
|
-
rescue *IGNORED_ERRORS =>
|
38
|
-
WebDriver.logger.debug("port prober could not bind to #{host}:#{port} (#{
|
37
|
+
rescue *IGNORED_ERRORS => e
|
38
|
+
WebDriver.logger.debug("port prober could not bind to #{host}:#{port} (#{e.message})")
|
39
39
|
# ignored - some machines appear unable to bind to some of their interfaces
|
40
40
|
end
|
41
41
|
end
|
File without changes
|
@@ -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,7 +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
|
+
bridge.find_element_by by, what, ref
|
63
64
|
rescue Selenium::WebDriver::Error::TimeoutError
|
64
65
|
# Implicit Wait times out in Edge
|
65
66
|
raise Selenium::WebDriver::Error::NoSuchElementError
|
@@ -77,7 +78,7 @@ module Selenium
|
|
77
78
|
by = FINDERS[how.to_sym]
|
78
79
|
raise ArgumentError, "cannot find elements by #{how.inspect}" unless by
|
79
80
|
|
80
|
-
bridge.find_elements_by by, what
|
81
|
+
bridge.find_elements_by by, what, ref
|
81
82
|
rescue Selenium::WebDriver::Error::TimeoutError
|
82
83
|
# Implicit Wait times out in Edge
|
83
84
|
[]
|
@@ -37,19 +37,6 @@ module Selenium
|
|
37
37
|
end
|
38
38
|
|
39
39
|
def firefox(**opts)
|
40
|
-
binary_path = Firefox::Binary.path
|
41
|
-
args = opts.delete(:args)
|
42
|
-
case args
|
43
|
-
when Hash
|
44
|
-
args[:binary] ||= binary_path
|
45
|
-
opts[:args] = args
|
46
|
-
when Array
|
47
|
-
opts[:args] = ["--binary=#{binary_path}"]
|
48
|
-
opts[:args] += args
|
49
|
-
else
|
50
|
-
opts[:args] = ["--binary=#{binary_path}"]
|
51
|
-
end
|
52
|
-
|
53
40
|
Firefox::Service.new(**opts)
|
54
41
|
end
|
55
42
|
|
@@ -69,8 +69,8 @@ module Selenium
|
|
69
69
|
ChildProcess.close_on_exec @server
|
70
70
|
|
71
71
|
true
|
72
|
-
rescue SocketError, Errno::EADDRINUSE, Errno::EBADF =>
|
73
|
-
WebDriver.logger.debug("#{self}: #{
|
72
|
+
rescue SocketError, Errno::EADDRINUSE, Errno::EBADF => e
|
73
|
+
WebDriver.logger.debug("#{self}: #{e.message}")
|
74
74
|
false
|
75
75
|
end
|
76
76
|
|
@@ -28,13 +28,15 @@ module Selenium
|
|
28
28
|
|
29
29
|
def self.driver_path=(path)
|
30
30
|
WebDriver.logger.deprecate 'Selenium::WebDriver::Edge#driver_path=',
|
31
|
-
'Selenium::WebDriver::Edge::Service#driver_path='
|
31
|
+
'Selenium::WebDriver::Edge::Service#driver_path=',
|
32
|
+
id: :driver_path
|
32
33
|
Selenium::WebDriver::Edge::Service.driver_path = path
|
33
34
|
end
|
34
35
|
|
35
36
|
def self.driver_path
|
36
37
|
WebDriver.logger.deprecate 'Selenium::WebDriver::Edge#driver_path',
|
37
|
-
'Selenium::WebDriver::Edge::Service#driver_path'
|
38
|
+
'Selenium::WebDriver::Edge::Service#driver_path',
|
39
|
+
id: :driver_path
|
38
40
|
Selenium::WebDriver::Edge::Service.driver_path
|
39
41
|
end
|
40
42
|
end # EdgeHtml
|
@@ -30,24 +30,10 @@ module Selenium
|
|
30
30
|
include DriverExtensions::HasWebStorage
|
31
31
|
include DriverExtensions::TakesScreenshot
|
32
32
|
|
33
|
-
def initialize(opts = {})
|
34
|
-
opts[:desired_capabilities] ||= Remote::Capabilities.edge
|
35
|
-
|
36
|
-
opts[:url] ||= service_url(opts)
|
37
|
-
|
38
|
-
listener = opts.delete(:listener)
|
39
|
-
desired_capabilities = opts.delete(:desired_capabilities)
|
40
|
-
|
41
|
-
@bridge = Remote::Bridge.new(opts)
|
42
|
-
@bridge.create_session(desired_capabilities)
|
43
|
-
|
44
|
-
super(@bridge, listener: listener)
|
45
|
-
end
|
46
|
-
|
47
33
|
def browser
|
48
34
|
:edge
|
49
35
|
end
|
50
36
|
end # Driver
|
51
|
-
end #
|
37
|
+
end # EdgeHtml
|
52
38
|
end # WebDriver
|
53
39
|
end # Selenium
|