html-proofer 1.6.0 → 2.0.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.
Files changed (46) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +1 -1
  3. data/README.md +74 -56
  4. data/Rakefile +4 -6
  5. data/bin/htmlproof +46 -36
  6. data/html-proofer.gemspec +22 -22
  7. data/lib/html/proofer/check_runner/issue.rb +62 -0
  8. data/lib/html/proofer/{check.rb → check_runner.rb} +11 -19
  9. data/lib/html/proofer/checkable.rb +42 -28
  10. data/lib/html/proofer/checks/favicon.rb +6 -6
  11. data/lib/html/proofer/checks/html.rb +11 -12
  12. data/lib/html/proofer/checks/images.rb +11 -11
  13. data/lib/html/proofer/checks/links.rb +30 -28
  14. data/lib/html/proofer/checks/scripts.rb +7 -8
  15. data/lib/html/proofer/log.rb +38 -0
  16. data/lib/html/proofer/url_validator.rb +135 -0
  17. data/lib/html/proofer/utils.rb +24 -0
  18. data/lib/html/proofer/version.rb +1 -1
  19. data/lib/html/proofer.rb +95 -199
  20. data/spec/html/proofer/command_spec.rb +82 -0
  21. data/spec/html/proofer/favicon_spec.rb +20 -20
  22. data/spec/html/proofer/fixtures/images/srcSetCheck.html +7 -0
  23. data/spec/html/proofer/fixtures/images/srcSetIgnorable.html +13 -0
  24. data/spec/html/proofer/fixtures/images/srcSetMissingAlt.html +7 -0
  25. data/spec/html/proofer/fixtures/images/srcSetMissingImage.html +7 -0
  26. data/spec/html/proofer/fixtures/links/erstiebegru/314/210/303/237ung.html +1 -0
  27. data/spec/html/proofer/fixtures/links/erstiebegr/303/274/303/237ung.html +1 -0
  28. data/spec/html/proofer/fixtures/links/file.foo +11 -0
  29. data/spec/html/proofer/fixtures/links/folder/multiples/catalog/file.html +8 -0
  30. data/spec/html/proofer/fixtures/links/folder/multiples/javadoc/file.html +8 -0
  31. data/spec/html/proofer/fixtures/links/nodupe.html +1 -1
  32. data/spec/html/proofer/fixtures/links/redirected_error.html +1 -0
  33. data/spec/html/proofer/fixtures/links/rootLink/rootLink.html +0 -1
  34. data/spec/html/proofer/fixtures/links/urlencoded-href.html +2 -0
  35. data/spec/html/proofer/fixtures/links/utf8Link.html +2 -0
  36. data/spec/html/proofer/fixtures/utils/lang-jp.html +1 -0
  37. data/spec/html/proofer/html_spec.rb +25 -25
  38. data/spec/html/proofer/images_spec.rb +59 -35
  39. data/spec/html/proofer/links_spec.rb +152 -109
  40. data/spec/html/proofer/scripts_spec.rb +17 -17
  41. data/spec/html/proofer/utils_spec.rb +14 -0
  42. data/spec/html/proofer_spec.rb +58 -38
  43. data/spec/spec_helper.rb +13 -6
  44. metadata +39 -7
  45. data/lib/html/proofer/checks.rb +0 -15
  46. data/lib/html/proofer/issue.rb +0 -21
data/lib/html/proofer.rb CHANGED
@@ -1,40 +1,34 @@
1
- require 'nokogiri'
2
- require 'yell'
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 "awesome_print"
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 Yell::Loggable
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 => ".html",
37
- :favicon => false,
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 => "index.html",
47
- :validate_html => false,
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
- # Typhoeus won't let you pass in any non-Typhoeus option; if the option is not
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
- Yell.new({ :format => false, :name => "HTML::Proofer", :level => "gte.#{log_level}" }) do |l|
72
- l.adapter :stdout, level: [:debug, :info, :warn]
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
- unless @src.is_a? Array
79
- external_urls = {}
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
- logger.info HTML::colorize :green, "Ran on #{files.length} files!\n\n"
72
+ if @src.is_a?(Array) && !@options[:disable_external]
73
+ check_list_of_links
105
74
  else
106
- external_urls = Hash[*@src.map{ |s| [s, nil] }.flatten]
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 HTML::colorize :green, "HTML-Proofer finished successfully."
79
+ logger.log :info, :green, 'HTML-Proofer finished successfully.'
112
80
  else
113
- matcher = nil
114
-
115
- # always sort by the actual option, then path, to ensure consistent alphabetical (by filename) results
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
- @failed_tests.each do |issue|
122
- case @options[:error_sort]
123
- when :path
124
- if matcher != issue.path
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
- # the hypothesis is that Proofer runs way faster if we pull out
149
- # all the external URLs and run the checks at the end. Otherwise, we're halting
150
- # the consuming process for every file. In addition, sorting the list lets
151
- # libcurl keep connections to hosts alive. Finally, we'll make a HEAD request,
152
- # rather than GETing all the contents
153
- def external_link_checker(external_urls)
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
- Ethon.logger = logger # log from Typhoeus/Ethon
159
-
160
- external_urls.each_pair do |href, filenames|
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
- def queue_request(method, href, filenames)
172
- request = Typhoeus::Request.new(href, @typhoeus_opts.merge({:method => method}))
173
- request.on_complete { |response| response_handler(response, filenames) }
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
- def response_handler(response, filenames)
178
- effective_url = response.options[:effective_url]
179
- href = response.request.base_url
180
- method = response.request.options[:method]
181
- response_code = response.code
182
-
183
- debug_msg = "Received a #{response_code} for #{href}"
184
- debug_msg << " in #{filenames.join(' ')}" unless filenames.nil?
185
- logger.debug debug_msg
186
-
187
- if response_code.between?(200, 299)
188
- return if @options[:only_4xx]
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
- elsif response.timed_out?
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 hydra
218
- @hydra ||= Typhoeus::Hydra.new
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 @src, "**", "*#{@options[:ext]}"
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
- @options[:file_ignore].each do |pattern|
235
- if pattern.is_a? String
236
- return pattern == file
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 self.create_nokogiri(path)
246
- content = File.open(path).read
247
- Nokogiri::HTML(content)
248
- end
249
-
250
- def get_checks
251
- checks = HTML::Proofer::Checks::Check.subclasses.map { |c| c.name }
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 "spec_helper"
1
+ require 'spec_helper'
2
2
 
