webdrivers 4.0.0 → 5.2.0
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 +4 -4
- data/CHANGELOG.md +98 -0
- data/README.md +88 -34
- data/lib/webdrivers/chrome_finder.rb +77 -9
- data/lib/webdrivers/chromedriver.rb +65 -39
- data/lib/webdrivers/common.rb +31 -21
- data/lib/webdrivers/edge_finder.rb +98 -0
- data/lib/webdrivers/edgedriver.rb +99 -0
- data/lib/webdrivers/geckodriver.rb +2 -23
- data/lib/webdrivers/iedriver.rb +14 -20
- data/lib/webdrivers/logger.rb +2 -93
- data/lib/webdrivers/network.rb +2 -0
- data/lib/webdrivers/railtie.rb +0 -1
- data/lib/webdrivers/system.rb +57 -14
- data/lib/webdrivers/tasks/chromedriver.rake +0 -2
- data/lib/webdrivers/tasks/edgedriver.rake +44 -0
- data/lib/webdrivers/tasks/geckodriver.rake +0 -2
- data/lib/webdrivers/tasks/iedriver.rake +0 -2
- data/lib/webdrivers/version.rb +1 -1
- data/lib/webdrivers.rb +1 -0
- data/spec/webdrivers/chrome_finder_spec.rb +103 -0
- data/spec/webdrivers/chromedriver_spec.rb +33 -15
- data/spec/webdrivers/edge_finder_spec.rb +52 -0
- data/spec/webdrivers/edgedriver_spec.rb +273 -0
- data/spec/webdrivers/geckodriver_spec.rb +45 -10
- data/spec/webdrivers/i_edriver_spec.rb +17 -12
- data/spec/webdrivers/system_spec.rb +79 -0
- data/spec/webdrivers/webdrivers_spec.rb +38 -26
- metadata +51 -24
- data/.github/ISSUE_TEMPLATE.md +0 -14
- data/.gitignore +0 -7
- data/.rubocop.yml +0 -45
- data/.travis.yml +0 -24
- data/Gemfile +0 -6
- data/Rakefile +0 -11
- data/appveyor.yml +0 -23
- data/webdrivers.gemspec +0 -33
data/lib/webdrivers/common.rb
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require 'rubygems/package'
|
|
4
|
-
require 'zip'
|
|
5
|
-
require 'webdrivers/logger'
|
|
6
4
|
require 'webdrivers/network'
|
|
7
5
|
require 'webdrivers/system'
|
|
8
6
|
require 'selenium-webdriver'
|
|
7
|
+
require 'webdrivers/logger'
|
|
9
8
|
require 'webdrivers/version'
|
|
10
9
|
|
|
11
10
|
module Webdrivers
|
|
@@ -18,15 +17,24 @@ module Webdrivers
|
|
|
18
17
|
class NetworkError < StandardError
|
|
19
18
|
end
|
|
20
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
|
+
|
|
21
26
|
class << self
|
|
22
27
|
attr_accessor :proxy_addr, :proxy_port, :proxy_user, :proxy_pass
|
|
23
28
|
attr_writer :install_dir, :cache_time
|
|
24
29
|
|
|
25
30
|
#
|
|
26
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).
|
|
27
34
|
#
|
|
28
35
|
def cache_time
|
|
29
|
-
|
|
36
|
+
@cache_time ||= (ENV['WD_CACHE_TIME'] || DEFAULT_CACHE_TIME)
|
|
37
|
+
@cache_time.to_i
|
|
30
38
|
end
|
|
31
39
|
|
|
32
40
|
#
|
|
@@ -34,7 +42,7 @@ module Webdrivers
|
|
|
34
42
|
#
|
|
35
43
|
# @return [String]
|
|
36
44
|
def install_dir
|
|
37
|
-
@install_dir
|
|
45
|
+
@install_dir ||= ENV['WD_INSTALL_DIR'] || DEFAULT_INSTALL_DIR
|
|
38
46
|
end
|
|
39
47
|
|
|
40
48
|
def logger
|
|
@@ -61,7 +69,7 @@ module Webdrivers
|
|
|
61
69
|
raise 'Webdrivers.net_http_ssl_fix is no longer available.' \
|
|
62
70
|
' Please see https://github.com/titusfortner/webdrivers#ssl_connect-errors.'
|
|
63
71
|
end
|
|
64
|
-
end
|
|
72
|
+
end
|
|
65
73
|
|
|
66
74
|
class Common
|
|
67
75
|
class << self
|
|
@@ -72,7 +80,7 @@ end
|
|
|
72
80
|
#
|
|
73
81
|
# @return [Gem::Version]
|
|
74
82
|
def required_version
|
|
75
|
-
normalize_version
|
|
83
|
+
normalize_version(@required_version ||= nil)
|
|
76
84
|
end
|
|
77
85
|
|
|
78
86
|
#
|
|
@@ -105,17 +113,17 @@ end
|
|
|
105
113
|
#
|
|
106
114
|
# @return [String]
|
|
107
115
|
def driver_path
|
|
108
|
-
File.join
|
|
116
|
+
File.absolute_path File.join(System.install_dir, file_name)
|
|
109
117
|
end
|
|
110
118
|
|
|
111
119
|
private
|
|
112
120
|
|
|
121
|
+
def download_version
|
|
122
|
+
required_version == EMPTY_VERSION ? latest_version : required_version
|
|
123
|
+
end
|
|
124
|
+
|
|
113
125
|
def download_url
|
|
114
|
-
@download_url ||=
|
|
115
|
-
downloads[downloads.keys.max]
|
|
116
|
-
else
|
|
117
|
-
downloads[normalize_version(required_version)]
|
|
118
|
-
end
|
|
126
|
+
@download_url ||= direct_url(download_version).tap { |url| Webdrivers.logger.debug "#{file_name} URL: #{url}" }
|
|
119
127
|
end
|
|
120
128
|
|
|
121
129
|
def exists?
|
|
@@ -123,11 +131,7 @@ end
|
|
|
123
131
|
end
|
|
124
132
|
|
|
125
133
|
def correct_binary?
|
|
126
|
-
current_version ==
|
|
127
|
-
latest_version
|
|
128
|
-
else
|
|
129
|
-
normalize_version(required_version)
|
|
130
|
-
end
|
|
134
|
+
current_version == download_version
|
|
131
135
|
rescue ConnectionError, VersionError
|
|
132
136
|
driver_path if sufficient_binary?
|
|
133
137
|
end
|
|
@@ -141,7 +145,7 @@ end
|
|
|
141
145
|
end
|
|
142
146
|
|
|
143
147
|
def binary_version
|
|
144
|
-
version = System.call(
|
|
148
|
+
version = System.call(driver_path, '--version')
|
|
145
149
|
Webdrivers.logger.debug "Current version of #{driver_path} is #{version}"
|
|
146
150
|
version
|
|
147
151
|
rescue Errno::ENOENT
|
|
@@ -149,9 +153,15 @@ end
|
|
|
149
153
|
nil
|
|
150
154
|
end
|
|
151
155
|
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
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
|
|
155
165
|
else
|
|
156
166
|
version = yield
|
|
157
167
|
System.cache_version(file_name, version)
|
|
@@ -0,0 +1,98 @@
|
|
|
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/microsoft/edge]
|
|
73
|
+
files = %w[microsoft-edge microsoft-edge-beta microsoft-edge-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
|
+
end
|
|
84
|
+
|
|
85
|
+
def win_version(location)
|
|
86
|
+
System.call("powershell (Get-ItemProperty '#{location}').VersionInfo.ProductVersion")&.strip
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def linux_version(location)
|
|
90
|
+
System.call(location, '--product-version')&.strip
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def mac_version(location)
|
|
94
|
+
System.call(location, '--version')&.strip
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
end
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'shellwords'
|
|
4
|
+
require 'webdrivers/common'
|
|
5
|
+
require 'webdrivers/chromedriver'
|
|
6
|
+
require 'webdrivers/edge_finder'
|
|
7
|
+
|
|
8
|
+
module Webdrivers
|
|
9
|
+
class Edgedriver < Chromedriver
|
|
10
|
+
class << self
|
|
11
|
+
undef :chrome_version
|
|
12
|
+
#
|
|
13
|
+
# Returns currently installed Edge version.
|
|
14
|
+
#
|
|
15
|
+
# @return [Gem::Version]
|
|
16
|
+
def browser_version
|
|
17
|
+
normalize_version EdgeFinder.version
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
#
|
|
21
|
+
# Returns url with domain for calls to get this driver.
|
|
22
|
+
#
|
|
23
|
+
# @return [String]
|
|
24
|
+
def base_url
|
|
25
|
+
'https://msedgedriver.azureedge.net'
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
private
|
|
29
|
+
|
|
30
|
+
def latest_point_release(version)
|
|
31
|
+
# Microsoft doesn't currently provide LATEST_RELEASE_X.Y.Z - only use X
|
|
32
|
+
# but require the driver version be >= the passed in version
|
|
33
|
+
str = Network.get(URI.join(base_url, "LATEST_RELEASE_#{version.segments[0]}"))
|
|
34
|
+
latest_release = normalize_version(str.encode('ASCII-8BIT', 'UTF-16'))
|
|
35
|
+
raise VersionError unless latest_release >= version
|
|
36
|
+
|
|
37
|
+
latest_release
|
|
38
|
+
rescue NetworkError, VersionError
|
|
39
|
+
msg = failed_to_find_message(version)
|
|
40
|
+
Webdrivers.logger.debug msg
|
|
41
|
+
raise VersionError, msg
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def failed_to_find_message(version)
|
|
45
|
+
msg = "Unable to find latest point release version for #{version}."
|
|
46
|
+
msg = begin
|
|
47
|
+
# str = Network.get(URI.join(base_url, 'LATEST_RELEASE'))
|
|
48
|
+
# Microsoft doesn't yet/ever support LATEST_RELEASE - Use Canary as latest
|
|
49
|
+
str = Network.get(URI.join(base_url, 'LATEST_CANARY'))
|
|
50
|
+
latest_release = normalize_version(str.encode('ASCII-8BIT', 'UTF-16'))
|
|
51
|
+
if version > latest_release
|
|
52
|
+
"#{msg} You appear to be using a non-production version of Edge."
|
|
53
|
+
else
|
|
54
|
+
msg
|
|
55
|
+
end
|
|
56
|
+
rescue NetworkError
|
|
57
|
+
"#{msg} A network issue is preventing determination of latest msedgedriver release."
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
"#{msg} Please set `Webdrivers::Edgedriver.required_version = <desired driver version>` "\
|
|
61
|
+
"to a known edgedriver version: Can not reach #{base_url}"
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def file_name
|
|
65
|
+
System.platform == 'win' ? 'msedgedriver.exe' : 'msedgedriver'
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def apple_m1_compatible?(driver_version)
|
|
69
|
+
if System.apple_m1_architecture? && driver_version >= normalize_version('87.0.669.0')
|
|
70
|
+
Webdrivers.logger.debug 'msedgedriver version is Apple M1 compatible.'
|
|
71
|
+
return true
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
Webdrivers.logger.debug 'msedgedriver version is NOT Apple M1 compatible. Required >= 87.0.669.0'
|
|
75
|
+
false
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def driver_filename(driver_version)
|
|
79
|
+
if System.platform == 'win' || System.wsl_v1?
|
|
80
|
+
"win#{System.bitsize}" # 32 or 64-bit
|
|
81
|
+
elsif System.platform == 'linux'
|
|
82
|
+
'linux64'
|
|
83
|
+
elsif System.platform == 'mac'
|
|
84
|
+
# Determine M1 or Intel architecture
|
|
85
|
+
apple_arch = apple_m1_compatible?(driver_version) ? 'arm' : 'mac'
|
|
86
|
+
"#{apple_arch}64"
|
|
87
|
+
else
|
|
88
|
+
raise 'Failed to determine driver filename to download for your OS.'
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def direct_url(driver_version)
|
|
93
|
+
"#{base_url}/#{driver_version}/edgedriver_#{driver_filename(driver_version)}.zip"
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
::Selenium::WebDriver::Edge::Service.driver_path = proc { ::Webdrivers::Edgedriver.update }
|
|
@@ -42,14 +42,6 @@ module Webdrivers
|
|
|
42
42
|
System.platform == 'win' ? 'geckodriver.exe' : 'geckodriver'
|
|
43
43
|
end
|
|
44
44
|
|
|
45
|
-
def download_url
|
|
46
|
-
@download_url ||= if required_version == EMPTY_VERSION
|
|
47
|
-
direct_url(latest_version)
|
|
48
|
-
else
|
|
49
|
-
direct_url(required_version)
|
|
50
|
-
end
|
|
51
|
-
end
|
|
52
|
-
|
|
53
45
|
def direct_url(version)
|
|
54
46
|
"#{base_url}/download/v#{version}/geckodriver-v#{version}-#{platform_ext}"
|
|
55
47
|
end
|
|
@@ -59,7 +51,7 @@ module Webdrivers
|
|
|
59
51
|
when 'linux'
|
|
60
52
|
"linux#{System.bitsize}.tar.gz"
|
|
61
53
|
when 'mac'
|
|
62
|
-
'macos.tar.gz'
|
|
54
|
+
System.apple_m1_architecture? ? 'macos-aarch64.tar.gz' : 'macos.tar.gz'
|
|
63
55
|
when 'win'
|
|
64
56
|
"win#{System.bitsize}.zip"
|
|
65
57
|
end
|
|
@@ -68,17 +60,4 @@ module Webdrivers
|
|
|
68
60
|
end
|
|
69
61
|
end
|
|
70
62
|
|
|
71
|
-
|
|
72
|
-
::Selenium::WebDriver::Firefox::Service.driver_path = proc { ::Webdrivers::Geckodriver.update }
|
|
73
|
-
else
|
|
74
|
-
# v3.141.0 and lower
|
|
75
|
-
module Selenium
|
|
76
|
-
module WebDriver
|
|
77
|
-
module Firefox
|
|
78
|
-
def self.driver_path
|
|
79
|
-
@driver_path ||= Webdrivers::Geckodriver.update
|
|
80
|
-
end
|
|
81
|
-
end
|
|
82
|
-
end
|
|
83
|
-
end
|
|
84
|
-
end
|
|
63
|
+
::Selenium::WebDriver::Firefox::Service.driver_path = proc { ::Webdrivers::Geckodriver.update }
|
data/lib/webdrivers/iedriver.rb
CHANGED
|
@@ -34,7 +34,7 @@ module Webdrivers
|
|
|
34
34
|
#
|
|
35
35
|
# @return [String]
|
|
36
36
|
def base_url
|
|
37
|
-
'https://
|
|
37
|
+
'https://api.github.com/repos/seleniumhq/selenium/releases'
|
|
38
38
|
end
|
|
39
39
|
|
|
40
40
|
private
|
|
@@ -43,32 +43,26 @@ module Webdrivers
|
|
|
43
43
|
'IEDriverServer.exe'
|
|
44
44
|
end
|
|
45
45
|
|
|
46
|
+
def direct_url(version)
|
|
47
|
+
downloads[version]
|
|
48
|
+
end
|
|
49
|
+
|
|
46
50
|
def downloads
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
ds = items.each_with_object({}) do |item, hash|
|
|
51
|
-
key = normalize_version item[/([^_]+)\.zip/, 1]
|
|
52
|
-
hash[key] = "#{base_url}#{item}"
|
|
51
|
+
ds = download_manifest.each_with_object({}) do |item, hash|
|
|
52
|
+
version = normalize_version item['name'][/\.?([^_]+)\.zip/, 1]
|
|
53
|
+
hash[version] = item['browser_download_url']
|
|
53
54
|
end
|
|
54
55
|
Webdrivers.logger.debug "Versions now located on downloads site: #{ds.keys}"
|
|
55
56
|
ds
|
|
56
57
|
end
|
|
57
|
-
end
|
|
58
|
-
end
|
|
59
|
-
end
|
|
60
58
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
module Selenium
|
|
66
|
-
module WebDriver
|
|
67
|
-
module IE
|
|
68
|
-
def self.driver_path
|
|
69
|
-
@driver_path ||= Webdrivers::IEdriver.update
|
|
70
|
-
end
|
|
59
|
+
def download_manifest
|
|
60
|
+
json = Network.get(base_url)
|
|
61
|
+
all_assets = JSON.parse(json).map { |release| release['assets'] }.flatten
|
|
62
|
+
all_assets.select { |asset| asset['name'].include?('IEDriverServer_Win32') }
|
|
71
63
|
end
|
|
72
64
|
end
|
|
73
65
|
end
|
|
74
66
|
end
|
|
67
|
+
|
|
68
|
+
::Selenium::WebDriver::IE::Service.driver_path = proc { ::Webdrivers::IEdriver.update }
|
data/lib/webdrivers/logger.rb
CHANGED
|
@@ -1,11 +1,5 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require 'forwardable'
|
|
4
|
-
require 'logger'
|
|
5
|
-
|
|
6
|
-
# Code adapted from Selenium Implementation
|
|
7
|
-
# https://github.com/SeleniumHQ/selenium/blob/master/rb/lib/selenium/webdriver/common/logger.rb
|
|
8
|
-
|
|
9
3
|
module Webdrivers
|
|
10
4
|
#
|
|
11
5
|
# @example Enable full logging
|
|
@@ -18,94 +12,9 @@ module Webdrivers
|
|
|
18
12
|
# Webdrivers.logger.info('This is info message')
|
|
19
13
|
# Webdrivers.logger.warn('This is warning message')
|
|
20
14
|
#
|
|
21
|
-
class Logger
|
|
22
|
-
extend Forwardable
|
|
23
|
-
include ::Logger::Severity
|
|
24
|
-
|
|
25
|
-
def_delegators :@logger, :debug, :debug?,
|
|
26
|
-
:info, :info?,
|
|
27
|
-
:warn, :warn?,
|
|
28
|
-
:error, :error?,
|
|
29
|
-
:fatal, :fatal?,
|
|
30
|
-
:level
|
|
31
|
-
|
|
15
|
+
class Logger < Selenium::WebDriver::Logger
|
|
32
16
|
def initialize
|
|
33
|
-
|
|
34
|
-
end
|
|
35
|
-
|
|
36
|
-
def output=(io)
|
|
37
|
-
# `Logger#reopen` was added in Ruby 2.3
|
|
38
|
-
if @logger.respond_to?(:reopen)
|
|
39
|
-
@logger.reopen(io)
|
|
40
|
-
else
|
|
41
|
-
@logger = create_logger(io)
|
|
42
|
-
end
|
|
43
|
-
end
|
|
44
|
-
|
|
45
|
-
#
|
|
46
|
-
# For Ruby < 2.3 compatibility
|
|
47
|
-
# Based on https://github.com/ruby/ruby/blob/ruby_2_3/lib/logger.rb#L250
|
|
48
|
-
#
|
|
49
|
-
|
|
50
|
-
def level=(severity)
|
|
51
|
-
if severity.is_a?(Integer)
|
|
52
|
-
@logger.level = severity
|
|
53
|
-
else
|
|
54
|
-
case severity.to_s.downcase
|
|
55
|
-
when 'debug'
|
|
56
|
-
@logger.level = DEBUG
|
|
57
|
-
when 'info'
|
|
58
|
-
@logger.level = INFO
|
|
59
|
-
when 'warn'
|
|
60
|
-
@logger.level = WARN
|
|
61
|
-
when 'error'
|
|
62
|
-
@logger.level = ERROR
|
|
63
|
-
when 'fatal'
|
|
64
|
-
@logger.level = FATAL
|
|
65
|
-
when 'unknown'
|
|
66
|
-
@logger.level = UNKNOWN
|
|
67
|
-
else
|
|
68
|
-
raise ArgumentError, "invalid log level: #{severity}"
|
|
69
|
-
end
|
|
70
|
-
end
|
|
71
|
-
end
|
|
72
|
-
|
|
73
|
-
#
|
|
74
|
-
# Returns IO object used by logger internally.
|
|
75
|
-
#
|
|
76
|
-
# Normally, we would have never needed it, but we want to
|
|
77
|
-
# use it as IO object for all child processes to ensure their
|
|
78
|
-
# output is redirected there.
|
|
79
|
-
#
|
|
80
|
-
# It is only used in debug level, in other cases output is suppressed.
|
|
81
|
-
#
|
|
82
|
-
# @api private
|
|
83
|
-
#
|
|
84
|
-
def io
|
|
85
|
-
@logger.instance_variable_get(:@logdev).instance_variable_get(:@dev)
|
|
86
|
-
end
|
|
87
|
-
|
|
88
|
-
#
|
|
89
|
-
# Marks code as deprecated with replacement.
|
|
90
|
-
#
|
|
91
|
-
# @param [String] old
|
|
92
|
-
# @param [String] new
|
|
93
|
-
#
|
|
94
|
-
def deprecate(old, new)
|
|
95
|
-
warn "[DEPRECATION] #{old} is deprecated. Use #{new} instead."
|
|
96
|
-
end
|
|
97
|
-
|
|
98
|
-
private
|
|
99
|
-
|
|
100
|
-
def create_logger(output)
|
|
101
|
-
logger = ::Logger.new(output)
|
|
102
|
-
logger.progname = 'Webdrivers'
|
|
103
|
-
logger.level = ($DEBUG ? DEBUG : WARN)
|
|
104
|
-
logger.formatter = proc do |severity, time, progname, msg|
|
|
105
|
-
"#{time.strftime('%F %T')} #{severity} #{progname} #{msg}\n"
|
|
106
|
-
end
|
|
107
|
-
|
|
108
|
-
logger
|
|
17
|
+
super('Webdrivers')
|
|
109
18
|
end
|
|
110
19
|
end
|
|
111
20
|
end
|
data/lib/webdrivers/network.rb
CHANGED
data/lib/webdrivers/railtie.rb
CHANGED
data/lib/webdrivers/system.rb
CHANGED
|
@@ -2,6 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
require 'rubygems/package'
|
|
4
4
|
require 'zip'
|
|
5
|
+
require 'English'
|
|
6
|
+
|
|
7
|
+
# validate zip entry sizes to avoid zip bombs
|
|
8
|
+
# see https://github.com/rubyzip/rubyzip#size-validation
|
|
9
|
+
# and https://github.com/rubyzip/rubyzip/pull/403 for further details
|
|
10
|
+
# this will be the default in rubyzip 2.0+
|
|
11
|
+
Zip.validate_entry_sizes = true
|
|
5
12
|
|
|
6
13
|
module Webdrivers
|
|
7
14
|
#
|
|
@@ -13,11 +20,13 @@ module Webdrivers
|
|
|
13
20
|
max_attempts = 3
|
|
14
21
|
attempts_made = 0
|
|
15
22
|
delay = 0.5
|
|
16
|
-
Webdrivers.logger.debug "Deleting #{file}"
|
|
17
23
|
|
|
18
24
|
begin
|
|
19
25
|
attempts_made += 1
|
|
20
|
-
|
|
26
|
+
if File.exist? file
|
|
27
|
+
Webdrivers.logger.debug "Deleting #{file}"
|
|
28
|
+
File.delete file
|
|
29
|
+
end
|
|
21
30
|
rescue Errno::EACCES # Solves an intermittent file locking issue on Windows
|
|
22
31
|
sleep(delay)
|
|
23
32
|
retry if File.exist?(file) && attempts_made <= max_attempts
|
|
@@ -89,7 +98,7 @@ module Webdrivers
|
|
|
89
98
|
when /tar\.bz2$/
|
|
90
99
|
untarbz2_file(tempfile)
|
|
91
100
|
when /\.zip$/
|
|
92
|
-
unzip_file(tempfile)
|
|
101
|
+
unzip_file(tempfile, File.basename(target))
|
|
93
102
|
else
|
|
94
103
|
Webdrivers.logger.debug 'No Decompression needed'
|
|
95
104
|
FileUtils.cp(tempfile, File.join(Dir.pwd, file_name))
|
|
@@ -114,19 +123,17 @@ module Webdrivers
|
|
|
114
123
|
end
|
|
115
124
|
end
|
|
116
125
|
|
|
117
|
-
def unzip_file(filename)
|
|
126
|
+
def unzip_file(filename, driver_name)
|
|
118
127
|
Webdrivers.logger.debug "Decompressing #{filename}"
|
|
119
128
|
|
|
120
129
|
Zip::File.open(filename) do |zip_file|
|
|
121
|
-
zip_file.
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
zip_file.extract(f, f_path)
|
|
127
|
-
end
|
|
130
|
+
driver = zip_file.get_entry(driver_name)
|
|
131
|
+
f_path = File.join(Dir.pwd, driver.name)
|
|
132
|
+
delete(f_path)
|
|
133
|
+
FileUtils.mkdir_p(File.dirname(f_path)) unless File.exist?(File.dirname(f_path))
|
|
134
|
+
zip_file.extract(driver, f_path)
|
|
128
135
|
end
|
|
129
|
-
|
|
136
|
+
driver_name
|
|
130
137
|
end
|
|
131
138
|
|
|
132
139
|
def platform
|
|
@@ -141,13 +148,49 @@ module Webdrivers
|
|
|
141
148
|
end
|
|
142
149
|
end
|
|
143
150
|
|
|
151
|
+
def apple_m1_architecture?
|
|
152
|
+
if platform == 'mac' && RUBY_PLATFORM.include?('arm64-darwin')
|
|
153
|
+
Webdrivers.logger.debug 'Apple architecture: M1 (arm64-darwin)'
|
|
154
|
+
return true
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
Webdrivers.logger.debug 'Apple architecture: Intel (mac64)'
|
|
158
|
+
false
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
# @return [TrueClass, FalseClass]
|
|
162
|
+
def wsl_v1?
|
|
163
|
+
platform == 'linux' && File.open('/proc/version').read.include?('Microsoft')
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
# @param [String] path
|
|
167
|
+
# @return [String]
|
|
168
|
+
def to_win32_path(path)
|
|
169
|
+
return path if /[a-z]:\\/iu.match?(path)
|
|
170
|
+
|
|
171
|
+
call("wslpath -w '#{path}'").chomp
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
# @param [String] path
|
|
175
|
+
# @return [String]
|
|
176
|
+
def to_wsl_path(path)
|
|
177
|
+
call("wslpath -u '#{path}'").chomp
|
|
178
|
+
end
|
|
179
|
+
|
|
144
180
|
def bitsize
|
|
145
181
|
Selenium::WebDriver::Platform.bitsize
|
|
146
182
|
end
|
|
147
183
|
|
|
148
|
-
def call(
|
|
184
|
+
def call(process, arg = nil)
|
|
185
|
+
cmd = arg ? [process, arg] : process # Windows provides powershell command (process) only, no args.
|
|
149
186
|
Webdrivers.logger.debug "making System call: #{cmd}"
|
|
150
|
-
|
|
187
|
+
p = IO.popen(cmd)
|
|
188
|
+
out = p.read
|
|
189
|
+
p.close
|
|
190
|
+
raise "Failed to make system call: #{cmd}" unless $CHILD_STATUS.success?
|
|
191
|
+
|
|
192
|
+
Webdrivers.logger.debug "System call returned: #{out}"
|
|
193
|
+
out
|
|
151
194
|
end
|
|
152
195
|
end
|
|
153
196
|
end
|
|
@@ -19,8 +19,6 @@ namespace :webdrivers do
|
|
|
19
19
|
desc 'Remove and download updated chromedriver if necessary'
|
|
20
20
|
task :update, [:version] do |_, args|
|
|
21
21
|
args.with_defaults(version: 0)
|
|
22
|
-
Webdrivers.cache_time = ENV.fetch('WD_CACHE_TIME', 86_400)
|
|
23
|
-
Webdrivers.install_dir = ENV.fetch('WD_INSTALL_DIR', nil)
|
|
24
22
|
Webdrivers::Chromedriver.required_version = args.version
|
|
25
23
|
Webdrivers::Chromedriver.update
|
|
26
24
|
Webdrivers.logger.info "Updated to chromedriver #{Webdrivers::Chromedriver.current_version}"
|