chauffeur 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (39) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +5 -0
  3. data/.overcommit.yml +33 -0
  4. data/.rubocop.yml +13 -0
  5. data/Gemfile +8 -0
  6. data/Readme.md +94 -0
  7. data/bin/chauffeur +52 -0
  8. data/chauffeur.gemspec +24 -0
  9. data/lib/chauffeur/config.yml +30 -0
  10. data/lib/chauffeur/downloaders/chromedriver_downloader.rb +43 -0
  11. data/lib/chauffeur/downloaders/edgedriver_downloader.rb +44 -0
  12. data/lib/chauffeur/downloaders/firefoxdriver_downloader.rb +42 -0
  13. data/lib/chauffeur/downloaders/iedriver_downloader.rb +44 -0
  14. data/lib/chauffeur/driver_downloader.rb +177 -0
  15. data/lib/chauffeur/help.txt +60 -0
  16. data/lib/chauffeur/path_expander.rb +90 -0
  17. data/lib/chauffeur/requires.rb +15 -0
  18. data/lib/chauffeur/setup.rb +36 -0
  19. data/lib/chauffeur/unknown_platform_error.rb +10 -0
  20. data/lib/chauffeur/unknown_version_error.rb +7 -0
  21. data/lib/chauffeur.rb +83 -0
  22. data/lib/pry_playground.rb +4 -0
  23. data/spec/chromedriver_downloader_spec.rb +82 -0
  24. data/spec/chromedriver_downloader_specs/chromedriver_downloader_overridden_methods_spec.rb +79 -0
  25. data/spec/chromedriver_downloader_specs/chromedriver_downloader_simple_spec.rb +22 -0
  26. data/spec/driver_downloader_specs/driver_downloader_error_spec.rb +26 -0
  27. data/spec/driver_versions_spec.rb +29 -0
  28. data/spec/edgedriver_downloader_specs/edgedriver_downloader_overridden_methods.rb +58 -0
  29. data/spec/edgedriver_downloader_specs/edgedriver_downloader_simple_spec.rb +22 -0
  30. data/spec/firefoxdriver_downloader_specs/firefoxdriver_downloader_overridden_methods_spec.rb +86 -0
  31. data/spec/firefoxdriver_downloader_specs/firefoxdriver_downloader_simple_spec.rb +22 -0
  32. data/spec/format_for_platform_spec.rb +59 -0
  33. data/spec/helpers/spec_helper.rb +4 -0
  34. data/spec/iedriver_downloader_spec.rb +17 -0
  35. data/spec/iedriver_downloader_specs/iedriver_downloader_overridden_methods_spec.rb +65 -0
  36. data/spec/iedriver_downloader_specs/iedriver_downloader_simple_spec.rb +22 -0
  37. data/spec/path_expansion_spec.rb +43 -0
  38. data/spec/setup_spec.rb +48 -0
  39. 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
@@ -0,0 +1,5 @@
1
+ drivers
2
+ chauffeur*.gem
3
+ coverage
4
+ Gemfile.lock
5
+ .idea/*
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
@@ -0,0 +1,13 @@
1
+ AllCops:
2
+ Include:
3
+ - Gemfile
4
+ - Rakefile
5
+ Exclude:
6
+ - lib/pry_playground.rb
7
+ - .rubocop.yml
8
+
9
+ Layout/EndOfLine:
10
+ EnforcedStyle: lf
11
+
12
+ LineLength:
13
+ Max: 100
data/Gemfile ADDED
@@ -0,0 +1,8 @@
1
+ source 'http://rubygems.org' do
2
+ gem 'archive-zip', '~> 0.10'
3
+ gem 'httparty', '~> 0.15'
4
+ gem 'nokogiri', '~> 1.8'
5
+ gem 'pry', '~> 0.11'
6
+ gem 'rspec', '~> 3.7'
7
+ gem 'simplecov', '~> 0.15'
8
+ end
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