html-proofer 1.6.0 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile +1 -1
- data/README.md +74 -56
- data/Rakefile +4 -6
- data/bin/htmlproof +46 -36
- data/html-proofer.gemspec +22 -22
- data/lib/html/proofer/check_runner/issue.rb +62 -0
- data/lib/html/proofer/{check.rb → check_runner.rb} +11 -19
- data/lib/html/proofer/checkable.rb +42 -28
- data/lib/html/proofer/checks/favicon.rb +6 -6
- data/lib/html/proofer/checks/html.rb +11 -12
- data/lib/html/proofer/checks/images.rb +11 -11
- data/lib/html/proofer/checks/links.rb +30 -28
- data/lib/html/proofer/checks/scripts.rb +7 -8
- data/lib/html/proofer/log.rb +38 -0
- data/lib/html/proofer/url_validator.rb +135 -0
- data/lib/html/proofer/utils.rb +24 -0
- data/lib/html/proofer/version.rb +1 -1
- data/lib/html/proofer.rb +95 -199
- data/spec/html/proofer/command_spec.rb +82 -0
- data/spec/html/proofer/favicon_spec.rb +20 -20
- data/spec/html/proofer/fixtures/images/srcSetCheck.html +7 -0
- data/spec/html/proofer/fixtures/images/srcSetIgnorable.html +13 -0
- data/spec/html/proofer/fixtures/images/srcSetMissingAlt.html +7 -0
- data/spec/html/proofer/fixtures/images/srcSetMissingImage.html +7 -0
- data/spec/html/proofer/fixtures/links/erstiebegru/314/210/303/237ung.html +1 -0
- data/spec/html/proofer/fixtures/links/erstiebegr/303/274/303/237ung.html +1 -0
- data/spec/html/proofer/fixtures/links/file.foo +11 -0
- data/spec/html/proofer/fixtures/links/folder/multiples/catalog/file.html +8 -0
- data/spec/html/proofer/fixtures/links/folder/multiples/javadoc/file.html +8 -0
- data/spec/html/proofer/fixtures/links/nodupe.html +1 -1
- data/spec/html/proofer/fixtures/links/redirected_error.html +1 -0
- data/spec/html/proofer/fixtures/links/rootLink/rootLink.html +0 -1
- data/spec/html/proofer/fixtures/links/urlencoded-href.html +2 -0
- data/spec/html/proofer/fixtures/links/utf8Link.html +2 -0
- data/spec/html/proofer/fixtures/utils/lang-jp.html +1 -0
- data/spec/html/proofer/html_spec.rb +25 -25
- data/spec/html/proofer/images_spec.rb +59 -35
- data/spec/html/proofer/links_spec.rb +152 -109
- data/spec/html/proofer/scripts_spec.rb +17 -17
- data/spec/html/proofer/utils_spec.rb +14 -0
- data/spec/html/proofer_spec.rb +58 -38
- data/spec/spec_helper.rb +13 -6
- metadata +39 -7
- data/lib/html/proofer/checks.rb +0 -15
- data/lib/html/proofer/issue.rb +0 -21
data/lib/html/proofer.rb
CHANGED
@@ -1,40 +1,34 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
def require_all(path)
|
2
|
+
glob = File.join(File.dirname(__FILE__), path, '*.rb')
|
3
|
+
Dir[glob].each do |f|
|
4
|
+
require f
|
5
|
+
end
|
6
|
+
end
|
7
|
+
|
8
|
+
require_all 'proofer'
|
9
|
+
require_all 'proofer/check_runner'
|
10
|
+
require_all 'proofer/checks'
|
11
|
+
require_relative './proofer/utils'
|
12
|
+
|
3
13
|
require 'parallel'
|
4
|
-
require "addressable/uri"
|
5
14
|
|
6
15
|
begin
|
7
|
-
require
|
16
|
+
require 'awesome_print'
|
8
17
|
rescue LoadError; end
|
9
18
|
|
10
|
-
%w[
|
11
|
-
checkable
|
12
|
-
checks
|
13
|
-
issue
|
14
|
-
version
|
15
|
-
].each { |r| require File.join(File.dirname(__FILE__), "proofer", r) }
|
16
|
-
|
17
19
|
module HTML
|
18
20
|
|
19
|
-
def self.colorize(color, string)
|
20
|
-
if $stdout.isatty && $stderr.isatty
|
21
|
-
Colored.colorize(string, :foreground => color)
|
22
|
-
else
|
23
|
-
string
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
21
|
class Proofer
|
28
|
-
include
|
22
|
+
include Utils
|
29
23
|
|
30
24
|
attr_reader :options, :typhoeus_opts, :parallel_opts
|
31
25
|
|
32
|
-
def initialize(src, opts={})
|
26
|
+
def initialize(src, opts = {})
|
33
27
|
@src = src
|
34
28
|
|
35
29
|
@proofer_opts = {
|
36
|
-
:ext =>
|
37
|
-
:
|
30
|
+
:ext => '.html',
|
31
|
+
:check_favicon => false,
|
38
32
|
:href_swap => [],
|
39
33
|
:href_ignore => [],
|
40
34
|
:file_ignore => [],
|
@@ -43,184 +37,103 @@ module HTML
|
|
43
37
|
:disable_external => false,
|
44
38
|
:verbose => false,
|
45
39
|
:only_4xx => false,
|
46
|
-
:directory_index_file =>
|
47
|
-
:
|
48
|
-
:error_sort => :path
|
40
|
+
:directory_index_file => 'index.html',
|
41
|
+
:check_html => false,
|
42
|
+
:error_sort => :path,
|
43
|
+
:checks_to_ignore => []
|
49
44
|
}
|
50
45
|
|
51
|
-
@typhoeus_opts = {
|
46
|
+
@typhoeus_opts = opts[:typhoeus] || {
|
52
47
|
:followlocation => true
|
53
48
|
}
|
49
|
+
opts.delete(:typhoeus)
|
50
|
+
|
51
|
+
@hydra_opts = opts[:hydra] || {}
|
52
|
+
opts.delete(:hydra)
|
54
53
|
|
55
54
|
# fall back to parallel defaults
|
56
55
|
@parallel_opts = opts[:parallel] || {}
|
57
56
|
opts.delete(:parallel)
|
58
57
|
|
59
|
-
|
60
|
-
# a proofer_opt, it must be for Typhoeus
|
61
|
-
opts.keys.each do |key|
|
62
|
-
if @proofer_opts[key].nil?
|
63
|
-
@typhoeus_opts[key] = opts[key]
|
64
|
-
end
|
65
|
-
end
|
66
|
-
|
67
|
-
@options = @proofer_opts.merge(@typhoeus_opts).merge(opts)
|
58
|
+
@options = @proofer_opts.merge(opts)
|
68
59
|
|
69
60
|
@failed_tests = []
|
61
|
+
end
|
70
62
|
|
71
|
-
|
72
|
-
|
73
|
-
l.adapter :stderr, level: [:error, :fatal]
|
74
|
-
end
|
63
|
+
def logger
|
64
|
+
@logger ||= HTML::Proofer::Log.new(@options[:verbose])
|
75
65
|
end
|
76
66
|
|
77
67
|
def run
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
logger.info HTML::colorize :white, "Running #{get_checks} checks on #{@src} on *#{@options[:ext]}... \n\n"
|
82
|
-
|
83
|
-
results = Parallel.map(files, @parallel_opts) do |path|
|
84
|
-
html = HTML::Proofer.create_nokogiri(path)
|
85
|
-
result = {:external_urls => {}, :failed_tests => []}
|
86
|
-
|
87
|
-
get_checks.each do |klass|
|
88
|
-
logger.debug HTML::colorize :blue, "Checking #{klass.to_s.downcase} on #{path} ..."
|
89
|
-
check = Object.const_get(klass).new(@src, path, html, @options)
|
90
|
-
check.run
|
91
|
-
result[:external_urls].merge!(check.external_urls)
|
92
|
-
result[:failed_tests].concat(check.issues) if check.issues.length > 0
|
93
|
-
end
|
94
|
-
result
|
95
|
-
end
|
96
|
-
|
97
|
-
results.each do |item|
|
98
|
-
external_urls.merge!(item[:external_urls])
|
99
|
-
@failed_tests.concat(item[:failed_tests])
|
100
|
-
end
|
101
|
-
|
102
|
-
external_link_checker(external_urls) unless @options[:disable_external]
|
68
|
+
count = checks.length
|
69
|
+
check_text = "#{checks} " << (count == 1 ? 'check' : 'checks')
|
70
|
+
logger.log :info, :blue, "Running #{check_text} on #{@src} on *#{@options[:ext]}... \n\n"
|
103
71
|
|
104
|
-
|
72
|
+
if @src.is_a?(Array) && !@options[:disable_external]
|
73
|
+
check_list_of_links
|
105
74
|
else
|
106
|
-
|
107
|
-
external_link_checker(external_urls) unless @options[:disable_external]
|
75
|
+
check_directory_of_files
|
108
76
|
end
|
109
77
|
|
110
78
|
if @failed_tests.empty?
|
111
|
-
logger.info
|
79
|
+
logger.log :info, :green, 'HTML-Proofer finished successfully.'
|
112
80
|
else
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
@failed_tests = @failed_tests.sort do |a,b|
|
117
|
-
comp = (a.send(@options[:error_sort]) <=> b.send(@options[:error_sort]))
|
118
|
-
comp.zero? ? (a.path <=> b.path) : comp
|
119
|
-
end
|
81
|
+
print_failed_tests
|
82
|
+
end
|
83
|
+
end
|
120
84
|
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
logger.error HTML::colorize :blue, "- #{issue.path}"
|
126
|
-
matcher = issue.path
|
127
|
-
end
|
128
|
-
logger.error HTML::colorize :red, " * #{issue.desc}"
|
129
|
-
when :desc
|
130
|
-
if matcher != issue.desc
|
131
|
-
logger.error HTML::colorize :blue, "- #{issue.desc}"
|
132
|
-
matcher = issue.desc
|
133
|
-
end
|
134
|
-
logger.error HTML::colorize :red, " * #{issue.path}"
|
135
|
-
when :status
|
136
|
-
if matcher != issue.status
|
137
|
-
logger.error HTML::colorize :blue, "- #{issue.status}"
|
138
|
-
matcher = issue.status
|
139
|
-
end
|
140
|
-
logger.error HTML::colorize :red, " * #{issue.to_s}"
|
141
|
-
end
|
85
|
+
def check_list_of_links
|
86
|
+
if @options[:href_swap]
|
87
|
+
@src = @src.map do |external_url|
|
88
|
+
swap(external_url, @options[:href_swap])
|
142
89
|
end
|
143
|
-
|
144
|
-
raise HTML::colorize :red, "HTML-Proofer found #{@failed_tests.length} failures!"
|
145
90
|
end
|
91
|
+
external_urls = Hash[*@src.map { |s| [s, nil] }.flatten]
|
92
|
+
validate_urls(external_urls)
|
146
93
|
end
|
147
94
|
|
148
|
-
#
|
149
|
-
#
|
150
|
-
# the
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
external_urls = Hash[external_urls.sort]
|
155
|
-
|
156
|
-
logger.info HTML::colorize :yellow, "Checking #{external_urls.length} external links..."
|
95
|
+
# Collects any external URLs found in a directory of files. Also collectes
|
96
|
+
# every failed test from check_files_for_internal_woes.
|
97
|
+
# Sends the external URLs to Typhoeus for batch processing.
|
98
|
+
def check_directory_of_files
|
99
|
+
external_urls = {}
|
100
|
+
results = check_files_for_internal_woes
|
157
101
|
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
if has_hash? href && @options[:check_external_hash]
|
162
|
-
queue_request(:get, href, filenames)
|
163
|
-
else
|
164
|
-
queue_request(:head, href, filenames)
|
165
|
-
end
|
102
|
+
results.each do |item|
|
103
|
+
external_urls.merge!(item[:external_urls])
|
104
|
+
@failed_tests.concat(item[:failed_tests])
|
166
105
|
end
|
167
|
-
logger.debug HTML::colorize :yellow, "Running requests for all #{hydra.queued_requests.size} external URLs..."
|
168
|
-
hydra.run
|
169
|
-
end
|
170
106
|
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
hydra.queue request
|
107
|
+
validate_urls(external_urls) unless @options[:disable_external]
|
108
|
+
|
109
|
+
logger.log :info, :blue, "Ran on #{files.length} files!\n\n"
|
175
110
|
end
|
176
111
|
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
return unless @options[:check_external_hash]
|
190
|
-
if hash = has_hash?(href)
|
191
|
-
body_doc = Nokogiri::HTML(response.body)
|
192
|
-
# user-content is a special addition by GitHub.
|
193
|
-
xpath = %$//*[@name="#{hash}"]|//*[@id="#{hash}"]$
|
194
|
-
xpath << %$|//*[@name="user-content-#{hash}"]|//*[@id="user-content-#{hash}"]$ if URI.parse(href).host.match(/github\.com/i)
|
195
|
-
if body_doc.xpath(xpath).empty?
|
196
|
-
add_failed_tests filenames, "External link #{href} failed: #{effective_url} exists, but the hash '#{hash}' does not", response_code
|
197
|
-
end
|
112
|
+
# Walks over each implemented check and runs them on the files, in parallel.
|
113
|
+
def check_files_for_internal_woes
|
114
|
+
Parallel.map(files, @parallel_opts) do |path|
|
115
|
+
html = create_nokogiri(path)
|
116
|
+
result = { :external_urls => {}, :failed_tests => [] }
|
117
|
+
|
118
|
+
checks.each do |klass|
|
119
|
+
logger.log :debug, :yellow, "Checking #{klass.to_s.downcase} on #{path} ..."
|
120
|
+
check = Object.const_get(klass).new(@src, path, html, @options)
|
121
|
+
check.run
|
122
|
+
result[:external_urls].merge!(check.external_urls)
|
123
|
+
result[:failed_tests].concat(check.issues) if check.issues.length > 0
|
198
124
|
end
|
199
|
-
|
200
|
-
return if @options[:only_4xx]
|
201
|
-
add_failed_tests filenames, "External link #{href} failed: got a time out", response_code
|
202
|
-
elsif (response_code == 405 || response_code == 420 || response_code == 503) && method == :head
|
203
|
-
# 420s usually come from rate limiting; let's ignore the query and try just the path with a GET
|
204
|
-
uri = URI(href)
|
205
|
-
queue_request(:get, uri.scheme + "://" + uri.host + uri.path, filenames)
|
206
|
-
# just be lazy; perform an explicit get request. some servers are apparently not configured to
|
207
|
-
# intercept HTTP HEAD
|
208
|
-
elsif method == :head
|
209
|
-
queue_request(:get, effective_url, filenames)
|
210
|
-
else
|
211
|
-
return if @options[:only_4xx] && !response_code.between?(400, 499)
|
212
|
-
# Received a non-successful http response.
|
213
|
-
add_failed_tests filenames, "External link #{href} failed: #{response_code} #{response.return_message}", response_code
|
125
|
+
result
|
214
126
|
end
|
215
127
|
end
|
216
128
|
|
217
|
-
def
|
218
|
-
|
129
|
+
def validate_urls(external_urls)
|
130
|
+
url_validator = HTML::Proofer::UrlValidator.new(logger, external_urls, @options, @typhoeus_opts, @hydra_opts)
|
131
|
+
@failed_tests.concat(url_validator.run)
|
219
132
|
end
|
220
133
|
|
221
134
|
def files
|
222
135
|
if File.directory? @src
|
223
|
-
pattern = File.join
|
136
|
+
pattern = File.join(@src, '**', "*#{@options[:ext]}")
|
224
137
|
files = Dir.glob(pattern).select { |fn| File.file? fn }
|
225
138
|
files.reject { |f| ignore_file?(f) }
|
226
139
|
elsif File.extname(@src) == @options[:ext]
|
@@ -231,49 +144,23 @@ module HTML
|
|
231
144
|
end
|
232
145
|
|
233
146
|
def ignore_file?(file)
|
234
|
-
|
235
|
-
if pattern.is_a?
|
236
|
-
|
237
|
-
elsif pattern.is_a? Regexp
|
238
|
-
return pattern =~ file
|
239
|
-
end
|
147
|
+
options[:file_ignore].each do |pattern|
|
148
|
+
return true if pattern.is_a?(String) && pattern == file
|
149
|
+
return true if pattern.is_a?(Regexp) && pattern =~ file
|
240
150
|
end
|
241
151
|
|
242
152
|
false
|
243
153
|
end
|
244
154
|
|
245
|
-
def
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
checks.delete("Favicons") unless @options[:favicon]
|
253
|
-
checks.delete("Html") unless @options[:validate_html]
|
254
|
-
checks
|
255
|
-
end
|
256
|
-
|
257
|
-
def has_hash?(url)
|
258
|
-
begin
|
259
|
-
URI.parse(url).fragment
|
260
|
-
rescue URI::InvalidURIError
|
261
|
-
nil
|
262
|
-
end
|
263
|
-
end
|
264
|
-
|
265
|
-
def log_level
|
266
|
-
@options[:verbose] ? :debug : :info
|
267
|
-
end
|
268
|
-
|
269
|
-
def add_failed_tests(filenames, desc, status = nil)
|
270
|
-
if filenames.nil?
|
271
|
-
@failed_tests << Checks::Issue.new("", desc, status)
|
272
|
-
elsif
|
273
|
-
filenames.each { |f|
|
274
|
-
@failed_tests << Checks::Issue.new(f, desc, status)
|
275
|
-
}
|
155
|
+
def checks
|
156
|
+
return @checks unless @checks.nil?
|
157
|
+
@checks = HTML::Proofer::CheckRunner.checks.map(&:name)
|
158
|
+
@checks.delete('FaviconCheck') unless @options[:check_favicon]
|
159
|
+
@checks.delete('HtmlCheck') unless @options[:check_html]
|
160
|
+
@options[:checks_to_ignore].each do |ignored|
|
161
|
+
@checks.delete(ignored)
|
276
162
|
end
|
163
|
+
@checks
|
277
164
|
end
|
278
165
|
|
279
166
|
def failed_tests
|
@@ -282,5 +169,14 @@ module HTML
|
|
282
169
|
@failed_tests.each { |f| result << f.to_s }
|
283
170
|
result
|
284
171
|
end
|
172
|
+
|
173
|
+
def print_failed_tests
|
174
|
+
sorted_failures = HTML::Proofer::CheckRunner::SortedIssues.new(@failed_tests, @options[:error_sort], logger)
|
175
|
+
|
176
|
+
sorted_failures.sort_and_report
|
177
|
+
count = @failed_tests.length
|
178
|
+
failure_text = "#{count} " << (count == 1 ? 'failure' : 'failures')
|
179
|
+
fail logger.colorize :red, "HTML-Proofer found #{failure_text}!"
|
180
|
+
end
|
285
181
|
end
|
286
182
|
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe 'Command test' do
|
4
|
+
it 'works with as-links' do
|
5
|
+
output = make_bin('--as-links www.github.com,foofoofoo.biz')
|
6
|
+
expect(output).to match('1 failure')
|
7
|
+
end
|
8
|
+
|
9
|
+
it 'works with alt-ignore' do
|
10
|
+
ignorableLinks = "#{FIXTURES_DIR}/images/ignorableAltViaOptions.html"
|
11
|
+
output = make_bin('--alt-ignore /wikimedia/,gpl.png', ignorableLinks)
|
12
|
+
expect(output).to match('successfully')
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'works with checks_to_ignore' do
|
16
|
+
external = "#{FIXTURES_DIR}/links/file.foo"
|
17
|
+
output = make_bin('--ext .foo --checks-to-ignore LinkCheck', external)
|
18
|
+
expect(output).to match('successfully')
|
19
|
+
expect(output).to_not match('LinkCheck')
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'works with check-external-hash' do
|
23
|
+
brokenHashOnTheWeb = "#{FIXTURES_DIR}/links/brokenHashOnTheWeb.html"
|
24
|
+
output = make_bin('--check-external-hash', brokenHashOnTheWeb)
|
25
|
+
expect(output).to match('1 failure')
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'works with directory-index-file' do
|
29
|
+
link_pointing_to_directory = "#{FIXTURES_DIR}/links/link_pointing_to_directory.html"
|
30
|
+
output = make_bin('--directory-index-file index.php', link_pointing_to_directory)
|
31
|
+
expect(output).to match('successfully')
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'works with disable-external' do
|
35
|
+
external = "#{FIXTURES_DIR}/links/brokenLinkExternal.html"
|
36
|
+
output = make_bin('--disable-external', external)
|
37
|
+
expect(output).to match('successfully')
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'works with ext' do
|
41
|
+
external = "#{FIXTURES_DIR}/links/file.foo"
|
42
|
+
output = make_bin('--ext .foo', external)
|
43
|
+
expect(output).to match('1 failure')
|
44
|
+
expect(output).to match('LinkCheck')
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'works with file-ignore' do
|
48
|
+
external = "#{FIXTURES_DIR}/links/brokenHashInternal.html"
|
49
|
+
output = make_bin("--file-ignore #{external}", external)
|
50
|
+
expect(output).to match('successfully')
|
51
|
+
end
|
52
|
+
|
53
|
+
it 'works with href-ignore' do
|
54
|
+
ignorableLinks = "#{FIXTURES_DIR}/links/ignorableLinksViaOptions.html"
|
55
|
+
output = make_bin('--href-ignore /^http:\/\//,/sdadsad/,../whaadadt.html', ignorableLinks)
|
56
|
+
expect(output).to match('successfully')
|
57
|
+
end
|
58
|
+
|
59
|
+
it 'works with href-swap' do
|
60
|
+
translatedLink = "#{FIXTURES_DIR}/links/linkTranslatedViaHrefSwap.html"
|
61
|
+
output = make_bin('--href-swap "\A/articles/([\w-]+):\1.html"', translatedLink)
|
62
|
+
expect(output).to match('successfully')
|
63
|
+
end
|
64
|
+
|
65
|
+
it 'works with only-4xx' do
|
66
|
+
brokenHashOnTheWeb = "#{FIXTURES_DIR}/links/brokenHashOnTheWeb.html"
|
67
|
+
output = make_bin('--only-4xx', brokenHashOnTheWeb)
|
68
|
+
expect(output).to match('successfully')
|
69
|
+
end
|
70
|
+
|
71
|
+
it 'works with check-favicon' do
|
72
|
+
broken = "#{FIXTURES_DIR}/favicon/favicon_broken.html"
|
73
|
+
output = make_bin('--check-favicon', broken)
|
74
|
+
expect(output).to match('1 failure')
|
75
|
+
end
|
76
|
+
|
77
|
+
it 'works with check-html' do
|
78
|
+
broken = "#{FIXTURES_DIR}/html/invalid_tag.html"
|
79
|
+
output = make_bin('--check-html', broken)
|
80
|
+
expect(output).to match('1 failure')
|
81
|
+
end
|
82
|
+
end
|
@@ -1,47 +1,47 @@
|
|
1
|
-
require
|
1
|
+
require 'spec_helper'
|
2
2
|
|
3
|
-
describe
|
4
|
-
it
|
3
|
+
describe 'Favicons test' do
|
4
|
+
it 'ignores for absent favicon by default' do
|
5
5
|
absent = "#{FIXTURES_DIR}/favicon/favicon_absent.html"
|
6
|
-
expect(
|
6
|
+
expect(run_proofer(absent).failed_tests).to eq []
|
7
7
|
end
|
8
8
|
|
9
|
-
it
|
9
|
+
it 'fails for absent favicon' do
|
10
10
|
absent = "#{FIXTURES_DIR}/favicon/favicon_absent.html"
|
11
|
-
proofer =
|
12
|
-
expect(proofer.failed_tests.first).to match
|
11
|
+
proofer = run_proofer(absent, { :check_favicon => true })
|
12
|
+
expect(proofer.failed_tests.first).to match(/no favicon specified/)
|
13
13
|
end
|
14
14
|
|
15
|
-
it
|
15
|
+
it 'fails for absent favicon but present apple touch icon' do
|
16
16
|
absent = "#{FIXTURES_DIR}/favicon/favicon_absent_apple.html"
|
17
|
-
proofer =
|
17
|
+
proofer = run_proofer(absent, { :check_favicon => true })
|
18
18
|
# Travis gives a different error message here for some reason
|
19
|
-
expect(proofer.failed_tests.last).to match
|
19
|
+
expect(proofer.failed_tests.last).to match(/(internally linking to gpl.png, which does not exist|no favicon specified)/)
|
20
20
|
end
|
21
21
|
|
22
|
-
it
|
22
|
+
it 'fails for broken favicon' do
|
23
23
|
broken = "#{FIXTURES_DIR}/favicon/favicon_broken.html"
|
24
|
-
proofer =
|
24
|
+
proofer = run_proofer(broken, { :check_favicon => true })
|
25
25
|
|
26
|
-
expect(proofer.failed_tests.first).to match
|
26
|
+
expect(proofer.failed_tests.first).to match(/internally linking to asdadaskdalsdk.png/)
|
27
27
|
end
|
28
28
|
|
29
|
-
it
|
29
|
+
it 'passes for present favicon' do
|
30
30
|
present = "#{FIXTURES_DIR}/favicon/favicon_present.html"
|
31
|
-
proofer =
|
31
|
+
proofer = run_proofer(present, { :check_favicon => true })
|
32
32
|
expect(proofer.failed_tests).to eq []
|
33
33
|
end
|
34
34
|
|
35
|
-
it
|
35
|
+
it 'passes for present favicon with shortcut notation' do
|
36
36
|
present = "#{FIXTURES_DIR}/favicon/favicon_present_shortcut.html"
|
37
|
-
proofer =
|
37
|
+
proofer = run_proofer(present, { :check_favicon => true })
|
38
38
|
expect(proofer.failed_tests).to eq []
|
39
39
|
end
|
40
40
|
|
41
|
-
it
|
41
|
+
it 'fails for broken favicon with data-proofer-ignore' do
|
42
42
|
broken_but_ignored = "#{FIXTURES_DIR}/favicon/favicon_broken_but_ignored.html"
|
43
|
-
proofer =
|
44
|
-
expect(proofer.failed_tests.first).to match
|
43
|
+
proofer = run_proofer(broken_but_ignored, { :check_favicon => true })
|
44
|
+
expect(proofer.failed_tests.first).to match(/no favicon specified/)
|
45
45
|
end
|
46
46
|
|
47
47
|
end
|
@@ -0,0 +1,7 @@
|
|
1
|
+
<picture>
|
2
|
+
<!--[if IE 9]><video style="display: none;"><![endif]-->
|
3
|
+
<source srcset="examples/images/extralarge.jpg" media="(min-width: 1000px)">
|
4
|
+
<source srcset="examples/images/large.jpg" media="(min-width: 800px)">
|
5
|
+
<!--[if IE 9]></video><![endif]-->
|
6
|
+
<img src="gpl.png" alt="Working">
|
7
|
+
</picture>
|
@@ -0,0 +1,7 @@
|
|
1
|
+
<picture>
|
2
|
+
<!--[if IE 9]><video style="display: none;"><![endif]-->
|
3
|
+
<source srcset="examples/images/extralarge.jpg" media="(min-width: 1000px)">
|
4
|
+
<source srcset="examples/images/large.jpg" media="(min-width: 800px)">
|
5
|
+
<!--[if IE 9]></video><![endif]-->
|
6
|
+
<img srcset="gpl.png">
|
7
|
+
</picture>
|
@@ -0,0 +1,7 @@
|
|
1
|
+
<picture>
|
2
|
+
<!--[if IE 9]><video style="display: none;"><![endif]-->
|
3
|
+
<source srcset="examples/images/extralarge.jpg" media="(min-width: 1000px)">
|
4
|
+
<source srcset="examples/images/large.jpg" media="(min-width: 800px)">
|
5
|
+
<!--[if IE 9]></video><![endif]-->
|
6
|
+
<img srcset="notreal.png" alt="Missing image">
|
7
|
+
</picture>
|
@@ -0,0 +1 @@
|
|
1
|
+
|
@@ -0,0 +1 @@
|
|
1
|
+
|
@@ -1 +1 @@
|
|
1
|
-
<a href="https://help.github.com/
|
1
|
+
<a href="https://help.github.com/articlezzz">add ssh</a>
|
@@ -0,0 +1 @@
|
|
1
|
+
<a href="http://asia.cnet.com/blogs/geekonomics/post.htm?id=63009224">not real</a>
|
@@ -0,0 +1 @@
|
|
1
|
+
<html lang="jp">
|