webdrivers 3.8.1 → 3.9.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.
@@ -2,219 +2,153 @@
2
2
 
3
3
  require 'rubygems/package'
4
4
  require 'zip'
5
+ require 'webdrivers/logger'
6
+ require 'webdrivers/network'
7
+ require 'webdrivers/system'
8
+ require 'selenium-webdriver'
5
9
 
6
10
  module Webdrivers
7
- class Common
8
- class << self
9
- attr_accessor :version
11
+ class ConnectionError < StandardError
12
+ end
10
13
 
11
- def update
12
- unless site_available?
13
- return current_version.nil? ? nil : binary
14
- end
14
+ class VersionError < StandardError
15
+ end
15
16
 
16
- # Newer not specified or latest not found, so use existing
17
- return binary if desired_version.nil? && File.exist?(binary)
17
+ class << self
18
+ attr_accessor :proxy_addr, :proxy_port, :proxy_user, :proxy_pass, :install_dir
18
19
 
19
- # Can't find desired and no existing binary
20
- if desired_version.nil?
21
- msg = "Unable to find the latest version of #{file_name}; try downloading manually " \
22
- "from #{base_url} and place in #{install_dir}"
23
- raise StandardError, msg
24
- end
20
+ attr_writer :cache_time
25
21
 
26
- if correct_binary?
27
- Webdrivers.logger.debug 'Expected webdriver version found'
28
- return binary
29
- end
22
+ def cache_time
23
+ @cache_time || 0
24
+ end
30
25
 
31
- remove # Remove outdated exe
32
- download # Fetch latest
33
- end
26
+ def logger
27
+ @logger ||= Webdrivers::Logger.new
28
+ end
34
29
 
35
- def desired_version
36
- if version.is_a?(Gem::Version)
37
- version
38
- elsif version.nil?
39
- latest_version
40
- else
41
- normalize_version(version)
42
- end
43
- end
30
+ def configure
31
+ yield self
32
+ end
44
33
 
45
- def latest_version
46
- return @latest_version if @latest_version
34
+ def net_http_ssl_fix
35
+ raise 'Webdrivers.net_http_ssl_fix is no longer available.' \
36
+ ' Please see https://github.com/titusfortner/webdrivers#ssl_connect-errors.'
37
+ end
38
+ end
47
39
 
48
- raise StandardError, 'Can not reach site' unless site_available?
40
+ class Common
41
+ class << self
42
+ attr_writer :required_version
43
+ attr_reader :cache_warning
49
44
 
50
- @latest_version = downloads.keys.max
45
+ def version
46
+ Webdrivers.logger.deprecate("#{self.class}#version", "#{self.class}#required_version")
47
+ required_version
51
48
  end
52
49
 
53
- def remove
54
- max_attempts = 3
55
- attempts_made = 0
56
- delay = 0.5
57
- Webdrivers.logger.debug "Deleting #{binary}"
58
- @download_url = nil
59
-
60
- begin
61
- attempts_made += 1
62
- File.delete binary if File.exist? binary
63
- rescue Errno::EACCES # Solves an intermittent file locking issue on Windows
64
- sleep(delay)
65
- retry if File.exist?(binary) && attempts_made <= max_attempts
66
- raise
67
- end
50
+ def version=(version)
51
+ Webdrivers.logger.deprecate("#{self.class}#version=", "#{self.class}#required_version=")
52
+ self.required_version = version
68
53
  end
69
54
 
70
- def download
71
- raise StandardError, 'Can not reach site' unless site_available?
72
-
73
- filename = File.basename download_url
74
-
75
- FileUtils.mkdir_p(install_dir) unless File.exist?(install_dir)
76
- Dir.chdir install_dir do
77
- df = Tempfile.open(['', filename], binmode: true) do |file|
78
- file.print get(download_url)
79
- file
80
- end
81
-
82
- raise "Could not download #{download_url}" unless File.exist? df.to_path
83
-
84
- Webdrivers.logger.debug "Successfully downloaded #{df.to_path}"
55
+ def required_version
56
+ normalize_version @required_version
57
+ end
85
58
 
