webdrivers 3.8.1 → 3.9.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|