3
- describe "Favicons test" do
4
- it "ignores for absent favicon by default" do
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(make_proofer(absent).failed_tests).to eq []
6
+ expect(run_proofer(absent).failed_tests).to eq []
7
7
  end
8
8
 
9
- it "fails for absent favicon" do
9
+ it 'fails for absent favicon' do
10
10
  absent = "#{FIXTURES_DIR}/favicon/favicon_absent.html"
11
- proofer = make_proofer(absent, {:favicon => true})
12
- expect(proofer.failed_tests.first).to match /no favicon specified/
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 "fails for absent favicon but present apple touch icon" do
15
+ it 'fails for absent favicon but present apple touch icon' do
16
16
  absent = "#{FIXTURES_DIR}/favicon/favicon_absent_apple.html"
17
- proofer = make_proofer(absent, {:favicon => true})
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 /(internally linking to gpl.png, which does not exist|no favicon specified)/
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 "fails for broken favicon" do
22
+ it 'fails for broken favicon' do
23
23
  broken = "#{FIXTURES_DIR}/favicon/favicon_broken.html"
24
- proofer = make_proofer(broken, {:favicon => true})
24
+ proofer = run_proofer(broken, { :check_favicon => true })
25
25
 
26
- expect(proofer.failed_tests.first).to match /internally linking to asdadaskdalsdk.png/
26
+ expect(proofer.failed_tests.first).to match(/internally linking to asdadaskdalsdk.png/)
27
27
  end
28
28
 
29
- it "passes for present favicon" do
29
+ it 'passes for present favicon' do
30
30
  present = "#{FIXTURES_DIR}/favicon/favicon_present.html"
31
- proofer = make_proofer(present, {:favicon => true})
31
+ proofer = run_proofer(present, { :check_favicon => true })
32
32
  expect(proofer.failed_tests).to eq []
33
33
  end
34
34
 
35
- it "passes for present favicon with shortcut notation" do
35
+ it 'passes for present favicon with shortcut notation' do
36
36
  present = "#{FIXTURES_DIR}/favicon/favicon_present_shortcut.html"
37
- proofer = make_proofer(present, {:favicon => true})
37
+ proofer = run_proofer(present, { :check_favicon => true })
38
38
  expect(proofer.failed_tests).to eq []
39
39
  end
40
40
 
41
- it "fails for broken favicon with data-proofer-ignore" do
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 = make_proofer(broken_but_ignored, {:favicon => true})
44
- expect(proofer.failed_tests.first).to match /no favicon specified/
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,13 @@
1
+ <html>
2
+
3
+ <body>
4
+
5
+
6
+ <img src="gpl.png"/>Relative to self
7
+
8
+
9
+ <p>Blah blah blah. <img srcset="//upload.wikimedia.org/wikipedia/en/thumb/2/22/Heckert_GNU_white.svg/256px-Heckert_GNU_white.svg.png" /> </p>
10
+
11
+ </body>
12
+
13
+ </html>
@@ -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,11 @@
1
+ <html>
2
+
3
+ <body>
4
+
5
+ <p>Blah blah blah. <a href="http://www.google.com">Working link!</a></p>
6
+
7
+
8
+ <a href="http://www.asdo3IRJ395295jsingrkrg4.com">broken link!</a>
9
+ </body>
10
+
11
+ </html>
@@ -0,0 +1,8 @@
1
+ <html>
2
+
3
+ <body>
4
+
5
+ <a href="http://www.asdo3IRJ395295jsingrkrg4.com">broken link!</a>
6
+ </body>
7
+
8
+ </html>
@@ -0,0 +1,8 @@
1
+ <html>
2
+
3
+ <body>
4
+
5
+ <a href="http://www.asdo3IRJ395295jsingrkrg4.com">broken link!</a>
6
+ </body>
7
+
8
+ </html>
@@ -1 +1 @@
1
- <a href="https://help.github.com/articles/generating-ssh-keys#step-3-add-your-ssh-key-to-github">add ssh</a>
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>
@@ -3,7 +3,6 @@
3
3
  <body>
4
4
 
5
5
  <p>Blah blah blah. <a href="/">I am root.</a></p>
6
- <p>Blah blah blah. <a href="/folder">I am relative to root.</a></p>
7
6
 
8
7
  </body>
9
8
 
@@ -0,0 +1,2 @@
1
+ <a href="erstiebegr%C3%BC%C3%9Fung.html">Erstiebegrüßung</a>
2
+ <a href="erstiebegrüßung.html">Erstiebegrüßung</a>
@@ -0,0 +1,2 @@
1
+ <a href="http://ben.balter.com/2014/09/29/source-disclosed-≠-open-source/">utf8</a>
2
+ <a href="http://ben.balter.com/2014/09/29/source-disclosed-%E2%89%A0-open-source/">another utf8</a>
@@ -0,0 +1 @@
1
+ <html lang="jp">