86
- decompress_file(df.to_path, filename)
87
- Webdrivers.logger.debug 'Decompression Complete'
88
- Webdrivers.logger.debug "Deleting #{df.to_path}"
89
- df.close!
59
+ def update
60
+ if correct_binary?
61
+ Webdrivers.logger.debug 'The required webdriver version is already on the system'
62
+ return driver_path
90
63
  end
91
- raise "Could not decompress #{download_url} to get #{binary}" unless File.exist?(binary)
92
64
 
93
- FileUtils.chmod 'ugo+rx', binary
94
- Webdrivers.logger.debug "Completed download and processing of #{binary}"
95
- binary
65
+ remove
66
+ System.download(download_url, driver_path)
96
67
  end
97
68
 
98
- def install_dir
99
- Webdrivers.install_dir || File.expand_path(File.join(ENV['HOME'], '.webdrivers'))
100
- end
69
+ def desired_version
70
+ old = "#{self.class}#desired_version"
71
+ new = "#{self.class}#required_version or #{self.class}#latest_version"
72
+ Webdrivers.logger.deprecate(old, new)
101
73
 
102
- def binary
103
- File.join install_dir, file_name
74
+ desired_version.version.empty? ? latest_version : normalize_version(desired_version)
104
75
  end
105
76
 
106
- protected
107
-
108
- def get(url, limit = 10)
109
- raise StandardError, 'Too many HTTP redirects' if limit.zero?
77
+ def remove
78
+ @download_url = nil
79
+ @latest_version = nil
80
+ System.delete "#{System.install_dir}/#{file_name.gsub('.exe', '')}.version"
81
+ System.delete driver_path
82
+ end
110
83
 
111
- response = http.get_response(URI(url))
112
- Webdrivers.logger.debug "Get response: #{response.inspect}"
84
+ def download
85
+ Webdrivers.logger.deprecate('#download', '#update')
86
+ System.download(download_url, driver_path)
87
+ end
113
88
 
114
- case response
115
- when Net::HTTPSuccess
116
- response.body
117
- when Net::HTTPRedirection
118
- location = response['location']
119
- Webdrivers.logger.debug "Redirected to #{location}"
120
- get(location, limit - 1)
121
- else
122
- response.value
123
- end
89
+ def binary
90
+ Webdrivers.logger.deprecate('#binary', '#driver_path')
91
+ driver_path
124
92
  end
125
93
 
126
- def http
127
- if using_proxy
128
- Net::HTTP.Proxy(Webdrivers.proxy_addr, Webdrivers.proxy_port,
129
- Webdrivers.proxy_user, Webdrivers.proxy_pass)
130
- else
131
- Net::HTTP
132
- end
94
+ def driver_path
95
+ File.join System.install_dir, file_name
133
96
  end
134
97
 
135
98
  private
136
99
 
137
100
  def download_url
138
- @download_url ||= downloads[desired_version]
139
- end
140
-
141
- def using_proxy
142
- Webdrivers.proxy_addr && Webdrivers.proxy_port
101
+ @download_url ||= if required_version.version.empty?
102
+ downloads[downloads.keys.max]
103
+ else
104
+ downloads[normalize_version(required_version)]
105
+ end
143
106
  end
144
107
 
145
- def downloaded?
146
- result = File.exist? binary
147
- Webdrivers.logger.debug "File is already downloaded: #{result}"
148
- result
108
+ def exists?
109
+ System.exists? driver_path
149
110
  end
150
111
 
151
- def site_available?
152
- Webdrivers.logger.debug "Looking for Site: #{base_url}"
153
- get(base_url)
154
- Webdrivers.logger.debug "Found Site: #{base_url}"
155
- true
156
- rescue StandardError => e
157
- Webdrivers.logger.debug e
158
- false
112
+ def correct_binary?
113
+ current_version == if required_version.version.empty?
114
+ latest_version
115
+ else
116
+ normalize_version(required_version)
117
+ end
118
+ rescue ConnectionError
119
+ driver_path if sufficient_binary?
159
120
  end
160
121
 
