webdrivers 2.3.2 → 4.7.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 +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
@@ -1,34 +1,104 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
|
3
|
+
require 'shellwords'
|
4
|
+
require 'webdrivers/common'
|
5
|
+
require 'webdrivers/chromedriver'
|
6
|
+
require 'webdrivers/edge_finder'
|
5
7
|
|
8
|
+
module Webdrivers
|
9
|
+
class Edgedriver < Chromedriver
|
6
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://developer.microsoft.com/en-us/microsoft-edge/tools/webdriver/'
|
26
|
+
'https://msedgedriver.azureedge.net/'
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def latest_point_release(version)
|
32
|
+
# Microsoft doesn't currently provide LATEST_RELEASE_X.Y.Z - only use X
|
33
|
+
# but require the driver version be >= the passed in version
|
34
|
+
str = Network.get(URI.join(base_url, "LATEST_RELEASE_#{version.segments[0]}"))
|
35
|
+
latest_release = normalize_version(str.encode('ASCII-8BIT', 'UTF-16'))
|
36
|
+
raise VersionError unless latest_release >= version
|
37
|
+
|
38
|
+
latest_release
|
39
|
+
rescue NetworkError, VersionError
|
40
|
+
msg = failed_to_find_message(version)
|
41
|
+
Webdrivers.logger.debug msg
|
42
|
+
raise VersionError, msg
|
43
|
+
end
|
44
|
+
|
45
|
+
def failed_to_find_message(version)
|
46
|
+
msg = "Unable to find latest point release version for #{version}."
|
47
|
+
msg = begin
|
48
|
+
# str = Network.get(URI.join(base_url, 'LATEST_RELEASE'))
|
49
|
+
# Microsoft doesn't yet/ever support LATEST_RELEASE - Use Canary as latest
|
50
|
+
str = Network.get(URI.join(base_url, 'LATEST_CANARY'))
|
51
|
+
latest_release = normalize_version(str.encode('ASCII-8BIT', 'UTF-16'))
|
52
|
+
if version > latest_release
|
53
|
+
"#{msg} You appear to be using a non-production version of Edge."
|
54
|
+
else
|
55
|
+
msg
|
56
|
+
end
|
57
|
+
rescue NetworkError
|
58
|
+
"#{msg} A network issue is preventing determination of latest msedgedriver release."
|
59
|
+
end
|
60
|
+
|
61
|
+
"#{msg} Please set `Webdrivers::Edgedriver.required_version = <desired driver version>` "\
|
62
|
+
"to a known edgedriver version: Can not reach #{base_url}"
|
63
|
+
end
|
64
|
+
|
7
65
|
def file_name
|
8
|
-
|
66
|
+
System.platform == 'win' ? 'msedgedriver.exe' : 'msedgedriver'
|
9
67
|
end
|
10
68
|
|
11
|
-
def
|
12
|
-
|
69
|
+
def apple_m1_compatible?(driver_version)
|
70
|
+
if System.apple_m1_architecture? && driver_version >= normalize_version('87.0.669.0')
|
71
|
+
Webdrivers.logger.debug 'msedgedriver version is Apple M1 compatible.'
|
72
|
+
return true
|
73
|
+
end
|
74
|
+
|
75
|
+
Webdrivers.logger.debug 'msedgedriver version is NOT Apple M1 compatible. Required >= 87.0.669.0'
|
76
|
+
false
|
13
77
|
end
|
14
78
|
|
15
|
-
def
|
16
|
-
|
17
|
-
version[/\d+\.\d+\.\d+/][/[^\.]\d+$/]
|
79
|
+
def linux_compatible?(driver_version)
|
80
|
+
System.platform == 'linux' && driver_version >= normalize_version('89.0.731.0')
|
18
81
|
end
|
19
82
|
|
20
|
-
def
|
21
|
-
if
|
22
|
-
|
83
|
+
def driver_filename(driver_version)
|
84
|
+
if System.platform == 'win' || System.wsl_v1?
|
85
|
+
"win#{System.bitsize}" # 32 or 64-bit
|
86
|
+
elsif linux_compatible?(driver_version)
|
87
|
+
'linux64'
|
88
|
+
elsif System.platform == 'mac'
|
89
|
+
# Determine M1 or Intel architecture
|
90
|
+
apple_arch = apple_m1_compatible?(driver_version) ? 'arm' : 'mac'
|
91
|
+
"#{apple_arch}64"
|
23
92
|
else
|
24
|
-
'
|
93
|
+
raise 'Failed to determine driver filename to download for your OS.'
|
25
94
|
end
|
26
95
|
end
|
27
96
|
|
28
|
-
def
|
29
|
-
|
97
|
+
def direct_url(driver_version)
|
98
|
+
"#{base_url}/#{driver_version}/edgedriver_#{driver_filename(driver_version)}.zip"
|
30
99
|
end
|
31
100
|
end
|
32
|
-
|
33
101
|
end
|
34
|
-
end
|
102
|
+
end
|
103
|
+
|
104
|
+
::Selenium::WebDriver::Edge::Service.driver_path = proc { ::Webdrivers::Edgedriver.update }
|
@@ -1,42 +1,63 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'nokogiri'
|
4
|
+
require 'webdrivers/common'
|
2
5
|
|
3
6
|
module Webdrivers
|
4
7
|
class Geckodriver < Common
|
5
|
-
|
6
8
|
class << self
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
9
|
+
#
|
10
|
+
# Returns current geckodriver version.
|
11
|
+
#
|
12
|
+
# @return [Gem::Version]
|
11
13
|
def current_version
|
12
|
-
|
13
|
-
|
14
|
-
end
|
14
|
+
Webdrivers.logger.debug 'Checking current version'
|
15
|
+
return nil unless exists?
|
15
16
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
hash["#{matched[1]}.#{minor}.#{matched[3]}"] = version
|
21
|
-
end
|
22
|
-
padded.keys.sort.last
|
17
|
+
version = binary_version
|
18
|
+
return nil if version.nil?
|
19
|
+
|
20
|
+
normalize_version version.match(/geckodriver (\d+\.\d+\.\d+)/)[1]
|
23
21
|
end
|
24
22
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
hash[item[/v(\d+\.\d+\.\d+)/, 1]] = "https://github.com#{item}"
|
32
|
-
end
|
23
|
+
#
|
24
|
+
# Returns latest available geckodriver version.
|
25
|
+
#
|
26
|
+
# @return [Gem::Version]
|
27
|
+
def latest_version
|
28
|
+
@latest_version ||= with_cache(file_name) { normalize_version(Network.get_url("#{base_url}/latest")[/[^v]*$/]) }
|
33
29
|
end
|
34
30
|
|
31
|
+
#
|
32
|
+
# Returns url with domain for calls to get this driver.
|
33
|
+
#
|
34
|
+
# @return [String]
|
35
35
|
def base_url
|
36
36
|
'https://github.com/mozilla/geckodriver/releases'
|
37
37
|
end
|
38
38
|
|
39
|
-
|
39
|
+
private
|
40
40
|
|
41
|
+
def file_name
|
42
|
+
System.platform == 'win' ? 'geckodriver.exe' : 'geckodriver'
|
43
|
+
end
|
44
|
+
|
45
|
+
def direct_url(version)
|
46
|
+
"#{base_url}/download/v#{version}/geckodriver-v#{version}-#{platform_ext}"
|
47
|
+
end
|
48
|
+
|
49
|
+
def platform_ext
|
50
|
+
case System.platform
|
51
|
+
when 'linux'
|
52
|
+
"linux#{System.bitsize}.tar.gz"
|
53
|
+
when 'mac'
|
54
|
+
'macos.tar.gz'
|
55
|
+
when 'win'
|
56
|
+
"win#{System.bitsize}.zip"
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
41
60
|
end
|
42
|
-
end
|
61
|
+
end
|
62
|
+
|
63
|
+
::Selenium::WebDriver::Firefox::Service.driver_path = proc { ::Webdrivers::Geckodriver.update }
|
data/lib/webdrivers/iedriver.rb
CHANGED
@@ -1,35 +1,68 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'nokogiri'
|
4
|
+
require 'rubygems/version'
|
5
|
+
require 'webdrivers/common'
|
2
6
|
|
3
7
|
module Webdrivers
|
4
|
-
class
|
5
|
-
|
8
|
+
class IEdriver < Common
|
6
9
|
class << self
|
7
|
-
|
8
|
-
|
10
|
+
#
|
11
|
+
# Returns current IEDriverServer.exe 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
|
+
normalize_version version.match(/IEDriverServer.exe (\d\.\d+\.\d+)/)[1]
|
9
22
|
end
|
10
23
|
|
11
|
-
|
12
|
-
|
13
|
-
|
24
|
+
#
|
25
|
+
# Returns latest available IEDriverServer.exe version.
|
26
|
+
#
|
27
|
+
# @return [Gem::Version]
|
28
|
+
def latest_version
|
29
|
+
@latest_version ||= with_cache(file_name) { downloads.keys.max }
|
14
30
|
end
|
15
31
|
|
16
|
-
|
17
|
-
|
32
|
+
#
|
33
|
+
# Returns url with domain for calls to get this driver.
|
34
|
+
#
|
35
|
+
# @return [String]
|
36
|
+
def base_url
|
37
|
+
'https://api.github.com/repos/seleniumhq/selenium/releases'
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
def file_name
|
43
|
+
'IEDriverServer.exe'
|
44
|
+
end
|
45
|
+
|
46
|
+
def direct_url(version)
|
47
|
+
downloads[version]
|
18
48
|
end
|
19
49
|
|
20
50
|
def downloads
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
items.each_with_object({}) do |item, hash|
|
25
|
-
hash[item[/^[^\/]+/]] = "#{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']
|
26
54
|
end
|
55
|
+
Webdrivers.logger.debug "Versions now located on downloads site: #{ds.keys}"
|
56
|
+
ds
|
27
57
|
end
|
28
58
|
|
29
|
-
def
|
30
|
-
|
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') }
|
31
63
|
end
|
32
64
|
end
|
33
|
-
|
34
65
|
end
|
35
|
-
end
|
66
|
+
end
|
67
|
+
|
68
|
+
::Selenium::WebDriver::IE::Service.driver_path = proc { ::Webdrivers::IEdriver.update }
|
@@ -0,0 +1,111 @@
|
|
1
|
+
# frozen_string_literal: true
|
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
|
+
module Webdrivers
|
10
|
+
#
|
11
|
+
# @example Enable full logging
|
12
|
+
# Webdrivers.logger.level = :debug
|
13
|
+
#
|
14
|
+
# @example Log to file
|
15
|
+
# Webdrivers.logger.output = 'webdrivers.log'
|
16
|
+
#
|
17
|
+
# @example Use logger manually
|
18
|
+
# Webdrivers.logger.info('This is info message')
|
19
|
+
# Webdrivers.logger.warn('This is warning message')
|
20
|
+
#
|
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
|
+
|
32
|
+
def initialize
|
33
|
+
@logger = create_logger($stdout)
|
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
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'net/http'
|
4
|
+
|
5
|
+
module Webdrivers
|
6
|
+
#
|
7
|
+
# @api private
|
8
|
+
#
|
9
|
+
class Network
|
10
|
+
class << self
|
11
|
+
def get(url, limit = 10)
|
12
|
+
Webdrivers.logger.debug "Making network call to #{url}"
|
13
|
+
|
14
|
+
response = get_response(url, limit)
|
15
|
+
case response
|
16
|
+
when Net::HTTPSuccess
|
17
|
+
response.body
|
18
|
+
else
|
19
|
+
raise NetworkError, "#{response.class::EXCEPTION_TYPE}: #{response.code} \"#{response.message}\" with #{url}"
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def get_url(url, limit = 10)
|
24
|
+
Webdrivers.logger.debug "Making network call to #{url}"
|
25
|
+
|
26
|
+
get_response(url, limit).uri.to_s
|
27
|
+
end
|
28
|
+
|
29
|
+
def get_response(url, limit = 10)
|
30
|
+
raise ConnectionError, 'Too many HTTP redirects' if limit.zero?
|
31
|
+
|
32
|
+
begin
|
33
|
+
response = http.get_response(URI(url))
|
34
|
+
rescue SocketError
|
35
|
+
raise ConnectionError, "Can not reach #{url}"
|
36
|
+
end
|
37
|
+
|
38
|
+
Webdrivers.logger.debug "Get response: #{response.inspect}"
|
39
|
+
|
40
|
+
if response.is_a?(Net::HTTPRedirection)
|
41
|
+
location = response['location']
|
42
|
+
Webdrivers.logger.debug "Redirected to #{location}"
|
43
|
+
get_response(location, limit - 1)
|
44
|
+
else
|
45
|
+
response
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def http
|
50
|
+
if using_proxy
|
51
|
+
Net::HTTP.Proxy(Webdrivers.proxy_addr, Webdrivers.proxy_port,
|
52
|
+
Webdrivers.proxy_user, Webdrivers.proxy_pass)
|
53
|
+
else
|
54
|
+
Net::HTTP
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def using_proxy
|
59
|
+
Webdrivers.proxy_addr && Webdrivers.proxy_port
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'webdrivers'
|
4
|
+
require 'rails'
|
5
|
+
|
6
|
+
module Webdrivers
|
7
|
+
class Railtie < Rails::Railtie
|
8
|
+
railtie_name :webdrivers
|
9
|
+
|
10
|
+
rake_tasks do
|
11
|
+
path = File.expand_path(__dir__)
|
12
|
+
Dir.glob("#{path}/tasks/*.rake").each { |f| load f }
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,197 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'rubygems/package'
|
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
|
12
|
+
|
13
|
+
module Webdrivers
|
14
|
+
#
|
15
|
+
# @api private
|
16
|
+
#
|
17
|
+
class System
|
18
|
+
class << self
|
19
|
+
def delete(file)
|
20
|
+
max_attempts = 3
|
21
|
+
attempts_made = 0
|
22
|
+
delay = 0.5
|
23
|
+
|
24
|
+
begin
|
25
|
+
attempts_made += 1
|
26
|
+
if File.exist? file
|
27
|
+
Webdrivers.logger.debug "Deleting #{file}"
|
28
|
+
File.delete file
|
29
|
+
end
|
30
|
+
rescue Errno::EACCES # Solves an intermittent file locking issue on Windows
|
31
|
+
sleep(delay)
|
32
|
+
retry if File.exist?(file) && attempts_made <= max_attempts
|
33
|
+
raise
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def install_dir
|
38
|
+
Webdrivers.install_dir
|
39
|
+
end
|
40
|
+
|
41
|
+
def cache_version(file_name, version)
|
42
|
+
FileUtils.mkdir_p(install_dir) unless File.exist?(install_dir)
|
43
|
+
|
44
|
+
File.open("#{install_dir}/#{file_name.gsub('.exe', '')}.version", 'w+') do |file|
|
45
|
+
file.print(version)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def cached_version(file_name)
|
50
|
+
File.open("#{install_dir}/#{file_name.gsub('.exe', '')}.version", 'r', &:read)
|
51
|
+
end
|
52
|
+
|
53
|
+
def valid_cache?(file_name)
|
54
|
+
file = "#{install_dir}/#{file_name.gsub('.exe', '')}.version"
|
55
|
+
return false unless File.exist?(file)
|
56
|
+
|
57
|
+
Time.now - File.mtime(file) < Webdrivers.cache_time
|
58
|
+
end
|
59
|
+
|
60
|
+
def download(url, target)
|
61
|
+
FileUtils.mkdir_p(install_dir) unless File.exist?(install_dir)
|
62
|
+
|
63
|
+
download_file(url, target)
|
64
|
+
|
65
|
+
FileUtils.chmod 'ugo+rx', target
|
66
|
+
Webdrivers.logger.debug "Completed download and processing of #{target}"
|
67
|
+
target
|
68
|
+
end
|
69
|
+
|
70
|
+
def download_file(url, target)
|
71
|
+
file_name = File.basename(url)
|
72
|
+
Dir.chdir(install_dir) do
|
73
|
+
tempfile = Tempfile.open(['', file_name], binmode: true) do |file|
|
74
|
+
file.print Network.get(url)
|
75
|
+
file
|
76
|
+
end
|
77
|
+
|
78
|
+
raise "Could not download #{url}" unless File.exist?(tempfile.to_path)
|
79
|
+
|
80
|
+
Webdrivers.logger.debug "Successfully downloaded #{tempfile.to_path}"
|
81
|
+
|
82
|
+
decompress_file(tempfile, file_name, target)
|
83
|
+
tempfile.close!
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
def exists?(file)
|
88
|
+
result = File.exist? file
|
89
|
+
Webdrivers.logger.debug "#{file} is#{' not' unless result} already downloaded"
|
90
|
+
result
|
91
|
+
end
|
92
|
+
|
93
|
+
def decompress_file(tempfile, file_name, target)
|
94
|
+
tempfile = tempfile.to_path
|
95
|
+
case tempfile
|
96
|
+
when /tar\.gz$/
|
97
|
+
untargz_file(tempfile, File.basename(target))
|
98
|
+
when /tar\.bz2$/
|
99
|
+
untarbz2_file(tempfile)
|
100
|
+
when /\.zip$/
|
101
|
+
unzip_file(tempfile, File.basename(target))
|
102
|
+
else
|
103
|
+
Webdrivers.logger.debug 'No Decompression needed'
|
104
|
+
FileUtils.cp(tempfile, File.join(Dir.pwd, file_name))
|
105
|
+
end
|
106
|
+
raise "Could not decompress #{file_name} to get #{target}" unless File.exist?(File.basename(target))
|
107
|
+
end
|
108
|
+
|
109
|
+
def untarbz2_file(filename)
|
110
|
+
Webdrivers.logger.debug "Decompressing #{filename}"
|
111
|
+
|
112
|
+
call("tar xjf #{filename}").gsub('.tar.bz2', '')
|
113
|
+
end
|
114
|
+
|
115
|
+
def untargz_file(source, target)
|
116
|
+
Webdrivers.logger.debug "Decompressing #{source}"
|
117
|
+
|
118
|
+
tar_extract = Gem::Package::TarReader.new(Zlib::GzipReader.open(source))
|
119
|
+
|
120
|
+
File.open(target, 'w+b') do |ucf|
|
121
|
+
tar_extract.each { |entry| ucf << entry.read }
|
122
|
+
File.basename ucf
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
def unzip_file(filename, driver_name)
|
127
|
+
Webdrivers.logger.debug "Decompressing #{filename}"
|
128
|
+
|
129
|
+
Zip::File.open(filename) do |zip_file|
|
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)
|
135
|
+
end
|
136
|
+
driver_name
|
137
|
+
end
|
138
|
+
|
139
|
+
def platform
|
140
|
+
if Selenium::WebDriver::Platform.linux?
|
141
|
+
'linux'
|
142
|
+
elsif Selenium::WebDriver::Platform.mac?
|
143
|
+
'mac'
|
144
|
+
elsif Selenium::WebDriver::Platform.windows?
|
145
|
+
'win'
|
146
|
+
else
|
147
|
+
raise NotImplementedError, 'Your OS is not supported by webdrivers gem.'
|
148
|
+
end
|
149
|
+
end
|
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
|
+
|
180
|
+
def bitsize
|
181
|
+
Selenium::WebDriver::Platform.bitsize
|
182
|
+
end
|
183
|
+
|
184
|
+
def call(process, arg = nil)
|
185
|
+
cmd = arg ? [process, arg] : process # Windows provides powershell command (process) only, no args.
|
186
|
+
Webdrivers.logger.debug "making System call: #{cmd}"
|
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
|
194
|
+
end
|
195
|
+
end
|
196
|
+
end
|
197
|
+
end
|