chauffeur 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +5 -0
- data/.overcommit.yml +33 -0
- data/.rubocop.yml +13 -0
- data/Gemfile +8 -0
- data/Readme.md +94 -0
- data/bin/chauffeur +52 -0
- data/chauffeur.gemspec +24 -0
- data/lib/chauffeur/config.yml +30 -0
- data/lib/chauffeur/downloaders/chromedriver_downloader.rb +43 -0
- data/lib/chauffeur/downloaders/edgedriver_downloader.rb +44 -0
- data/lib/chauffeur/downloaders/firefoxdriver_downloader.rb +42 -0
- data/lib/chauffeur/downloaders/iedriver_downloader.rb +44 -0
- data/lib/chauffeur/driver_downloader.rb +177 -0
- data/lib/chauffeur/help.txt +60 -0
- data/lib/chauffeur/path_expander.rb +90 -0
- data/lib/chauffeur/requires.rb +15 -0
- data/lib/chauffeur/setup.rb +36 -0
- data/lib/chauffeur/unknown_platform_error.rb +10 -0
- data/lib/chauffeur/unknown_version_error.rb +7 -0
- data/lib/chauffeur.rb +83 -0
- data/lib/pry_playground.rb +4 -0
- data/spec/chromedriver_downloader_spec.rb +82 -0
- data/spec/chromedriver_downloader_specs/chromedriver_downloader_overridden_methods_spec.rb +79 -0
- data/spec/chromedriver_downloader_specs/chromedriver_downloader_simple_spec.rb +22 -0
- data/spec/driver_downloader_specs/driver_downloader_error_spec.rb +26 -0
- data/spec/driver_versions_spec.rb +29 -0
- data/spec/edgedriver_downloader_specs/edgedriver_downloader_overridden_methods.rb +58 -0
- data/spec/edgedriver_downloader_specs/edgedriver_downloader_simple_spec.rb +22 -0
- data/spec/firefoxdriver_downloader_specs/firefoxdriver_downloader_overridden_methods_spec.rb +86 -0
- data/spec/firefoxdriver_downloader_specs/firefoxdriver_downloader_simple_spec.rb +22 -0
- data/spec/format_for_platform_spec.rb +59 -0
- data/spec/helpers/spec_helper.rb +4 -0
- data/spec/iedriver_downloader_spec.rb +17 -0
- data/spec/iedriver_downloader_specs/iedriver_downloader_overridden_methods_spec.rb +65 -0
- data/spec/iedriver_downloader_specs/iedriver_downloader_simple_spec.rb +22 -0
- data/spec/path_expansion_spec.rb +43 -0
- data/spec/setup_spec.rb +48 -0
- metadata +165 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 42cda14add9e38bfb16fa01dd90d7375880f4d294f93087efa6a918da5e08c24
|
4
|
+
data.tar.gz: 127de41984c2a30e3ab044d4d1a283d63e1f8f7e0d90df866f56121b1f4b1f15
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 02a9aec896b3fc05fc53b70c4508f8bc8d51f0c504c2b2110836b2a9376e90589bfd7c9009f660fc1421623d886b93a040c4117aa63eb9f1b91ebdc53f814b42
|
7
|
+
data.tar.gz: f2cbb732bcee843e24d76c7d062aeedb0adb46ac1286d82744b905e679c6c0f319756c9b3dfb471d138037cfff6e51d81db3399f43731c4c731386c69d766243
|
data/.gitignore
ADDED
data/.overcommit.yml
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
# Use this file to configure the Overcommit hooks you wish to use. This will
|
2
|
+
# extend the default configuration defined in:
|
3
|
+
# https://github.com/brigade/overcommit/blob/master/config/default.yml
|
4
|
+
#
|
5
|
+
# At the topmost level of this YAML file is a key representing type of hook
|
6
|
+
# being run (e.g. pre-commit, commit-msg, etc.). Within each type you can
|
7
|
+
# customize each hook, such as whether to only run it on certain files (via
|
8
|
+
# `include`), whether to only display output if it fails (via `quiet`), etc.
|
9
|
+
#
|
10
|
+
# For a complete list of hooks, see:
|
11
|
+
# https://github.com/brigade/overcommit/tree/master/lib/overcommit/hook
|
12
|
+
#
|
13
|
+
# For a complete list of options that you can use to customize hooks, see:
|
14
|
+
# https://github.com/brigade/overcommit#configuration
|
15
|
+
#
|
16
|
+
# Uncomment the following lines to make the configuration take effect.
|
17
|
+
|
18
|
+
#PreCommit:
|
19
|
+
# RuboCop:
|
20
|
+
# enabled: true
|
21
|
+
# on_warn: fail # Treat all warnings as failures
|
22
|
+
#
|
23
|
+
# TrailingWhitespace:
|
24
|
+
# enabled: true
|
25
|
+
# exclude:
|
26
|
+
# - '**/db/structure.sql' # Ignore trailing whitespace in generated files
|
27
|
+
#
|
28
|
+
#PostCheckout:
|
29
|
+
# ALL: # Special hook name that customizes all hooks of this type
|
30
|
+
# quiet: true # Change all post-checkout hooks to only display output on failure
|
31
|
+
#
|
32
|
+
# IndexTags:
|
33
|
+
# enabled: true # Generate a tags file with `ctags` each time HEAD changes
|
data/.rubocop.yml
ADDED
data/Gemfile
ADDED
data/Readme.md
ADDED
@@ -0,0 +1,94 @@
|
|
1
|
+
# Chauffeur
|
2
|
+
Chauffeur is a tool to help manage drivers for automating browsers.
|
3
|
+
|
4
|
+
It has two primary behaviors: installing drivers and adding them to your path.
|
5
|
+
|
6
|
+
_!!Note: Microsoft WebDriver will only work for version 14393 and greater. Before that it used an installer._
|
7
|
+
|
8
|
+
## Usage
|
9
|
+
This is very important! Chauffeur must be run from the working directory of the project or it will not function.
|
10
|
+
|
11
|
+
Add it to Gemfile or use `gem install chauffeur`
|
12
|
+
|
13
|
+
Initialize drivers in your project with
|
14
|
+
```
|
15
|
+
cmd > chauffeur init
|
16
|
+
```
|
17
|
+
This will create a directory in your project with a file config.yml and the folders to hold drivers.
|
18
|
+
|
19
|
+
####driver_versions:
|
20
|
+
takes no arguments and prints the installed versions for each browser.
|
21
|
+
```
|
22
|
+
cmd > chauffeur driver_versions
|
23
|
+
{"chromedriver"=>
|
24
|
+
{"linux32"=>"nil", "linux64"=>"nil", "mac32"=>"nil", "win32"=>"nil"},
|
25
|
+
"geckodriver"=>
|
26
|
+
{"linux32"=>"nil",
|
27
|
+
"linux64"=>"nil",
|
28
|
+
"macos"=>"nil",
|
29
|
+
"win32"=>"nil",
|
30
|
+
"win64"=>"nil"},
|
31
|
+
"iedriver"=>{"Win32"=>"nil", "x64"=>"nil"},
|
32
|
+
"microsoft_webdriver"=>{}}
|
33
|
+
```
|
34
|
+
###upgrade_driver:
|
35
|
+
takes the browser name and system platform as arguments and installs the driver.
|
36
|
+
browser: chrome, firefox, ie, edge
|
37
|
+
platform: chrome: [linux32, linux64, mac32, win32]
|
38
|
+
firefox: [linux32, linux64, macos, win32, win64]
|
39
|
+
ie: [Win32, x64]
|
40
|
+
edge: build version number
|
41
|
+
```
|
42
|
+
cmd > chauffeur upgrade_driver ie Win32
|
43
|
+
installing 'http://selenium-release.storage.googleapis.com/3.8/IEDriverServer_Win32_3.8.0.zip' into 'C:/path/to/project/drivers/iedriver/Win32/'
|
44
|
+
```
|
45
|
+
###upgrade_driver_all_platforms:
|
46
|
+
takes the browser name and installs most current driver for each platform
|
47
|
+
browser: chrome, firefox, ie, edge
|
48
|
+
|
49
|
+
```
|
50
|
+
cmd > chauffeur upgrade_driver_all_platforms chrome
|
51
|
+
installing 'http://chromedriver.storage.googleapis.com/2.33/chromedriver_linux32.zip' into 'C:/path/to/project/drivers/chromedriver/linux32/'
|
52
|
+
installing 'http://chromedriver.storage.googleapis.com/2.34/chromedriver_linux64.zip' into 'C:/path/to/project/drivers/chromedriver/linux64/'
|
53
|
+
installing 'http://chromedriver.storage.googleapis.com/2.22/chromedriver_mac32.zip' into 'C:/path/to/project/drivers/chromedriver/mac32/'
|
54
|
+
installing 'http://chromedriver.storage.googleapis.com/2.34/chromedriver_win32.zip' into 'C:/path/to/project/drivers/chromedriver/win32/'
|
55
|
+
```
|
56
|
+
|
57
|
+
###install_driver:
|
58
|
+
takes browser, platform, and version and installs that driver.
|
59
|
+
browser: chrome, firefox, ie, edge
|
60
|
+
platform: chrome: [linux32, linux64, mac32, win32]
|
61
|
+
firefox: [linux32, linux64, macos, win32, win64]
|
62
|
+
ie: [Win32, x64]
|
63
|
+
edge: build version number
|
64
|
+
version: must match exactly the download version
|
65
|
+
|
66
|
+
```
|
67
|
+
cmd > chauffeur install_driver firefox linux64 0.18.0
|
68
|
+
installing 'https://github.com/mozilla/geckodriver/releases//download/v0.18.0/geckodriver-v0.18.0-linux64.tar.gz' into 'C:/path/to/project/drivers/geckodriver/linux64/'
|
69
|
+
```
|
70
|
+
|
71
|
+
###install_driver_all_platforms:
|
72
|
+
takes browser name and version number and installs that version for all platforms.
|
73
|
+
browser: chrome, firefox, ie, edge
|
74
|
+
version: must match exactly the download version
|
75
|
+
|
76
|
+
```
|
77
|
+
cmd > chauffeur install_driver_all_platforms chrome 2.22
|
78
|
+
installing 'http://chromedriver.storage.googleapis.com/2.22/chromedriver_linux32.zip' into 'C:/path/to/project/drivers/chromedriver/linux32/'
|
79
|
+
installing 'http://chromedriver.storage.googleapis.com/2.22/chromedriver_linux64.zip' into 'C:/path/to/project/drivers/chromedriver/linux64/'
|
80
|
+
installing 'http://chromedriver.storage.googleapis.com/2.22/chromedriver_mac32.zip' into 'C:/path/to/project/drivers/chromedriver/mac32/'
|
81
|
+
installing 'http://chromedriver.storage.googleapis.com/2.22/chromedriver_win32.zip' into 'C:/path/to/project/drivers/chromedriver/win32/'
|
82
|
+
```
|
83
|
+
|
84
|
+
|
85
|
+
### Add drivers to path:
|
86
|
+
|
87
|
+
In your project code use
|
88
|
+
|
89
|
+
```
|
90
|
+
require 'chauffeur'
|
91
|
+
Chauffeur.add_drivers_to_path
|
92
|
+
```
|
93
|
+
|
94
|
+
|
data/bin/chauffeur
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'chauffeur'
|
4
|
+
require 'pp'
|
5
|
+
|
6
|
+
# puts "THE ARGUMENTS ARE: '#{ARGV}'"
|
7
|
+
|
8
|
+
def all_options
|
9
|
+
%w[
|
10
|
+
driver_versions
|
11
|
+
init
|
12
|
+
upgrade_driver
|
13
|
+
upgrade_driver_all_platforms
|
14
|
+
install_driver
|
15
|
+
install_driver_all_platforms
|
16
|
+
help
|
17
|
+
]
|
18
|
+
end
|
19
|
+
|
20
|
+
def browsers
|
21
|
+
%w[chrome firefox edge ie]
|
22
|
+
end
|
23
|
+
|
24
|
+
def browser_error(text)
|
25
|
+
Exception.new("Unknown browser'#{text}'. must be one of #{browsers}")
|
26
|
+
end
|
27
|
+
|
28
|
+
case ARGV[0]
|
29
|
+
when 'driver_versions'
|
30
|
+
pp Chauffeur.driver_versions
|
31
|
+
when 'init'
|
32
|
+
Chauffeur.initialize_chauffeur
|
33
|
+
when 'upgrade_driver'
|
34
|
+
raise browser_error(ARGV[1]) unless browsers.include?(ARGV[1])
|
35
|
+
Chauffeur.upgrade_driver(ARGV[1], ARGV[2])
|
36
|
+
when 'upgrade_driver_all_platforms'
|
37
|
+
raise browser_error(ARGV[1]) unless browsers.include?(ARGV[1])
|
38
|
+
Chauffeur.upgrade_driver_all_platforms(ARGV[1])
|
39
|
+
when 'install_driver'
|
40
|
+
raise browser_error(ARGV[1]) unless browsers.include?(ARGV[1])
|
41
|
+
Chauffeur.install_driver(ARGV[1], ARGV[2], ARGV[3])
|
42
|
+
when 'install_driver_all_platforms'
|
43
|
+
raise browser_error(ARGV[1]) unless browsers.include?(ARGV[1])
|
44
|
+
Chauffeur.install_driver_all_platforms(ARGV[1], ARGV[2])
|
45
|
+
when 'help'
|
46
|
+
help_contents = File.read("#{File.dirname(__FILE__)}/../lib/chauffeur/help.txt")
|
47
|
+
puts help_contents
|
48
|
+
else
|
49
|
+
help_contents = File.read("#{File.dirname(__FILE__)}/../lib/chauffeur/help.txt")
|
50
|
+
puts help_contents
|
51
|
+
raise "Unknown option '#{ARGV[0]}' must be one of #{all_options}."
|
52
|
+
end
|
data/chauffeur.gemspec
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
# Gemspec file for Chauffeur Gem
|
2
|
+
require 'English'
|
3
|
+
|
4
|
+
Gem::Specification.new do |s|
|
5
|
+
s.name = 'chauffeur'
|
6
|
+
s.version = '0.0.2'
|
7
|
+
s.date = '2017-10-23'
|
8
|
+
s.summary = 'summary'
|
9
|
+
s.description = 'Chauffeur is a tool to help manage drivers for automating browsers.'
|
10
|
+
s.authors = ['Jeremy Gardner']
|
11
|
+
s.email = 'jerrygar96@gmail.com'
|
12
|
+
s.files = `git ls-files`.split($ORS)
|
13
|
+
s.homepage = 'http://rubygems.org/gems/chauffeur'
|
14
|
+
s.license = 'MIT'
|
15
|
+
s.executables = %w[chauffeur]
|
16
|
+
|
17
|
+
s.add_development_dependency('pry', ['~> 0.11'])
|
18
|
+
s.add_development_dependency('rspec', ['~> 3.7'])
|
19
|
+
s.add_development_dependency('simplecov', ['~> 0.15'])
|
20
|
+
|
21
|
+
s.add_runtime_dependency('archive-zip', ['~> 0.10'])
|
22
|
+
s.add_runtime_dependency('httparty', ['~> 0.15'])
|
23
|
+
s.add_runtime_dependency('nokogiri', '~> 1.8')
|
24
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
---
|
2
|
+
folders:
|
3
|
+
- drivers/chromedriver/linux32
|
4
|
+
- drivers/chromedriver/linux64
|
5
|
+
- drivers/chromedriver/mac32
|
6
|
+
- drivers/chromedriver/win32
|
7
|
+
- drivers/edgedriver
|
8
|
+
- drivers/geckodriver/linux32
|
9
|
+
- drivers/geckodriver/linux64
|
10
|
+
- drivers/geckodriver/macos
|
11
|
+
- drivers/geckodriver/win32
|
12
|
+
- drivers/geckodriver/win64
|
13
|
+
- drivers/iedriver/Win32
|
14
|
+
- drivers/iedriver/x64
|
15
|
+
installed_versions:
|
16
|
+
chromedriver:
|
17
|
+
linux32: nil
|
18
|
+
linux64: nil
|
19
|
+
mac32: nil
|
20
|
+
win32: nil
|
21
|
+
geckodriver:
|
22
|
+
linux32: nil
|
23
|
+
linux64: nil
|
24
|
+
macos: nil
|
25
|
+
win32: nil
|
26
|
+
win64: nil
|
27
|
+
iedriver:
|
28
|
+
Win32: nil
|
29
|
+
x64: nil
|
30
|
+
microsoft_webdriver: {}
|
@@ -0,0 +1,43 @@
|
|
1
|
+
# ChromeDriver specific functions for driver downloading.
|
2
|
+
class ChromedriverDownloader < DriverDownloader
|
3
|
+
CHROMEDRIVER_URL = 'http://chromedriver.storage.googleapis.com/'.freeze
|
4
|
+
|
5
|
+
def browser_name
|
6
|
+
'chromedriver'
|
7
|
+
end
|
8
|
+
|
9
|
+
def driver_url
|
10
|
+
CHROMEDRIVER_URL
|
11
|
+
end
|
12
|
+
|
13
|
+
def all_platforms
|
14
|
+
%w[linux32 linux64 mac32 win32]
|
15
|
+
end
|
16
|
+
|
17
|
+
# Returns the most recent version of chromedriver for the
|
18
|
+
# desired platform.
|
19
|
+
# platform must be one of: linux32, linux64, mac32, win32
|
20
|
+
def latest_driver_version(platform)
|
21
|
+
raise unknown_platform_error(platform) unless valid_platform?(platform)
|
22
|
+
platform_drivers = all_driver_versions.select { |v| v.include?(platform) }
|
23
|
+
platform_drivers.map { |v| version_of(v.split('/')[0]) }.max
|
24
|
+
end
|
25
|
+
|
26
|
+
# Returns all available versions of Chromedriver
|
27
|
+
def all_driver_versions
|
28
|
+
resp = HTTParty.get(CHROMEDRIVER_URL).parsed_response
|
29
|
+
resp['ListBucketResult']['Contents'].map { |c| c['Key'] }
|
30
|
+
end
|
31
|
+
|
32
|
+
# Returns the url for the desired version of chromedriver
|
33
|
+
# version: string - must match exactly the version in the download URL
|
34
|
+
# platform: string - must be one of: linux32, linux64, mac32, win32
|
35
|
+
def driver_download_url(version, platform)
|
36
|
+
raise unknown_platform_error(platform) unless valid_platform?(platform)
|
37
|
+
rel_path = all_driver_versions.find do |v|
|
38
|
+
v.eql?("#{version}/chromedriver_#{platform}.zip")
|
39
|
+
end
|
40
|
+
raise unknown_version_error(version) unless rel_path
|
41
|
+
"#{CHROMEDRIVER_URL}#{rel_path}"
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# FireFoxDriver specific functions for driver downloading.
|
2
|
+
class EdgedriverDownloader < DriverDownloader
|
3
|
+
EDGEDRIVER_URL = 'https://developer.microsoft.com/en-us/microsoft-edge/tools/webdriver/'.freeze
|
4
|
+
|
5
|
+
def browser_name
|
6
|
+
'microsoft_webdriver'
|
7
|
+
end
|
8
|
+
|
9
|
+
def driver_url
|
10
|
+
EDGEDRIVER_URL
|
11
|
+
end
|
12
|
+
|
13
|
+
def all_platforms
|
14
|
+
%w[win]
|
15
|
+
end
|
16
|
+
|
17
|
+
# Returns the most recent version of edgedriver for the
|
18
|
+
# desired platform.
|
19
|
+
# platform must be one of: win
|
20
|
+
def latest_driver_version(platform)
|
21
|
+
raise unknown_platform_error(platform) unless valid_platform?(platform)
|
22
|
+
versions = all_driver_versions
|
23
|
+
versions.keys.sort.reverse.find { |k| k =~ /^\d+$/ }
|
24
|
+
end
|
25
|
+
|
26
|
+
# Returns all available versions of geckodriver
|
27
|
+
def all_driver_versions
|
28
|
+
resp = HTTParty.get(driver_url, verify: false).parsed_response
|
29
|
+
doc = Nokogiri::XML.parse(resp)
|
30
|
+
output = {}
|
31
|
+
doc.css('li.driver-download a.subtitle').each do |a|
|
32
|
+
output[a.text.gsub('Release ', '')] = a[:href]
|
33
|
+
end
|
34
|
+
output
|
35
|
+
end
|
36
|
+
|
37
|
+
# Returns the url for the desired version of geckodriver
|
38
|
+
# version: string - must match exactly the version in the download URL
|
39
|
+
# platform: string - must be win
|
40
|
+
def driver_download_url(version, platform)
|
41
|
+
raise unknown_platform_error(platform) unless valid_platform?(platform)
|
42
|
+
all_driver_versions[version] || raise(unknown_version_error(version))
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# FireFoxDriver specific functions for driver downloading.
|
2
|
+
class FirefoxdriverDownloader < DriverDownloader
|
3
|
+
GECKODRIVER_URL = 'https://github.com/mozilla/geckodriver/releases/'.freeze
|
4
|
+
|
5
|
+
def browser_name
|
6
|
+
'geckodriver'
|
7
|
+
end
|
8
|
+
|
9
|
+
def driver_url
|
10
|
+
GECKODRIVER_URL
|
11
|
+
end
|
12
|
+
|
13
|
+
def all_platforms
|
14
|
+
%w[linux32 linux64 macos win32 win64]
|
15
|
+
end
|
16
|
+
|
17
|
+
# Returns the most recent version of geckodriver for the
|
18
|
+
# desired platform.
|
19
|
+
# platform must be one of: linux32, linux64, mac32, win32
|
20
|
+
def latest_driver_version(platform)
|
21
|
+
raise unknown_platform_error(platform) unless valid_platform?(platform)
|
22
|
+
all_driver_versions.map { |v| Gem::Version.new(v.delete('v')) }.max
|
23
|
+
end
|
24
|
+
|
25
|
+
# Returns all available versions of geckodriver
|
26
|
+
def all_driver_versions
|
27
|
+
resp = HTTParty.get(GECKODRIVER_URL, verify: false).parsed_response
|
28
|
+
doc = Nokogiri::XML.parse(resp)
|
29
|
+
doc.css('div.release h1.release-title a').map(&:text)
|
30
|
+
end
|
31
|
+
|
32
|
+
# Returns the url for the desired version of geckodriver
|
33
|
+
# version: string - must match exactly the version in the download URL
|
34
|
+
# platform: string - must be one of: linux32, linux64, mac32, win32
|
35
|
+
def driver_download_url(version, platform)
|
36
|
+
raise unknown_platform_error(platform) unless valid_platform?(platform)
|
37
|
+
raise unknown_version_error(version) unless all_driver_versions.include?("v#{version}")
|
38
|
+
extension = platform.start_with?('win') ? 'zip' : 'tar.gz'
|
39
|
+
rel_path = "/download/v#{version}/geckodriver-v#{version}-#{platform}.#{extension}"
|
40
|
+
"#{GECKODRIVER_URL}#{rel_path}"
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# IEDriver specific functions for driver downloading.
|
2
|
+
class IedriverDownloader < DriverDownloader
|
3
|
+
IEDRIVER_URL = 'http://selenium-release.storage.googleapis.com/'.freeze
|
4
|
+
|
5
|
+
def browser_name
|
6
|
+
'iedriver'
|
7
|
+
end
|
8
|
+
|
9
|
+
def driver_url
|
10
|
+
IEDRIVER_URL
|
11
|
+
end
|
12
|
+
|
13
|
+
def all_platforms
|
14
|
+
%w[Win32 x64]
|
15
|
+
end
|
16
|
+
|
17
|
+
# Returns the most recent version of iedriver for the
|
18
|
+
# desired platform.
|
19
|
+
# platform must be one of: linux32, linux64, mac32, win32
|
20
|
+
def latest_driver_version(platform)
|
21
|
+
raise unknown_platform_error(platform) unless valid_platform?(platform)
|
22
|
+
platform_drivers = all_driver_versions.select { |v| v.include?(platform) }
|
23
|
+
platform_drivers.map { |v| version_of(v.split('/')[0]) }.max
|
24
|
+
end
|
25
|
+
|
26
|
+
# Returns all available versions of iedriver
|
27
|
+
def all_driver_versions
|
28
|
+
resp = HTTParty.get(IEDRIVER_URL).parsed_response
|
29
|
+
contents = resp['ListBucketResult']['Contents']
|
30
|
+
contents.map { |c| c['Key'] }.select { |url| url.include?('IEDriverServer') }
|
31
|
+
end
|
32
|
+
|
33
|
+
# Returns the url for the desired version of iedriver
|
34
|
+
# version: string - must match exactly the version in the download URL
|
35
|
+
# platform: string - must be one of: linux32, linux64, mac32, win32
|
36
|
+
def driver_download_url(version, platform)
|
37
|
+
raise unknown_platform_error(platform) unless valid_platform?(platform)
|
38
|
+
rel_path = all_driver_versions.find do |v|
|
39
|
+
v =~ %r{#{version}/IEDriverServer_#{platform}_#{version}\.\d+\.zip}
|
40
|
+
end
|
41
|
+
raise unknown_version_error(version) unless rel_path
|
42
|
+
"#{IEDRIVER_URL}#{rel_path}"
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,177 @@
|
|
1
|
+
# Downloads and installs browser drivers.
|
2
|
+
class DriverDownloader
|
3
|
+
require 'zlib'
|
4
|
+
|
5
|
+
def initialize
|
6
|
+
config_file_path = "#{Dir.pwd}/drivers/config.yml"
|
7
|
+
@data = File.open(config_file_path) { |f| YAML.safe_load(f) }
|
8
|
+
@installed_versions = @data['installed_versions']
|
9
|
+
end
|
10
|
+
|
11
|
+
# This must be implemented in all child classes!
|
12
|
+
#
|
13
|
+
# Returns a string for the driver name in file structure.
|
14
|
+
def browser_name
|
15
|
+
raise 'This class should not be initialized! Please use subclass.'
|
16
|
+
end
|
17
|
+
|
18
|
+
# This must be implemented in all child classes!
|
19
|
+
#
|
20
|
+
# returns the string url where all downloads can be located.
|
21
|
+
def driver_url
|
22
|
+
raise 'This class should not be initialized! Please use subclass.'
|
23
|
+
end
|
24
|
+
|
25
|
+
# This must be implemented in all child classes!
|
26
|
+
#
|
27
|
+
# returns an array of all available platforms for the driver.
|
28
|
+
def all_platforms
|
29
|
+
raise 'This class should not be initialized! Please use subclass.'
|
30
|
+
end
|
31
|
+
|
32
|
+
# This must be implemented in all child classes!
|
33
|
+
#
|
34
|
+
# Returns the most recent version of chromedriver for the
|
35
|
+
# desired platform.
|
36
|
+
# platform must be one of: linux32, linux64, mac32, win32
|
37
|
+
def latest_driver_version(_platform)
|
38
|
+
raise 'This class should not be initialized! Please use subclass.'
|
39
|
+
end
|
40
|
+
|
41
|
+
# Returns all available versions of Chromedriver
|
42
|
+
def all_driver_versions
|
43
|
+
raise 'This class should not be initialized! Please use subclass.'
|
44
|
+
end
|
45
|
+
|
46
|
+
# This must be implemented in all child classes!
|
47
|
+
#
|
48
|
+
# Returns the url for the desired version of driver
|
49
|
+
# version: string - must match exactly the version in the download URL
|
50
|
+
# platform: string - must be in all_platforms
|
51
|
+
def driver_download_url(_version, _platform)
|
52
|
+
raise 'This class should not be initialized! Please use subclass.'
|
53
|
+
end
|
54
|
+
|
55
|
+
# Returns the destination folder for the browser driver for the
|
56
|
+
# desired platform.
|
57
|
+
# platform: string - must match the appropriate platform for
|
58
|
+
# the particular driver
|
59
|
+
def path_for(platform, version)
|
60
|
+
raise unknown_platform_error(platform) unless valid_platform?(platform)
|
61
|
+
last_part = instance_of?(EdgedriverDownloader) ? version : platform
|
62
|
+
"#{Dir.pwd}/drivers/#{browser_name}/#{last_part}/"
|
63
|
+
end
|
64
|
+
|
65
|
+
# Downloads and installs driver
|
66
|
+
# version: string - the exact version number for the download
|
67
|
+
# platform: string - must match the appropriate platform for
|
68
|
+
# the particular driver
|
69
|
+
def install_driver(version, platform)
|
70
|
+
raise unknown_platform_error(platform) unless valid_platform?(platform)
|
71
|
+
if @installed_versions[browser_name][platform].eql?(version.to_s)
|
72
|
+
puts "Driver version #{version} already installed for #{platform}"
|
73
|
+
return
|
74
|
+
end
|
75
|
+
driver_path = path_for(platform, version)
|
76
|
+
download_url = driver_download_url(version, platform)
|
77
|
+
|
78
|
+
puts "installing '#{download_url}' into '#{driver_path}'"
|
79
|
+
|
80
|
+
download_and_unzip(driver_path, download_url)
|
81
|
+
update_browser_version(platform, version)
|
82
|
+
end
|
83
|
+
|
84
|
+
# Installs the latest version of chromedriver for the specified platform.
|
85
|
+
# platform: string - must match the appropriate platform for
|
86
|
+
# the particular driver
|
87
|
+
def upgrade_driver(platform)
|
88
|
+
raise unknown_platform_error(platform) unless valid_platform?(platform)
|
89
|
+
latest_version = latest_driver_version(platform)
|
90
|
+
install_driver(latest_version, platform)
|
91
|
+
end
|
92
|
+
|
93
|
+
# Installs the latest version of chromedriver for all platforms.
|
94
|
+
def upgrade_driver_all_platforms
|
95
|
+
all_platforms.each do |platform|
|
96
|
+
upgrade_driver(platform)
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
# Installs the specified version of specified driver for all platforms.
|
101
|
+
def install_driver_all_platforms(version)
|
102
|
+
all_platforms.each do |platform|
|
103
|
+
install_driver(version, platform)
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
# Downloads and installs driver to appropriate path
|
108
|
+
# driver_path: string - path to install driver (must end with '/')
|
109
|
+
# download_url: string - URL of the driver desired
|
110
|
+
def download_and_unzip(driver_path, download_url)
|
111
|
+
FileUtils.mkdir_p(driver_path)
|
112
|
+
destination_file_name = "#{driver_path}#{File.basename(download_url)}"
|
113
|
+
FileUtils.rm_f destination_file_name
|
114
|
+
File.open(destination_file_name, 'wb') do |saved_file|
|
115
|
+
saved_file.write(HTTParty.get(download_url, verify: false).parsed_response)
|
116
|
+
end
|
117
|
+
raise "Could not download #{download_url}" unless File.exist?(destination_file_name)
|
118
|
+
extract_and_delete(destination_file_name, driver_path) unless instance_of?(EdgedriverDownloader)
|
119
|
+
FileUtils.rm_f "#{destination_file_name}.zip"
|
120
|
+
end
|
121
|
+
|
122
|
+
private
|
123
|
+
|
124
|
+
# Gem::Version lets versions get compared in a way that makes sense for
|
125
|
+
# semantic versions. For example it makes 2.38 greater than 2.5
|
126
|
+
def version_of(num_str)
|
127
|
+
Gem::Version.new(num_str)
|
128
|
+
end
|
129
|
+
|
130
|
+
# Updates the hash of the installed versions and then saves the Yaml file
|
131
|
+
def update_browser_version(platform, version)
|
132
|
+
@installed_versions[browser_name][platform] = version.to_s
|
133
|
+
save_data
|
134
|
+
end
|
135
|
+
|
136
|
+
# Saves @data to config.yml file
|
137
|
+
def save_data
|
138
|
+
File.open("#{Dir.pwd}/drivers/config.yml", 'w') { |f| f.write(@data.to_yaml) }
|
139
|
+
end
|
140
|
+
|
141
|
+
# Checks to see if the passed in platform is valid for the particular browser
|
142
|
+
#
|
143
|
+
# Requires all_platforms to be defined in the instantiated class.
|
144
|
+
def valid_platform?(platform)
|
145
|
+
all_platforms.include?(platform)
|
146
|
+
end
|
147
|
+
|
148
|
+
# Returns instance of an UnknownPlatform Error to be thrown
|
149
|
+
#
|
150
|
+
# Requires all_platforms to be defined in the instantiated class.
|
151
|
+
def unknown_platform_error(platform)
|
152
|
+
msg = "Unknown platform #{platform}, valid options: #{all_platforms}."
|
153
|
+
raise UnknownPlatformError.new(platform, msg)
|
154
|
+
end
|
155
|
+
|
156
|
+
def unknown_version_error(version)
|
157
|
+
msg = "Unknown version '#{version}', valid options: #{all_driver_versions}."
|
158
|
+
raise UnknownVersionError.new(version, msg)
|
159
|
+
end
|
160
|
+
|
161
|
+
# Extracts a file and deletes the compressed file
|
162
|
+
#
|
163
|
+
# destination_file_name: string - full file path to the compressed file.
|
164
|
+
# driver_path: string - the full path to the destination folder.
|
165
|
+
def extract_and_delete(destination_file_name, driver_path)
|
166
|
+
if destination_file_name.end_with?('.tar.gz')
|
167
|
+
File.open(destination_file_name, 'rb') do |f|
|
168
|
+
gz = Zlib::GzipReader.new(f)
|
169
|
+
File.open("#{driver_path}geckodriver", 'wb', 0o0755) { |new_file| new_file.puts(gz.read) }
|
170
|
+
end
|
171
|
+
else
|
172
|
+
Archive::Zip.extract(destination_file_name, driver_path, overwrite: :all)
|
173
|
+
end
|
174
|
+
files_to_delete = Dir.glob("#{driver_path}*.{zip,gz}")
|
175
|
+
FileUtils.rm_rf(files_to_delete) if files_to_delete.size.eql?(1)
|
176
|
+
end
|
177
|
+
end
|