161
- def platform
162
- if Selenium::WebDriver::Platform.linux?
163
- "linux#{Selenium::WebDriver::Platform.bitsize}"
164
- elsif Selenium::WebDriver::Platform.mac?
165
- 'mac'
166
- else
167
- 'win'
168
- end
122
+ def sufficient_binary?
123
+ exists?
169
124
  end
170
125
 
171
- def decompress_file(filename, target)
172
- case filename
173
- when /tar\.gz$/
174
- Webdrivers.logger.debug 'Decompressing tar'
175
- untargz_file(filename)
176
- when /tar\.bz2$/
177
- Webdrivers.logger.debug 'Decompressing bz2'
178
- system "tar xjf #{filename}"
179
- filename.gsub('.tar.bz2', '')
180
- when /\.zip$/
181
- Webdrivers.logger.debug 'Decompressing zip'
182
- unzip_file(filename)
183
- else
184
- Webdrivers.logger.debug 'No Decompression needed'
185
- FileUtils.cp(filename, File.join(Dir.pwd, target))
186
- end
126
+ def normalize_version(version)
127
+ Gem::Version.new(version&.to_s)
187
128
  end
188
129
 
189
- def untargz_file(filename)
190
- tar_extract = Gem::Package::TarReader.new(Zlib::GzipReader.open(filename))
191
-
192
- File.open(file_name, 'w+b') do |ucf|
193
- tar_extract.each { |entry| ucf << entry.read }
194
- File.basename ucf
195
- end
130
+ def binary_version
131
+ version = System.call("#{driver_path} --version")
132
+ Webdrivers.logger.debug "Current version of #{driver_path} is #{version}"
133
+ version
134
+ rescue Errno::ENOENT
135
+ Webdrivers.logger.debug "No Such File or Directory: #{driver_path}"
136
+ nil
196
137
  end
197
138
 
198
- def unzip_file(filename)
199
- Zip::File.open(filename) do |zip_file|
200
- zip_file.each do |f|
201
- @top_path ||= f.name
202
- f_path = File.join(Dir.pwd, f.name)
203
- FileUtils.rm_rf(f_path) if File.exist?(f_path)
204
- FileUtils.mkdir_p(File.dirname(f_path)) unless File.exist?(File.dirname(f_path))
205
- zip_file.extract(f, f_path)
139
+ def with_cache(file_name)
140
+ if System.valid_cache?(file_name)
141
+ normalize_version System.cached_version(file_name)
142
+ else
143
+ unless cache_warning
144
+ Webdrivers.logger.warn 'Driver caching is turned off in this version, but will be '\
145
+ 'enabled by default in 4.x. Set the value with `Webdrivers#cache_time=` in seconds'
146
+ @cache_warning = true
206
147
  end
148
+ version = yield
149
+ System.cache_version(file_name, version)
150
+ normalize_version version
207
151
  end
208
- @top_path
209
- end
210
-
211
- # Already have latest version downloaded?
212
- def correct_binary?
213
- desired_version == current_version && File.exist?(binary)
214
- end
215
-
216
- def normalize_version(version)
217
- Gem::Version.new(version.to_s)
218
152
  end
219
153
  end
220
154
  end
@@ -1,41 +1,68 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'nokogiri'
4
+ require 'webdrivers/common'
4
5
 
5
6
  module Webdrivers
6
7
  class Geckodriver < Common
7
8
  class << self
8
9
  def current_version
9
10
  Webdrivers.logger.debug 'Checking current version'
10
- return nil unless downloaded?
11
+ return nil unless exists?
11
12
 
12
- string = `#{binary} --version`
13
- Webdrivers.logger.debug "Current version of #{binary} is #{string}"
14
- normalize_version string.match(/geckodriver (\d+\.\d+\.\d+)/)[1]
15
- end
13
+ version = binary_version
14
+ return nil if version.nil?
16
15
 
17
- private
16
+ normalize_version version.match(/geckodriver (\d+\.\d+\.\d+)/)[1]
17
+ end
18
18
 
