webdrivers 2.3.2 → 4.7.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (49) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +204 -56
  3. data/LICENSE.txt +2 -2
  4. data/README.md +253 -17
  5. data/lib/webdrivers/Rakefile +6 -0
  6. data/lib/webdrivers/chrome_finder.rb +127 -0
  7. data/lib/webdrivers/chromedriver.rb +131 -23
  8. data/lib/webdrivers/common.rb +145 -70
  9. data/lib/webdrivers/edge_finder.rb +99 -0
  10. data/lib/webdrivers/edgedriver.rb +87 -17
  11. data/lib/webdrivers/geckodriver.rb +46 -25
  12. data/lib/webdrivers/iedriver.rb +51 -18
  13. data/lib/webdrivers/logger.rb +111 -0
  14. data/lib/webdrivers/network.rb +63 -0
  15. data/lib/webdrivers/railtie.rb +15 -0
  16. data/lib/webdrivers/system.rb +197 -0
  17. data/lib/webdrivers/tasks/chromedriver.rake +44 -0
  18. data/lib/webdrivers/tasks/edgedriver.rake +44 -0
  19. data/lib/webdrivers/tasks/geckodriver.rake +44 -0
  20. data/lib/webdrivers/tasks/iedriver.rake +44 -0
  21. data/lib/webdrivers/version.rb +5 -0
  22. data/lib/webdrivers.rb +7 -9
  23. data/spec/spec_helper.rb +18 -2
  24. data/spec/webdrivers/chrome_finder_spec.rb +103 -0
  25. data/spec/webdrivers/chromedriver_spec.rb +276 -0
  26. data/spec/webdrivers/edge_finder_spec.rb +58 -0
  27. data/spec/webdrivers/edgedriver_spec.rb +279 -0
  28. data/spec/webdrivers/geckodriver_spec.rb +211 -0
  29. data/spec/webdrivers/i_edriver_spec.rb +197 -0
  30. data/spec/webdrivers/system_spec.rb +79 -0
  31. data/spec/webdrivers/webdrivers_spec.rb +80 -0
  32. data/spec/webdrivers_proxy_support_spec.rb +53 -0
  33. metadata +157 -43
  34. data/.gitignore +0 -6
  35. data/.travis.yml +0 -3
  36. data/Gemfile +0 -4
  37. data/Rakefile +0 -6
  38. data/bin/IEDriverServer +0 -5
  39. data/bin/MicrosoftWebDriver +0 -5
  40. data/bin/chromedriver +0 -5
  41. data/bin/geckodriver +0 -5
  42. data/bin/phantomjs +0 -5
  43. data/lib/webdrivers/phantomjs.rb +0 -40
  44. data/spec/chromedriver_spec.rb +0 -36
  45. data/spec/edgedriver_spec.rb +0 -24
  46. data/spec/geckodriver_spec.rb +0 -36
  47. data/spec/iedriver_spec.rb +0 -27
  48. data/spec/phantomjs_spec.rb +0 -36
  49. 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
- require 'nokogiri'
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
- def file_name
8
- platform == "win" ? "chromedriver.exe" : "chromedriver"
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
- def current_version
12
- return nil unless File.exists?(binary_path)
13
- %x(#{binary_path} --version).match(/ChromeDriver (\d\.\d+)/)[1]
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 newest_version
17
- padded = downloads.keys.each_with_object({}) do |version, hash|
18
- matched = version.match(/^(\d+)\.(\d+)$/)
19
- minor = sprintf '%02d', matched[2]
20
- hash["#{matched[1]}.#{minor}"] = version
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
- padded.keys.sort.last
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 downloads
26
- doc = Nokogiri::XML.parse(OpenURI.open_uri(base_url))
27
- items = doc.css("Contents Key").collect(&:text)
28
- items.select! { |item| item.include?(platform) }
29
- items.each_with_object({}) do |item, hash|
30
- hash[item[/^[^\/]+/]] = "#{base_url}/#{item}"
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
- def base_url
35
- 'http://chromedriver.storage.googleapis.com'
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
- end
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 }
@@ -1,100 +1,175 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'rubygems/package'
2
- require 'zip'
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 Common
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
- def install *args
9
- download
10
- exec binary_path, *args
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
- def download
14
- return if File.exists?(binary_path) && !internet_connection?
15
- raise StandardError, "Unable to Reach #{base_url}" unless internet_connection?
16
- return if newest_version == current_version
17
-
18
- url = download_url
19
- filename = File.basename url
20
- Dir.chdir platform_install_dir do
21
- FileUtils.rm_f filename
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
- raise "Could not unzip #{filename} to get #{binary_path}" unless File.exists? binary_path
32
- FileUtils.chmod "ugo+rx", binary_path
96
+
97
+ remove
98
+ System.download(download_url, driver_path)
33
99
  end
34
100
 
35
- def decompress_file(filename)
36
- case filename
37
- when /tar\.gz$/
38
- untargz_file(filename)
39
- when /\.zip$/
40
- unzip_file(filename)
41
- end
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
- def untargz_file(filename)
45
- tar_extract = Gem::Package::TarReader.new(Zlib::GzipReader.open(filename))
46
- tar_extract.rewind
119
+ private
47
120
 
48
- ucf = File.open(file_name, "w+")
49
- tar_extract.each { |entry| ucf << entry.read }
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 unzip_file(filename)
55
- Zip::ZipFile.open("#{Dir.pwd}/#{filename}") do |zip_file|
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 download_url(version = nil)
67
- downloads[version || newest_version]
129
+ def exists?
130
+ System.exists? driver_path
68
131
  end
69
132
 
70
- def binary_path
71
- File.join platform_install_dir, file_name
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 platform_install_dir
75
- File.join(install_dir, platform).tap { |dir| FileUtils.mkdir_p dir }
139
+ def sufficient_binary?
140
+ exists?
76
141
  end
77
142
 
78
- def install_dir
79
- File.expand_path(File.join(ENV['HOME'], ".webdrivers")).tap { |dir| FileUtils.mkdir_p dir}
143
+ def normalize_version(version)
144
+ Gem::Version.new(version.to_s)
80
145
  end
81
146
 
82
- def platform
83
- cfg = RbConfig::CONFIG
84
- case cfg['host_os']
85
- when /linux/ then
86
- cfg['host_cpu'] =~ /x86_64|amd64/ ? "linux64" : "linux32"
87
- when /darwin/ then "mac"
88
- else "win"
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
- def internet_connection?
93
- true #if open(base_url)
94
- rescue
95
- false
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