webdrivers 2.3.2 → 4.7.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/CHANGELOG.md +204 -56
- data/LICENSE.txt +2 -2
- data/README.md +253 -17
- data/lib/webdrivers/Rakefile +6 -0
- data/lib/webdrivers/chrome_finder.rb +127 -0
- data/lib/webdrivers/chromedriver.rb +131 -23
- data/lib/webdrivers/common.rb +145 -70
- data/lib/webdrivers/edge_finder.rb +99 -0
- data/lib/webdrivers/edgedriver.rb +87 -17
- data/lib/webdrivers/geckodriver.rb +46 -25
- data/lib/webdrivers/iedriver.rb +51 -18
- data/lib/webdrivers/logger.rb +111 -0
- data/lib/webdrivers/network.rb +63 -0
- data/lib/webdrivers/railtie.rb +15 -0
- data/lib/webdrivers/system.rb +197 -0
- data/lib/webdrivers/tasks/chromedriver.rake +44 -0
- data/lib/webdrivers/tasks/edgedriver.rake +44 -0
- data/lib/webdrivers/tasks/geckodriver.rake +44 -0
- data/lib/webdrivers/tasks/iedriver.rake +44 -0
- data/lib/webdrivers/version.rb +5 -0
- data/lib/webdrivers.rb +7 -9
- data/spec/spec_helper.rb +18 -2
- data/spec/webdrivers/chrome_finder_spec.rb +103 -0
- data/spec/webdrivers/chromedriver_spec.rb +276 -0
- data/spec/webdrivers/edge_finder_spec.rb +58 -0
- data/spec/webdrivers/edgedriver_spec.rb +279 -0
- data/spec/webdrivers/geckodriver_spec.rb +211 -0
- data/spec/webdrivers/i_edriver_spec.rb +197 -0
- data/spec/webdrivers/system_spec.rb +79 -0
- data/spec/webdrivers/webdrivers_spec.rb +80 -0
- data/spec/webdrivers_proxy_support_spec.rb +53 -0
- metadata +157 -43
- data/.gitignore +0 -6
- data/.travis.yml +0 -3
- data/Gemfile +0 -4
- data/Rakefile +0 -6
- data/bin/IEDriverServer +0 -5
- data/bin/MicrosoftWebDriver +0 -5
- data/bin/chromedriver +0 -5
- data/bin/geckodriver +0 -5
- data/bin/phantomjs +0 -5
- data/lib/webdrivers/phantomjs.rb +0 -40
- data/spec/chromedriver_spec.rb +0 -36
- data/spec/edgedriver_spec.rb +0 -24
- data/spec/geckodriver_spec.rb +0 -36
- data/spec/iedriver_spec.rb +0 -27
- data/spec/phantomjs_spec.rb +0 -36
- data/webdrivers.gemspec +0 -24
@@ -0,0 +1,127 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Webdrivers
|
4
|
+
#
|
5
|
+
# @api private
|
6
|
+
#
|
7
|
+
class ChromeFinder
|
8
|
+
class << self
|
9
|
+
def version
|
10
|
+
version = send("#{System.platform}_version", location)
|
11
|
+
raise VersionError, 'Failed to find Chrome version.' if version.nil? || version.empty?
|
12
|
+
|
13
|
+
Webdrivers.logger.debug "Browser version: #{version}"
|
14
|
+
version[/\d+\.\d+\.\d+\.\d+/] # Google Chrome 73.0.3683.75 -> 73.0.3683.75
|
15
|
+
end
|
16
|
+
|
17
|
+
def location
|
18
|
+
chrome_bin = user_defined_location || send("#{System.platform}_location")
|
19
|
+
return chrome_bin unless chrome_bin.nil?
|
20
|
+
|
21
|
+
raise BrowserNotFound, 'Failed to find Chrome binary.'
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def user_defined_location
|
27
|
+
if Selenium::WebDriver::Chrome.path
|
28
|
+
Webdrivers.logger.debug "Selenium::WebDriver::Chrome.path: #{Selenium::WebDriver::Chrome.path}"
|
29
|
+
return Selenium::WebDriver::Chrome.path
|
30
|
+
end
|
31
|
+
|
32
|
+
return if ENV['WD_CHROME_PATH'].nil?
|
33
|
+
|
34
|
+
Webdrivers.logger.debug "WD_CHROME_PATH: #{ENV['WD_CHROME_PATH']}"
|
35
|
+
ENV['WD_CHROME_PATH']
|
36
|
+
end
|
37
|
+
|
38
|
+
def win_location
|
39
|
+
envs = %w[LOCALAPPDATA PROGRAMFILES PROGRAMFILES(X86)]
|
40
|
+
directories = ['\\Google\\Chrome\\Application', '\\Chromium\\Application']
|
41
|
+
file = 'chrome.exe'
|
42
|
+
|
43
|
+
directories.each do |dir|
|
44
|
+
envs.each do |root|
|
45
|
+
option = "#{ENV[root]}\\#{dir}\\#{file}"
|
46
|
+
return option if File.exist?(option)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
nil
|
51
|
+
end
|
52
|
+
|
53
|
+
def wsl_location
|
54
|
+
_, drive, user = ENV['PATH'].match(%r{/([a-z])/Users/([^/:]+)/AppData/}).to_a
|
55
|
+
|
56
|
+
roots = [
|
57
|
+
"#{drive}:\\Users\\#{user}\\AppData\\Local",
|
58
|
+
"#{drive}:\\Program Files (x86)",
|
59
|
+
"#{drive}:\\Program Files"
|
60
|
+
]
|
61
|
+
|
62
|
+
directories = %w[Google\\Chrome\\Application Chromium\\Application]
|
63
|
+
file = 'chrome.exe'
|
64
|
+
|
65
|
+
directories.each do |dir|
|
66
|
+
roots.each do |root|
|
67
|
+
option = System.to_wsl_path("#{root}\\#{dir}\\#{file}")
|
68
|
+
return option if File.exist?(option)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
nil
|
73
|
+
end
|
74
|
+
|
75
|
+
def mac_location
|
76
|
+
directories = ['', File.expand_path('~')]
|
77
|
+
files = ['/Applications/Google Chrome.app/Contents/MacOS/Google Chrome',
|
78
|
+
'/Applications/Chromium.app/Contents/MacOS/Chromium']
|
79
|
+
|
80
|
+
directories.each do |dir|
|
81
|
+
files.each do |file|
|
82
|
+
option = "#{dir}/#{file}"
|
83
|
+
return option if File.exist?(option)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
nil
|
88
|
+
end
|
89
|
+
|
90
|
+
def linux_location
|
91
|
+
return wsl_location if System.wsl_v1?
|
92
|
+
|
93
|
+
directories = %w[/usr/local/sbin /usr/local/bin /usr/sbin /usr/bin /sbin /bin /snap/bin /opt/google/chrome]
|
94
|
+
files = %w[google-chrome chrome chromium chromium-browser]
|
95
|
+
|
96
|
+
directories.each do |dir|
|
97
|
+
files.each do |file|
|
98
|
+
option = "#{dir}/#{file}"
|
99
|
+
return option if File.exist?(option)
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
nil
|
104
|
+
end
|
105
|
+
|
106
|
+
def win_version(location)
|
107
|
+
System.call("pwsh.exe -command \"(Get-ItemProperty '#{location}').VersionInfo.ProductVersion\"")&.strip
|
108
|
+
rescue StandardError
|
109
|
+
System.call("powershell.exe \"(Get-ItemProperty '#{location}').VersionInfo.ProductVersion\"")&.strip
|
110
|
+
end
|
111
|
+
|
112
|
+
def wsl_version(location)
|
113
|
+
win_version(System.to_win32_path(location))
|
114
|
+
end
|
115
|
+
|
116
|
+
def linux_version(location)
|
117
|
+
return wsl_version(location) if System.wsl_v1?
|
118
|
+
|
119
|
+
System.call(location, '--product-version')&.strip
|
120
|
+
end
|
121
|
+
|
122
|
+
def mac_version(location)
|
123
|
+
System.call(location, '--version')&.strip
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
@@ -1,41 +1,149 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'shellwords'
|
4
|
+
require 'webdrivers/common'
|
5
|
+
require 'webdrivers/chrome_finder'
|
2
6
|
|
3
7
|
module Webdrivers
|
4
8
|
class Chromedriver < Common
|
5
|
-
|
6
9
|
class << self
|
7
|
-
|
8
|
-
|
10
|
+
#
|
11
|
+
# Returns current chromedriver version.
|
12
|
+
#
|
13
|
+
# @return [Gem::Version]
|
14
|
+
def current_version
|
15
|
+
Webdrivers.logger.debug 'Checking current version'
|
16
|
+
return nil unless exists?
|
17
|
+
|
18
|
+
version = binary_version
|
19
|
+
return nil if version.nil?
|
20
|
+
|
21
|
+
# Matches 2.46, 2.46.628411 and 73.0.3683.75
|
22
|
+
normalize_version version[/\d+\.\d+(\.\d+)?(\.\d+)?/]
|
9
23
|
end
|
10
24
|
|
11
|
-
|
12
|
-
|
13
|
-
|
25
|
+
#
|
26
|
+
# Returns latest available chromedriver version.
|
27
|
+
#
|
28
|
+
# @return [Gem::Version]
|
29
|
+
def latest_version
|
30
|
+
@latest_version ||= begin
|
31
|
+
# Versions before 70 do not have a LATEST_RELEASE file
|
32
|
+
return normalize_version('2.41') if browser_build_version < normalize_version('70')
|
33
|
+
|
34
|
+
# Cache check
|
35
|
+
# Cached version should exist and be compatible with the current browser version.
|
36
|
+
# Otherwise, fetch the latest compatible driver.
|
37
|
+
latest_applicable = with_cache(file_name,
|
38
|
+
current_build_version,
|
39
|
+
browser_build_version) { latest_point_release(browser_build_version) }
|
40
|
+
|
41
|
+
Webdrivers.logger.debug "Latest version available: #{latest_applicable}"
|
42
|
+
normalize_version(latest_applicable)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
#
|
47
|
+
# Returns currently installed Chrome/Chromium version.
|
48
|
+
#
|
49
|
+
# @return [Gem::Version]
|
50
|
+
def browser_version
|
51
|
+
normalize_version ChromeFinder.version
|
52
|
+
end
|
53
|
+
alias chrome_version browser_version
|
54
|
+
|
55
|
+
#
|
56
|
+
# Returns url with domain for calls to get this driver.
|
57
|
+
#
|
58
|
+
# @return [String]
|
59
|
+
def base_url
|
60
|
+
'https://chromedriver.storage.googleapis.com'
|
61
|
+
end
|
62
|
+
|
63
|
+
private
|
64
|
+
|
65
|
+
def latest_point_release(version)
|
66
|
+
normalize_version(Network.get(URI.join(base_url, "LATEST_RELEASE_#{version}")))
|
67
|
+
rescue NetworkError
|
68
|
+
msg = "Unable to find latest point release version for #{version}."
|
69
|
+
msg = begin
|
70
|
+
latest_release = normalize_version(Network.get(URI.join(base_url, 'LATEST_RELEASE')))
|
71
|
+
if version > latest_release
|
72
|
+
"#{msg} You appear to be using a non-production version of Chrome."
|
73
|
+
else
|
74
|
+
msg
|
75
|
+
end
|
76
|
+
rescue NetworkError
|
77
|
+
"#{msg} A network issue is preventing determination of latest chromedriver release."
|
78
|
+
end
|
79
|
+
|
80
|
+
msg = "#{msg} Please set `Webdrivers::Chromedriver.required_version = <desired driver version>` "\
|
81
|
+
'to a known chromedriver version: https://chromedriver.storage.googleapis.com/index.html'
|
82
|
+
Webdrivers.logger.debug msg
|
83
|
+
raise VersionError, msg
|
14
84
|
end
|
15
85
|
|
16
|
-
def
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
86
|
+
def file_name
|
87
|
+
System.platform == 'win' || System.wsl_v1? ? 'chromedriver.exe' : 'chromedriver'
|
88
|
+
end
|
89
|
+
|
90
|
+
def apple_m1_compatible?(driver_version)
|
91
|
+
if System.apple_m1_architecture? && driver_version >= normalize_version('87.0.4280.88')
|
92
|
+
Webdrivers.logger.debug 'chromedriver version is Apple M1 compatible.'
|
93
|
+
return true
|
21
94
|
end
|
22
|
-
|
95
|
+
|
96
|
+
Webdrivers.logger.debug 'chromedriver version is NOT Apple M1 compatible. Required >= 87.0.4280.88'
|
97
|
+
false
|
23
98
|
end
|
24
99
|
|
25
|
-
def
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
100
|
+
def direct_url(driver_version)
|
101
|
+
"#{base_url}/#{driver_version}/chromedriver_#{driver_filename(driver_version)}.zip"
|
102
|
+
end
|
103
|
+
|
104
|
+
def driver_filename(driver_version)
|
105
|
+
if System.platform == 'win' || System.wsl_v1?
|
106
|
+
'win32'
|
107
|
+
elsif System.platform == 'linux'
|
108
|
+
'linux64'
|
109
|
+
elsif System.platform == 'mac'
|
110
|
+
apple_arch = apple_m1_compatible?(driver_version) ? '_m1' : ''
|
111
|
+
"mac64#{apple_arch}"
|
112
|
+
else
|
113
|
+
raise 'Failed to determine driver filename to download for your OS.'
|
31
114
|
end
|
32
115
|
end
|
33
116
|
|
34
|
-
|
35
|
-
|
117
|
+
# Returns major.minor.build version from the currently installed chromedriver version
|
118
|
+
#
|
119
|
+
# @example
|
120
|
+
# 73.0.3683.68 (major.minor.build.patch) -> 73.0.3683 (major.minor.build)
|
121
|
+
def current_build_version
|
122
|
+
build_ver = if current_version.nil? # Driver not found
|
123
|
+
nil
|
124
|
+
else
|
125
|
+
current_version.segments[0..2].join('.')
|
126
|
+
end
|
127
|
+
normalize_version(build_ver)
|
36
128
|
end
|
37
129
|
|
38
|
-
|
130
|
+
# Returns major.minor.build version from the currently installed Chrome version
|
131
|
+
#
|
132
|
+
# @example
|
133
|
+
# 73.0.3683.75 (major.minor.build.patch) -> 73.0.3683 (major.minor.build)
|
134
|
+
def browser_build_version
|
135
|
+
normalize_version(browser_version.segments[0..2].join('.'))
|
136
|
+
end
|
137
|
+
alias chrome_build_version browser_build_version
|
39
138
|
|
139
|
+
# Returns true if an executable driver binary exists
|
140
|
+
# and its build version matches the browser build version
|
141
|
+
def sufficient_binary?
|
142
|
+
super && current_version && (current_version < normalize_version('70.0.3538') ||
|
143
|
+
current_build_version == browser_build_version)
|
144
|
+
end
|
145
|
+
end
|
40
146
|
end
|
41
|
-
end
|
147
|
+
end
|
148
|
+
|
149
|
+
::Selenium::WebDriver::Chrome::Service.driver_path = proc { ::Webdrivers::Chromedriver.update }
|
data/lib/webdrivers/common.rb
CHANGED
@@ -1,100 +1,175 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'rubygems/package'
|
2
|
-
require '
|
4
|
+
require 'webdrivers/logger'
|
5
|
+
require 'webdrivers/network'
|
6
|
+
require 'webdrivers/system'
|
7
|
+
require 'selenium-webdriver'
|
8
|
+
require 'webdrivers/version'
|
3
9
|
|
4
10
|
module Webdrivers
|
5
|
-
class
|
11
|
+
class ConnectionError < StandardError
|
12
|
+
end
|
13
|
+
|
14
|
+
class VersionError < StandardError
|
15
|
+
end
|
16
|
+
|
17
|
+
class NetworkError < StandardError
|
18
|
+
end
|
19
|
+
|
20
|
+
class BrowserNotFound < StandardError
|
21
|
+
end
|
22
|
+
|
23
|
+
DEFAULT_CACHE_TIME = 86_400 # 24 hours
|
24
|
+
DEFAULT_INSTALL_DIR = File.expand_path('~/.webdrivers')
|
25
|
+
|
26
|
+
class << self
|
27
|
+
attr_accessor :proxy_addr, :proxy_port, :proxy_user, :proxy_pass
|
28
|
+
attr_writer :install_dir, :cache_time
|
29
|
+
|
30
|
+
#
|
31
|
+
# Returns the amount of time (Seconds) the gem waits between two update checks.
|
32
|
+
# @note Value from the environment variable "WD_CACHE_TIME" takes precedence over Webdrivers.cache_time. If neither
|
33
|
+
# are set, it defaults to 86,400 Seconds (24 hours).
|
34
|
+
#
|
35
|
+
def cache_time
|
36
|
+
@cache_time ||= (ENV['WD_CACHE_TIME'] || DEFAULT_CACHE_TIME)
|
37
|
+
@cache_time.to_i
|
38
|
+
end
|
39
|
+
|
40
|
+
#
|
41
|
+
# Returns the install (download) directory path for the drivers.
|
42
|
+
#
|
43
|
+
# @return [String]
|
44
|
+
def install_dir
|
45
|
+
@install_dir ||= ENV['WD_INSTALL_DIR'] || DEFAULT_INSTALL_DIR
|
46
|
+
end
|
47
|
+
|
48
|
+
def logger
|
49
|
+
@logger ||= Webdrivers::Logger.new
|
50
|
+
end
|
6
51
|
|
52
|
+
#
|
53
|
+
# Provides a convenient way to configure the gem.
|
54
|
+
#
|
55
|
+
# @example Configure proxy and cache_time
|
56
|
+
# Webdrivers.configure do |config|
|
57
|
+
# config.proxy_addr = 'myproxy_address.com'
|
58
|
+
# config.proxy_port = '8080'
|
59
|
+
# config.proxy_user = 'username'
|
60
|
+
# config.proxy_pass = 'password'
|
61
|
+
# config.cache_time = 604_800 # 7 days
|
62
|
+
# end
|
63
|
+
#
|
64
|
+
def configure
|
65
|
+
yield self
|
66
|
+
end
|
67
|
+
|
68
|
+
def net_http_ssl_fix
|
69
|
+
raise 'Webdrivers.net_http_ssl_fix is no longer available.' \
|
70
|
+
' Please see https://github.com/titusfortner/webdrivers#ssl_connect-errors.'
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
class Common
|
7
75
|
class << self
|
8
|
-
|
9
|
-
|
10
|
-
|
76
|
+
attr_writer :required_version
|
77
|
+
|
78
|
+
#
|
79
|
+
# Returns the user defined required version.
|
80
|
+
#
|
81
|
+
# @return [Gem::Version]
|
82
|
+
def required_version
|
83
|
+
normalize_version(@required_version ||= nil)
|
11
84
|
end
|
12
85
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
File.open(filename, "wb") do |saved_file|
|
23
|
-
URI.parse(url).open("rb") do |read_file|
|
24
|
-
saved_file.write(read_file.read)
|
25
|
-
end
|
26
|
-
end
|
27
|
-
raise "Could not download #{url}" unless File.exists? filename
|
28
|
-
dcf = decompress_file(filename)
|
29
|
-
extract_file(dcf) if respond_to? :extract_file
|
86
|
+
#
|
87
|
+
# Triggers an update check.
|
88
|
+
#
|
89
|
+
# @return [String] Path to the driver binary.
|
90
|
+
def update
|
91
|
+
if correct_binary?
|
92
|
+
msg = required_version != EMPTY_VERSION ? 'The required webdriver version' : 'A working webdriver version'
|
93
|
+
Webdrivers.logger.debug "#{msg} is already on the system"
|
94
|
+
return driver_path
|
30
95
|
end
|
31
|
-
|
32
|
-
|
96
|
+
|
97
|
+
remove
|
98
|
+
System.download(download_url, driver_path)
|
33
99
|
end
|
34
100
|
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
101
|
+
#
|
102
|
+
# Deletes the existing driver binary.
|
103
|
+
#
|
104
|
+
def remove
|
105
|
+
@download_url = nil
|
106
|
+
@latest_version = nil
|
107
|
+
System.delete "#{System.install_dir}/#{file_name.gsub('.exe', '')}.version"
|
108
|
+
System.delete driver_path
|
109
|
+
end
|
110
|
+
|
111
|
+
#
|
112
|
+
# Returns path to the driver binary.
|
113
|
+
#
|
114
|
+
# @return [String]
|
115
|
+
def driver_path
|
116
|
+
File.absolute_path File.join(System.install_dir, file_name)
|
42
117
|
end
|
43
118
|
|
44
|
-
|
45
|
-
tar_extract = Gem::Package::TarReader.new(Zlib::GzipReader.open(filename))
|
46
|
-
tar_extract.rewind
|
119
|
+
private
|
47
120
|
|
48
|
-
|
49
|
-
|
50
|
-
ucf.close
|
51
|
-
File.basename ucf
|
121
|
+
def download_version
|
122
|
+
required_version == EMPTY_VERSION ? latest_version : required_version
|
52
123
|
end
|
53
124
|
|
54
|
-
def
|
55
|
-
|
56
|
-
zip_file.each do |f|
|
57
|
-
@top_path ||= f.name
|
58
|
-
f_path = File.join(Dir.pwd, f.name)
|
59
|
-
FileUtils.mkdir_p(File.dirname(f_path))
|
60
|
-
zip_file.extract(f, f_path) unless File.exist?(f_path)
|
61
|
-
end
|
62
|
-
end
|
63
|
-
@top_path
|
125
|
+
def download_url
|
126
|
+
@download_url ||= direct_url(download_version).tap { |url| Webdrivers.logger.debug "#{file_name} URL: #{url}" }
|
64
127
|
end
|
65
128
|
|
66
|
-
def
|
67
|
-
|
129
|
+
def exists?
|
130
|
+
System.exists? driver_path
|
68
131
|
end
|
69
132
|
|
70
|
-
def
|
71
|
-
|
133
|
+
def correct_binary?
|
134
|
+
current_version == download_version
|
135
|
+
rescue ConnectionError, VersionError
|
136
|
+
driver_path if sufficient_binary?
|
72
137
|
end
|
73
138
|
|
74
|
-
def
|
75
|
-
|
139
|
+
def sufficient_binary?
|
140
|
+
exists?
|
76
141
|
end
|
77
142
|
|
78
|
-
def
|
79
|
-
|
143
|
+
def normalize_version(version)
|
144
|
+
Gem::Version.new(version.to_s)
|
80
145
|
end
|
81
146
|
|
82
|
-
def
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
end
|
147
|
+
def binary_version
|
148
|
+
version = System.call(driver_path, '--version')
|
149
|
+
Webdrivers.logger.debug "Current version of #{driver_path} is #{version}"
|
150
|
+
version
|
151
|
+
rescue Errno::ENOENT
|
152
|
+
Webdrivers.logger.debug "No Such File or Directory: #{driver_path}"
|
153
|
+
nil
|
90
154
|
end
|
91
155
|
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
156
|
+
# Returns cached driver version if cache is still valid and the driver binary exists.
|
157
|
+
# Otherwise caches the given version (typically the latest available)
|
158
|
+
# In case of Chrome, it also verifies that the driver build and browser build versions are compatible.
|
159
|
+
# Example usage: lib/webdrivers/chromedriver.rb:34
|
160
|
+
def with_cache(file_name, driver_build = nil, browser_build = nil)
|
161
|
+
if System.valid_cache?(file_name) && exists? && (driver_build == browser_build)
|
162
|
+
cached_version = System.cached_version(file_name)
|
163
|
+
Webdrivers.logger.debug "using cached version as latest: #{cached_version}"
|
164
|
+
normalize_version cached_version
|
165
|
+
else
|
166
|
+
version = yield
|
167
|
+
System.cache_version(file_name, version)
|
168
|
+
normalize_version version
|
169
|
+
end
|
96
170
|
end
|
97
|
-
end
|
98
171
|
|
172
|
+
EMPTY_VERSION = Gem::Version.new('')
|
173
|
+
end
|
99
174
|
end
|
100
|
-
end
|
175
|
+
end
|
@@ -0,0 +1,99 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Webdrivers
|
4
|
+
#
|
5
|
+
# @api private
|
6
|
+
#
|
7
|
+
class EdgeFinder
|
8
|
+
class << self
|
9
|
+
def version
|
10
|
+
version = send("#{System.platform}_version", location)
|
11
|
+
raise VersionError, 'Failed to find Edge version.' if version.nil? || version.empty?
|
12
|
+
|
13
|
+
Webdrivers.logger.debug "Browser version: #{version}"
|
14
|
+
version[/\d+\.\d+\.\d+\.\d+/] # Microsoft Edge 73.0.3683.75 -> 73.0.3683.75
|
15
|
+
end
|
16
|
+
|
17
|
+
def location
|
18
|
+
edge_bin = user_defined_location || send("#{System.platform}_location")
|
19
|
+
return edge_bin unless edge_bin.nil?
|
20
|
+
|
21
|
+
raise BrowserNotFound, 'Failed to find Edge binary.'
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def user_defined_location
|
27
|
+
if Selenium::WebDriver::Edge.path
|
28
|
+
Webdrivers.logger.debug "Selenium::WebDriver::Edge.path: #{Selenium::WebDriver::Edge.path}"
|
29
|
+
return Selenium::WebDriver::Edge.path
|
30
|
+
end
|
31
|
+
|
32
|
+
return if ENV['WD_EDGE_PATH'].nil?
|
33
|
+
|
34
|
+
Webdrivers.logger.debug "WD_EDGE_PATH: #{ENV['WD_EDGE_PATH']}"
|
35
|
+
ENV['WD_EDGE_PATH']
|
36
|
+
end
|
37
|
+
|
38
|
+
def win_location
|
39
|
+
envs = %w[LOCALAPPDATA PROGRAMFILES PROGRAMFILES(X86)]
|
40
|
+
directories = ['\\Microsoft\\Edge\\Application',
|
41
|
+
'\\Microsoft\\Edge Beta\\Application',
|
42
|
+
'\\Microsoft\\Edge Dev\\Application',
|
43
|
+
'\\Microsoft\\Edge SxS\\Application']
|
44
|
+
file = 'msedge.exe'
|
45
|
+
|
46
|
+
directories.each do |dir|
|
47
|
+
envs.each do |root|
|
48
|
+
option = "#{ENV[root]}\\#{dir}\\#{file}"
|
49
|
+
return option if File.exist?(option)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
nil
|
53
|
+
end
|
54
|
+
|
55
|
+
def mac_location
|
56
|
+
directories = ['', File.expand_path('~')]
|
57
|
+
files = ['/Applications/Microsoft Edge.app/Contents/MacOS/Microsoft Edge',
|
58
|
+
'/Applications/Microsoft Edge Beta.app/Contents/MacOS/Microsoft Edge Beta',
|
59
|
+
'/Applications/Microsoft Edge Dev.app/Contents/MacOS/Microsoft Edge Dev',
|
60
|
+
'/Applications/Microsoft Edge Canary.app/Contents/MacOS/Microsoft Edge Canary']
|
61
|
+
|
62
|
+
directories.each do |dir|
|
63
|
+
files.each do |file|
|
64
|
+
option = "#{dir}/#{file}"
|
65
|
+
return option if File.exist?(option)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
nil
|
69
|
+
end
|
70
|
+
|
71
|
+
def linux_location
|
72
|
+
# directories = %w[/usr/local/sbin /usr/local/bin /usr/sbin /usr/bin /sbin /bin /snap/bin /opt/google/chrome]
|
73
|
+
# files = %w[microsoft-edge] # Based on Microsoft Edge 89.0.760.0 dev
|
74
|
+
#
|
75
|
+
# directories.each do |dir|
|
76
|
+
# files.each do |file|
|
77
|
+
# option = "#{dir}/#{file}"
|
78
|
+
# return option if File.exist?(option)
|
79
|
+
# end
|
80
|
+
# end
|
81
|
+
#
|
82
|
+
# nil
|
83
|
+
raise 'Default location not yet known'
|
84
|
+
end
|
85
|
+
|
86
|
+
def win_version(location)
|
87
|
+
System.call("powershell (Get-ItemProperty '#{location}').VersionInfo.ProductVersion")&.strip
|
88
|
+
end
|
89
|
+
|
90
|
+
def linux_version(location)
|
91
|
+
System.call(location, '--product-version')&.strip
|
92
|
+
end
|
93
|
+
|
94
|
+
def mac_version(location)
|
95
|
+
System.call(location, '--version')&.strip
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|