19
- def downloads # rubocop:disable Metrics/AbcSize
20
- doc = Nokogiri::HTML.parse(get(base_url))
21
- items = doc.css('.py-1 a').collect { |item| item['href'] }
22
- items.reject! { |item| item.include?('archive') }
23
- items.select! { |item| item.include?(platform) }
24
- ds = items.each_with_object({}) do |item, hash|
25
- key = normalize_version item[/v(\d+\.\d+\.\d+)/, 1]
26
- hash[key] = "https://github.com#{item}"
27
- end
28
- Webdrivers.logger.debug "Versions now located on downloads site: #{ds.keys}"
29
- ds
19
+ def latest_version
20
+ @latest_version ||= with_cache(file_name) { normalize_version(Network.get_url("#{base_url}/latest")[/[^v]*$/]) }
30
21
  end
31
22
 
23
+ private
24
+
32
25
  def file_name
33
- platform == 'win' ? 'geckodriver.exe' : 'geckodriver'
26
+ System.platform == 'win' ? 'geckodriver.exe' : 'geckodriver'
34
27
  end
35
28
 
36
29
  def base_url
37
30
  'https://github.com/mozilla/geckodriver/releases'
38
31
  end
32
+
33
+ def download_url
34
+ @download_url ||= required_version.version.empty? ? direct_url(latest_version) : direct_url(required_version)
35
+ end
36
+
37
+ def direct_url(version)
38
+ "#{base_url}/download/v#{version}/geckodriver-v#{version}-#{platform_ext}"
39
+ end
40
+
41
+ def platform_ext
42
+ case System.platform
43
+ when 'linux'
44
+ "linux#{System.bitsize}.tar.gz"
45
+ when 'mac'
46
+ 'macos.tar.gz'
47
+ when 'win'
48
+ "win#{System.bitsize}.zip"
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
54
+
55
+ if ::Selenium::WebDriver::Service.respond_to? :driver_path=
56
+ ::Selenium::WebDriver::Firefox::Service.driver_path = proc { ::Webdrivers::Geckodriver.update }
57
+ else
58
+ # v3.141.0 and lower
59
+ module Selenium
60
+ module WebDriver
61
+ module Firefox
62
+ def self.driver_path
63
+ @driver_path ||= Webdrivers::Geckodriver.update
64
+ end
65
+ end
39
66
  end
40
67
  end
41
68
  end
@@ -2,17 +2,23 @@
2
2
 
3
3
  require 'nokogiri'
4
4
  require 'rubygems/version'
5
+ require 'webdrivers/common'
5
6
 
6
7
  module Webdrivers
7
8
  class IEdriver < Common
8
9
  class << self
9
10
  def current_version
10
11
  Webdrivers.logger.debug 'Checking current version'
11
- return nil unless downloaded?
12
+ return nil unless exists?
12
13
 
13
- string = `#{binary} --version`
14
- Webdrivers.logger.debug "Current version of #{binary} is #{string}"
15
- normalize_version string.match(/IEDriverServer.exe (\d\.\d+\.\d*\.\d*)/)[1]
14
+ version = binary_version
15
+ return nil if version.nil?
16
+
17
+ normalize_version version.match(/IEDriverServer.exe (\d\.\d+\.\d+)/)[1]
18
+ end
19
+
20
+ def latest_version
21
+ @latest_version ||= with_cache(file_name) { downloads.keys.max }
16
22
  end
17
23
 
18
24
  private
@@ -26,7 +32,7 @@ module Webdrivers
26
32
  end
27
33
 
28
34
  def downloads
29
- doc = Nokogiri::XML.parse(get(base_url))
35
+ doc = Nokogiri::XML.parse(Network.get(base_url))
30
36
  items = doc.css('Key').collect(&:text)
31
37
  items.select! { |item| item.include?('IEDriverServer_Win32') }
32
38
  ds = items.each_with_object({}) do |item, hash|
@@ -39,3 +45,18 @@ module Webdrivers
39
45
  end
40
46
  end
41
47
  end
48
+
49
+ if ::Selenium::WebDriver::Service.respond_to? :driver_path=
50
+ ::Selenium::WebDriver::IE::Service.driver_path = proc { ::Webdrivers::IEdriver.update }
51
+ else
52
+ # v3.141.0 and lower
53
+ module Selenium
54
+ module WebDriver
55
+ module IE
56
+ def self.driver_path
57
+ @driver_path ||= Webdrivers::IEdriver.update
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end