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.
- checksums.yaml +4 -4
- data/.rubocop.yml +18 -9
- data/.travis.yml +1 -1
- data/CHANGELOG.md +9 -0
- data/LICENSE.txt +1 -1
- data/README.md +28 -24
- data/Rakefile +2 -0
- data/lib/webdrivers.rb +0 -22
- data/lib/webdrivers/chromedriver.rb +65 -59
- data/lib/webdrivers/common.rb +101 -167
- data/lib/webdrivers/geckodriver.rb +45 -18
- data/lib/webdrivers/iedriver.rb +26 -5
- data/lib/webdrivers/mswebdriver.rb +45 -49
- data/lib/webdrivers/network.rb +58 -0
- data/lib/webdrivers/system.rb +151 -0
- data/spec/spec_helper.rb +6 -0
- data/spec/webdrivers/chromedriver_spec.rb +197 -83
- data/spec/webdrivers/geckodriver_spec.rb +181 -37
- data/spec/webdrivers/i_edriver_spec.rb +171 -20
- data/spec/webdrivers/ms_webdriver_spec.rb +17 -13
- data/spec/webdrivers_proxy_support_spec.rb +2 -2
- data/webdrivers.gemspec +3 -2
- metadata +20 -5
- data/lib/webdrivers/selenium.rb +0 -40
data/lib/webdrivers/common.rb
CHANGED
@@ -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
|
8
|
-
|
9
|
-
attr_accessor :version
|
11
|
+
class ConnectionError < StandardError
|
12
|
+
end
|
10
13
|
|
11
|
-
|
12
|
-
|
13
|
-
return current_version.nil? ? nil : binary
|
14
|
-
end
|
14
|
+
class VersionError < StandardError
|
15
|
+
end
|
15
16
|
|
16
|
-
|
17
|
-
|
17
|
+
class << self
|
18
|
+
attr_accessor :proxy_addr, :proxy_port, :proxy_user, :proxy_pass, :install_dir
|
18
19
|
|
19
|
-
|
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
|
-
|
27
|
-
|
28
|
-
|
29
|
-
end
|
22
|
+
def cache_time
|
23
|
+
@cache_time || 0
|
24
|
+
end
|
30
25
|
|
31
|
-
|
32
|
-
|
33
|
-
|
26
|
+
def logger
|
27
|
+
@logger ||= Webdrivers::Logger.new
|
28
|
+
end
|
34
29
|
|
35
|
-
|
36
|
-
|
37
|
-
|
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
|
-
|
46
|
-
|
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
|
-
|
40
|
+
class Common
|
41
|
+
class << self
|
42
|
+
attr_writer :required_version
|
43
|
+
attr_reader :cache_warning
|
49
44
|
|
50
|
-
|
45
|
+
def version
|
46
|
+
Webdrivers.logger.deprecate("#{self.class}#version", "#{self.class}#required_version")
|
47
|
+
required_version
|
51
48
|
end
|
52
49
|
|
53
|
-
def
|
54
|
-
|
55
|
-
|
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
|
71
|
-
|
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
|
-
|
87
|
-
|
88
|
-
Webdrivers.logger.debug
|
89
|
-
|
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
|
-
|
94
|
-
|
95
|
-
binary
|
65
|
+
remove
|
66
|
+
System.download(download_url, driver_path)
|
96
67
|
end
|
97
68
|
|
98
|
-
def
|
99
|
-
|
100
|
-
|
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
|
-
|
103
|
-
File.join install_dir, file_name
|
74
|
+
desired_version.version.empty? ? latest_version : normalize_version(desired_version)
|
104
75
|
end
|
105
76
|
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
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
|
-
|
112
|
-
Webdrivers.logger.
|
84
|
+
def download
|
85
|
+
Webdrivers.logger.deprecate('#download', '#update')
|
86
|
+
System.download(download_url, driver_path)
|
87
|
+
end
|
113
88
|
|
114
|
-
|
115
|
-
|
116
|
-
|
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
|
127
|
-
|
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 ||=
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
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
|
146
|
-
|
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
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
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
|
162
|
-
|
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
|
172
|
-
|
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
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
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
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
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
|
11
|
+
return nil unless exists?
|
11
12
|
|
12
|
-
|
13
|
-
|
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
|
-
|
16
|
+
normalize_version version.match(/geckodriver (\d+\.\d+\.\d+)/)[1]
|
17
|
+
end
|
18
18
|
|
19
|
-
def
|
20
|
-
|
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
|
data/lib/webdrivers/iedriver.rb
CHANGED
@@ -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
|
12
|
+
return nil unless exists?
|
12
13
|
|
13
|
-
|
14
|
-
|
15
|
-
|
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
|