html_validation 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.document +5 -0
- data/.gitignore +4 -0
- data/.rspec +1 -0
- data/Gemfile +23 -0
- data/Gemfile.lock +31 -0
- data/LICENSE.txt +20 -0
- data/README.rdoc +113 -0
- data/Rakefile +2 -0
- data/VERSION +1 -0
- data/html_validation.gemspec +17 -0
- data/lib/html_validation/have_valid_html.rb +44 -0
- data/lib/html_validation/html_validation_matcher.rb +21 -0
- data/lib/html_validation/html_validation_result.rb +93 -0
- data/lib/html_validation/version.rb +3 -0
- data/lib/html_validation.rb +82 -0
- data/lib/tasks/validation.thor +27 -0
- data/spec/html_validator_matcher_spec.rb +47 -0
- data/spec/html_validator_spec.rb +133 -0
- data/spec/spec_helper.rb +14 -0
- metadata +68 -0
data/.document
ADDED
data/.gitignore
ADDED
data/.rspec
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--color
|
data/Gemfile
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
source "http://rubygems.org"
|
2
|
+
|
3
|
+
gemspec
|
4
|
+
|
5
|
+
# Add dependencies to develop your gem here.
|
6
|
+
# Include everything needed to run rake, tests, features, etc.
|
7
|
+
group :development do
|
8
|
+
gem "rspec"
|
9
|
+
gem "bundler"
|
10
|
+
end
|
11
|
+
|
12
|
+
gem 'rdoc'
|
13
|
+
gem 'thor'
|
14
|
+
|
15
|
+
# Unix Rubies (OSX, Linux)
|
16
|
+
platform :ruby do
|
17
|
+
|
18
|
+
end
|
19
|
+
|
20
|
+
# Windows Rubies (RubyInstaller)
|
21
|
+
platforms :mswin, :mingw do
|
22
|
+
|
23
|
+
end
|
data/Gemfile.lock
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
html_validation (0.0.1)
|
5
|
+
|
6
|
+
GEM
|
7
|
+
remote: http://rubygems.org/
|
8
|
+
specs:
|
9
|
+
diff-lcs (1.1.3)
|
10
|
+
json (1.7.7)
|
11
|
+
rdoc (4.0.0)
|
12
|
+
json (~> 1.4)
|
13
|
+
rspec (2.11.0)
|
14
|
+
rspec-core (~> 2.11.0)
|
15
|
+
rspec-expectations (~> 2.11.0)
|
16
|
+
rspec-mocks (~> 2.11.0)
|
17
|
+
rspec-core (2.11.1)
|
18
|
+
rspec-expectations (2.11.2)
|
19
|
+
diff-lcs (~> 1.1.3)
|
20
|
+
rspec-mocks (2.11.1)
|
21
|
+
thor (0.17.0)
|
22
|
+
|
23
|
+
PLATFORMS
|
24
|
+
ruby
|
25
|
+
|
26
|
+
DEPENDENCIES
|
27
|
+
bundler
|
28
|
+
html_validation!
|
29
|
+
rdoc
|
30
|
+
rspec
|
31
|
+
thor
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2012 - 2013 Eric Beland
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.rdoc
ADDED
@@ -0,0 +1,113 @@
|
|
1
|
+
= HTML Validation
|
2
|
+
|
3
|
+
html_validation helps you validate, track, and fix or accept HTML validation
|
4
|
+
issues without depending on an external web service.
|
5
|
+
The idea is to take an HTML markup string associated
|
6
|
+
with a particular resource (file or URL) and validate it locally.
|
7
|
+
No web connection or dependency on a 3rd party web service is involved--just an
|
8
|
+
install of HTML Tidy, which is supported by the W3C. An RSPec matcher is included.
|
9
|
+
|
10
|
+
HTML Validation is intended to be used in acceptance tests, test suites or rake
|
11
|
+
tasks to alert you to changes in your html's validity so you can fix them, or
|
12
|
+
barring that, review and accept any errors and warnings.
|
13
|
+
|
14
|
+
== HTML 5
|
15
|
+
|
16
|
+
The current (as of March 2013) default version of Tidy doesn't support HTML 5.
|
17
|
+
To get HTML 5 support, install this fork of tidy: https://github.com/w3c/tidy-html5
|
18
|
+
Download the repo as a zip file and extract somewhere, then follow the instructions
|
19
|
+
given on the page (using sudo for make commands if on Linux).
|
20
|
+
|
21
|
+
Be sure to get rid of the old tidy first if you have it already.
|
22
|
+
|
23
|
+
Redhat/Fedora: sudo yum erase tidy
|
24
|
+
Ubuntu: sudo apt-get remove tidy
|
25
|
+
OS X: sudo port uninstall tidy
|
26
|
+
|
27
|
+
On linux/OS X machines, confirm the right installation path shows up with: which tidy
|
28
|
+
|
29
|
+
== RSpec Setup / Usage:
|
30
|
+
Add to spec/spec_helper.rb:
|
31
|
+
|
32
|
+
require 'html_validation'
|
33
|
+
include PageValidations
|
34
|
+
|
35
|
+
Now, within your Integration Tests, you can do this:
|
36
|
+
|
37
|
+
page.should have_valid_html
|
38
|
+
|
39
|
+
It can be convenient to see the html printed in the RSpec failure messages.
|
40
|
+
To enable this feature:
|
41
|
+
|
42
|
+
HaveValidHTML.show_html_in_failures = true
|
43
|
+
|
44
|
+
== Non-RSpec Usage:
|
45
|
+
|
46
|
+
require 'html_validation'
|
47
|
+
|
48
|
+
|
49
|
+
h = HTMLValidation.new
|
50
|
+
v = h.validation("<html>foo</html>", 'http://somesite.com/index.html')
|
51
|
+
|
52
|
+
# Note: The second argument (resource) just serves as an identifier used to
|
53
|
+
# name our results files, and no data is actually retrieved for you from on the URL!
|
54
|
+
|
55
|
+
v.valid?
|
56
|
+
-> false
|
57
|
+
|
58
|
+
v.exceptions
|
59
|
+
-> line 1 column 1 - Warning: missing <!DOCTYPE> declaration
|
60
|
+
-> line 1 column 9 - Warning: plain text isn't allowed in <head> elements
|
61
|
+
-> line 1 column 9 - Warning: inserting missing 'title' element
|
62
|
+
|
63
|
+
v.accept!
|
64
|
+
|
65
|
+
v.valid?
|
66
|
+
-> true
|
67
|
+
|
68
|
+
# Note: after the exceptions string has been accepted, the exceptions
|
69
|
+
# are still available in v.exceptions even though valid? will return true.
|
70
|
+
|
71
|
+
# The exception string is treated and matched as a whole. The current
|
72
|
+
# implementation does not allow partial acceptance of individual
|
73
|
+
# results in a result string.
|
74
|
+
|
75
|
+
== Accepting Errors
|
76
|
+
|
77
|
+
The HTML Validation gem stores failure data per-resource. The results are stored
|
78
|
+
in the data_folder. Typically this is the default folder: spec/.validation.
|
79
|
+
After a validation fails, run the thor task to accept or reject validation exceptions.
|
80
|
+
|
81
|
+
From your project's root folder, run: thor validation:review
|
82
|
+
|
83
|
+
Note, if you configure an alternate data_folder, you may pass it as an option
|
84
|
+
to the Thor task.
|
85
|
+
|
86
|
+
|
87
|
+
== NOTES
|
88
|
+
|
89
|
+
This is untested on Windows as I don't have access to a Windows machine at the moment.
|
90
|
+
It is written so it could (probably) work on Windows. Pull requests in this area would
|
91
|
+
be welcomed.
|
92
|
+
|
93
|
+
== Requirements
|
94
|
+
|
95
|
+
HTML Tidy needs to be either installed at /usr/bin/tidy or on the PATH.
|
96
|
+
|
97
|
+
|
98
|
+
== Contributing to html_validation
|
99
|
+
|
100
|
+
* Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet
|
101
|
+
* Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it
|
102
|
+
* Fork the project
|
103
|
+
* Start a feature/bugfix branch
|
104
|
+
* Commit and push until you are happy with your contribution
|
105
|
+
* Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
|
106
|
+
|
107
|
+
|
108
|
+
=== Running the tests
|
109
|
+
|
110
|
+
After tidy has been installed, in the gem folder, run: rspec spec
|
111
|
+
|
112
|
+
Copyright (c) 2012 Eric Beland. See LICENSE.txt for further details.
|
113
|
+
|
data/Rakefile
ADDED
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.1.1
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
require File.expand_path('../lib/html_validation/version', __FILE__)
|
3
|
+
|
4
|
+
Gem::Specification.new do |gem|
|
5
|
+
gem.authors = ["Eric Beland"]
|
6
|
+
gem.email = ["ebeland@gmail.com"]
|
7
|
+
gem.description = %q{HTML Validation lets you validate html locally. Lets you build html validation into your test suite, but break the rules if you must.}
|
8
|
+
gem.summary = %q{Local HTML validation for tests and RSpec. }
|
9
|
+
gem.homepage = "https://github.com/ericbeland/html_validation"
|
10
|
+
|
11
|
+
gem.files = `git ls-files`.split($\)
|
12
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
13
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
14
|
+
gem.name = "html_validation"
|
15
|
+
gem.require_paths = ["lib"]
|
16
|
+
gem.version = PageValidations::HTML_VALIDATOR_VERSION
|
17
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'html_validation'
|
2
|
+
|
3
|
+
# This is a sample matcher for use with Rspec and Capybara.
|
4
|
+
# https://github.com/jnicklas/capybara
|
5
|
+
# keep this in spec/support/matchers
|
6
|
+
module PageValidations
|
7
|
+
|
8
|
+
class HaveValidHTML
|
9
|
+
|
10
|
+
# This is the matching method called by RSpec
|
11
|
+
# The response is passed in as an argument when you do this:
|
12
|
+
# page.should have_valid_html
|
13
|
+
|
14
|
+
@@show_html_in_failures = false
|
15
|
+
|
16
|
+
def self.show_html_in_failures=(val)
|
17
|
+
@@show_html_in_failures = val
|
18
|
+
end
|
19
|
+
|
20
|
+
def matches?(page)
|
21
|
+
h = HTMLValidation.new
|
22
|
+
@v = h.validation(page.body, page.current_url)
|
23
|
+
@v.valid?
|
24
|
+
end
|
25
|
+
|
26
|
+
def description
|
27
|
+
"Have valid html"
|
28
|
+
end
|
29
|
+
|
30
|
+
def failure_message_for_should
|
31
|
+
"#{@v.resource} Invalid html (fix or run rake html_validation task to add exceptions)\n#{@v.resource} exceptions:\n #{@v.exceptions}\n\n #{@v.html if @@show_html_in_failures}"
|
32
|
+
end
|
33
|
+
|
34
|
+
def failure_message_for_should_not
|
35
|
+
"#{@v.resource} Expected valid? to fail but didn't. Did you accidentally accept these html validation errors? \n#{@v.resource} exceptions:\n #{@v.exceptions}\n\n #{@v.html if @@show_html_in_failures}"
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
|
40
|
+
def have_valid_html
|
41
|
+
HaveValidHTML.new
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# the item to include to get the RSPec matcher(s)
|
2
|
+
|
3
|
+
require File.expand_path(File.join(File.dirname(__FILE__), 'have_valid_html'))
|
4
|
+
|
5
|
+
module HTMLValidationMatcher
|
6
|
+
@@data_path = nil
|
7
|
+
|
8
|
+
def self.included(base)
|
9
|
+
# get path of including file, which should be in the /spec folder
|
10
|
+
@@data_path, = File.expand_path(File.dirname(caller[0].partition(":")[0]))
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.data_path
|
14
|
+
@@data_path
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.data_path=(path)
|
18
|
+
@@data_path = path
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
@@ -0,0 +1,93 @@
|
|
1
|
+
require 'open3'
|
2
|
+
|
3
|
+
class HTMLValidationResult
|
4
|
+
attr_accessor :resource, :html, :exceptions
|
5
|
+
|
6
|
+
include PageValidations
|
7
|
+
# valid options[:tidy_opts]
|
8
|
+
def initialize(resource, html, datapath, options={})
|
9
|
+
@resource = resource
|
10
|
+
@html = html
|
11
|
+
@exceptions = ''
|
12
|
+
@datapath = datapath
|
13
|
+
@tidyopts = options[:tidy_opts] || "-qi"
|
14
|
+
@ignore_proprietary = options[:ignore_proprietary]
|
15
|
+
valid?
|
16
|
+
end
|
17
|
+
|
18
|
+
# takes a .url and loads the data into this object
|
19
|
+
def self.load_from_files(filepath)
|
20
|
+
resource = File.open("#{filepath}.resource.txt", 'r').read
|
21
|
+
html = File.open("#{filepath}.html.txt", 'r').read
|
22
|
+
HTMLValidationResult.new(resource, html, filepath)
|
23
|
+
end
|
24
|
+
|
25
|
+
# Validates an html string using html tidy. If there are no warnings or exceptions, or
|
26
|
+
# there is a previously accepted exception string that matches exactly, valid? returns true
|
27
|
+
# Line numbers of exceptions are likely to change with any edit, so our validation
|
28
|
+
# compares the exception strings with the lines and columns removed. Name can be a filename,
|
29
|
+
# file system path, or url, so long it is uniquely associated with the passed in html.
|
30
|
+
def valid?
|
31
|
+
@exceptions = validate
|
32
|
+
File.delete(data_path("accepted")) if File.exists?(data_path("accepted")) if @exceptions == ''
|
33
|
+
valid = (filter(@exceptions) == '' or accepted?(@exceptions))
|
34
|
+
save_html_and_exceptions
|
35
|
+
valid
|
36
|
+
end
|
37
|
+
|
38
|
+
# Saves the exception string for the given url or file path. When next run, if the exception
|
39
|
+
# string is identical, valid? will return true. Note that #exceptions will still list the
|
40
|
+
# exception string, though, even if it is an accepted exception string.
|
41
|
+
def accept!
|
42
|
+
File.open(data_path("accepted"), 'w') {|f| f.write(@exceptions) }
|
43
|
+
end
|
44
|
+
|
45
|
+
private
|
46
|
+
# We specifically prefer /usr/bin/tidy by default on *nix as there is another "tidy" programs
|
47
|
+
# that could end up earlier on the path. On snow leopard, tidy was installed at this location
|
48
|
+
# for me by default.
|
49
|
+
def tidy_command
|
50
|
+
is_windows = (RbConfig::CONFIG['host_os'] =~ /mswin|mingw|cygwin/)
|
51
|
+
bin = (is_windows or !File.exists?("/usr/bin/tidy")) ? 'tidy' : '/usr/bin/tidy'
|
52
|
+
"#{bin} #{@tidyopts}"
|
53
|
+
end
|
54
|
+
|
55
|
+
# get the filename for storing a type of data
|
56
|
+
def data_path(filetype)
|
57
|
+
"#{@datapath}.#{filetype}.txt"
|
58
|
+
end
|
59
|
+
|
60
|
+
def save_html_and_exceptions
|
61
|
+
File.open(data_path("html"), 'w') {|f| f.write(@html) }
|
62
|
+
File.open(data_path("resource"), 'w') {|f| f.write(@resource) }
|
63
|
+
File.open(data_path("exceptions"), 'w') {|f| f.write(@exceptions) }
|
64
|
+
end
|
65
|
+
|
66
|
+
# have we previously accepted this exact string for this path?
|
67
|
+
def accepted?(exception_str)
|
68
|
+
exception_str = filter(exception_str)
|
69
|
+
File.exists?(data_path('accepted')) ? filter(File.open(data_path('accepted'),"r").read) == exception_str : false
|
70
|
+
end
|
71
|
+
|
72
|
+
# Line numbers of exceptions are likely to change with any minor edit, so our validation
|
73
|
+
# compares the result strings with the lines and columns removed. This means that
|
74
|
+
# if the errors change position in the file (up or down b/c you add or remove code),
|
75
|
+
# accepted exception strings will remain valid.
|
76
|
+
def filter(str)
|
77
|
+
str.gsub!(/^line.*trimming empty.*\n/, '') # the messages about empty are overzealous, and not invalid
|
78
|
+
str.gsub!(/^line.*proprietary.*\n/, '') if @ignore_proprietary # if you use IE only attributes like wrap, or spellcheck or things not in standard
|
79
|
+
str.gsub(/line [0-9]+ column [0-9]+ -/, '')
|
80
|
+
# /line [0-9]+ column [0-9]+ - / + =~ "line 1 column 1 - Warning: missing <!DOCTYPE> declaration"
|
81
|
+
end
|
82
|
+
|
83
|
+
def validate
|
84
|
+
stdin, stdout, stderr = Open3.popen3(tidy_command)
|
85
|
+
stdin.puts @html
|
86
|
+
stdin.close
|
87
|
+
stdout.close
|
88
|
+
result = stderr.read
|
89
|
+
stderr.close
|
90
|
+
result
|
91
|
+
end
|
92
|
+
|
93
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
# == HTML Validation
|
2
|
+
# HTLM Acceptance helps you watch and come to terms with your HTML's validity, or lack thereof.
|
3
|
+
# The idea is to take an html markup string associated with a particular path (file or URL),
|
4
|
+
# and validate it. It is intended to be used in acceptance tests, test suites or a rake task
|
5
|
+
# to alert you to changes in your html's validity so you can fix them, or barring that, review and accept
|
6
|
+
# errors and warnings.
|
7
|
+
|
8
|
+
# ==Resource paths
|
9
|
+
# When calling the validation routine, a path, or URL is passed. This is used internally to name
|
10
|
+
# the resulting validation output files.
|
11
|
+
|
12
|
+
# NOTE: HTMLValidation never retreives html or reads in files *for* you. It doesn't read files, or call
|
13
|
+
# passed URL's. The purpose of passing a resource path is to give the test a name which saved exceptions
|
14
|
+
# can be stored against and compared to. In theory, the resource could be any distinct string, meaningful or not.
|
15
|
+
|
16
|
+
# If the resource (URL or file) has a saved exception string and it matches, the validation passes.
|
17
|
+
# The user can use a rake task can run this manually and upd ate the accepted exception string.
|
18
|
+
|
19
|
+
require 'rbconfig'
|
20
|
+
|
21
|
+
require File.expand_path(File.join(File.dirname(__FILE__), 'html_validation/html_validation_result'))
|
22
|
+
require File.expand_path(File.join(File.dirname(__FILE__), 'html_validation/html_validation_matcher'))
|
23
|
+
|
24
|
+
module PageValidations
|
25
|
+
|
26
|
+
class HTMLValidation
|
27
|
+
|
28
|
+
# The data_folder is where we store our output. options[:tidyopts], which defaults to "-qi"
|
29
|
+
# can be used to override the command line options to html tidy. On *nix, man tidy to see
|
30
|
+
# what else you might use for this string instead of "-qi", however "-qi" is probably what
|
31
|
+
# you want 95% of the time.
|
32
|
+
|
33
|
+
# You may also pass :ignore_proprietary => true as an option to suppress messages like:
|
34
|
+
# line 1 column 176 - Warning: <textarea> proprietary attribute "wrap"
|
35
|
+
# line 1 column 176 - Warning: <textarea> proprietary attribute "spellcheck"
|
36
|
+
|
37
|
+
# It may be useful to pass a subfolder in your project as the data_folder, so your
|
38
|
+
# HTML Validation status and validation results are stored along with your source.
|
39
|
+
def initialize(folder_for_data = nil, options = {})
|
40
|
+
self.data_folder = folder_for_data || default_result_file_path
|
41
|
+
@options = options
|
42
|
+
end
|
43
|
+
|
44
|
+
# For each stored exception, yield an HTMLValidationResult object to allow the user to
|
45
|
+
# call .accept! on the exception if it is OK.
|
46
|
+
def each_exception
|
47
|
+
Dir.chdir(@data_folder)
|
48
|
+
Dir.glob("*.exceptions.txt").each do |file|
|
49
|
+
if File.open(File.join(@data_folder, file), 'r').read != ''
|
50
|
+
yield HTMLValidationResult.load_from_files(file.gsub('.exceptions.txt',''))
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def validation(html, resource)
|
56
|
+
resource_data_path = File.join(@data_folder, filenameize(resource))
|
57
|
+
HTMLValidationResult.new(resource, html, resource_data_path, @options)
|
58
|
+
end
|
59
|
+
|
60
|
+
def data_folder=(path)
|
61
|
+
FileUtils.mkdir_p(path)
|
62
|
+
@data_folder = path
|
63
|
+
end
|
64
|
+
|
65
|
+
def default_result_file_path
|
66
|
+
posix = RbConfig::CONFIG['host_os'] =~ /(darwin|linux)/
|
67
|
+
rootpath = Rails.root if defined?(Rails)
|
68
|
+
rootpath ||= HTMLValidationMatcher.data_path if HTMLValidationMatcher.data_path
|
69
|
+
rootpath ||= posix ? '/tmp/' : "c:\\tmp\\"
|
70
|
+
File.join(rootpath, '.validation')
|
71
|
+
end
|
72
|
+
|
73
|
+
private
|
74
|
+
|
75
|
+
# Takes a url or filepath qne trims and sanitizes it for use as a filename.
|
76
|
+
def filenameize(path)
|
77
|
+
path.gsub!(/www.|^(http:\/\/|\/|C:\\)/, '')
|
78
|
+
path.gsub(/[^0-9A-Za-z.]/, '_')
|
79
|
+
end
|
80
|
+
|
81
|
+
end
|
82
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
#!/usr/bin/env thor
|
2
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', 'html_validation'))
|
3
|
+
|
4
|
+
class Validation < Thor
|
5
|
+
include PageValidations
|
6
|
+
desc "review", "Review and Accept (or fix and rerun) HTML Validation errors"
|
7
|
+
|
8
|
+
method_option :data_path, :aliases => "-d", :desc => "Optional custom data path (if not default of /spec/.validate)"
|
9
|
+
def review
|
10
|
+
data_path = options[:data_path] || File.join(Dir.getwd, 'spec', '.validation')
|
11
|
+
$stdout.puts "Reviewing validation results in: #{data_path}"
|
12
|
+
|
13
|
+
HTMLValidation.new(data_path).each_exception do |result|
|
14
|
+
$stdout.puts "Validation exceptions for: #{result.resource}:\n#{result.exceptions}"
|
15
|
+
$stdout.puts "Accept (y)es (n)o or (q)uit"
|
16
|
+
sin = $stdin.gets
|
17
|
+
if sin[0].downcase == 'y'
|
18
|
+
result.accept!
|
19
|
+
$stdout.puts "Accepted!"
|
20
|
+
else
|
21
|
+
$stdout.puts "Rejected!"
|
22
|
+
end
|
23
|
+
exit if sin.downcase == 'exit' or sin.downcase == 'quit' or sin.downcase == 'q'
|
24
|
+
end
|
25
|
+
$stdout.puts "HTML Validation Acceptance completed"
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
|
+
|
3
|
+
require 'html_validation/have_valid_html'
|
4
|
+
|
5
|
+
describe "HTMLValidationRSpecMatcher" do
|
6
|
+
|
7
|
+
before(:each) do
|
8
|
+
@page = double("page")
|
9
|
+
end
|
10
|
+
|
11
|
+
it "should check page object with the matcher for valid HTML and pass valid html" do
|
12
|
+
@page.stub :html => good_html
|
13
|
+
@page.stub :body => good_html
|
14
|
+
@page.stub :current_url => 'http://www.fake.com/good_page'
|
15
|
+
@page.should have_valid_html
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should check page object with the matcher for valid HTML and fail bad HTML" do
|
19
|
+
@page.stub :html => bad_html
|
20
|
+
@page.stub :body => bad_html
|
21
|
+
@page.stub :current_url => 'http://www.fake.com/bad_page'
|
22
|
+
@page.should_not have_valid_html
|
23
|
+
end
|
24
|
+
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def bad_html
|
29
|
+
'<html><title>the title<title></head><body><p>blah blah</body></html>'
|
30
|
+
end
|
31
|
+
|
32
|
+
def good_html
|
33
|
+
'<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html><title>the title</title></head><body><p>a paragraph</p></body></html>'
|
34
|
+
end
|
35
|
+
|
36
|
+
def tmp_path
|
37
|
+
is_windows = (RbConfig::CONFIG['host_os'] =~ /mswin|mingw|cygwin/)
|
38
|
+
is_windows ? 'c:\temp\validation' : '/tmp/validation'
|
39
|
+
end
|
40
|
+
|
41
|
+
# clean our temp dir without killing it
|
42
|
+
def clean_dir(dir)
|
43
|
+
Dir.chdir(dir)
|
44
|
+
Dir.glob('*').each {|f| FileUtils.rm f }
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
@@ -0,0 +1,133 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
|
+
|
3
|
+
|
4
|
+
describe "HTMLValidation" do
|
5
|
+
|
6
|
+
before(:each) do
|
7
|
+
FileUtils.mkdir tmp_path if !File.exists?('/tmp/validation')
|
8
|
+
@h = HTMLValidation.new('/tmp/validation')
|
9
|
+
end
|
10
|
+
|
11
|
+
it "should return false for invalid xml" do
|
12
|
+
result = @h.validation(bad_html, "http://myothersite.com").valid?.should be_false
|
13
|
+
end
|
14
|
+
|
15
|
+
it "should return true for valid html" do
|
16
|
+
result = @h.validation(good_html, "http://mysite.com").valid?.should be_true
|
17
|
+
end
|
18
|
+
|
19
|
+
it "should have an exception string for invalid xml" do
|
20
|
+
result = @h.validation(bad_html, "http://myfavoritesite.com")
|
21
|
+
(result.exceptions.empty?).should be_false
|
22
|
+
end
|
23
|
+
|
24
|
+
it "should return true for valid? if exceptions are accepted" do
|
25
|
+
result = @h.validation(bad_html, "http://mynewsite.com")
|
26
|
+
result.accept!
|
27
|
+
result = @h.validation(bad_html, "http://mynewsite.com").valid?.should be_true
|
28
|
+
end
|
29
|
+
|
30
|
+
it "should show no exceptions for a truly valid file" do
|
31
|
+
result = @h.validation(good_html, "http://mybestsite.com")
|
32
|
+
(result.exceptions == '').should be_true
|
33
|
+
end
|
34
|
+
|
35
|
+
it "should still show exceptions when returning valid for an accepted exception string" do
|
36
|
+
result = @h.validation(bad_html, "http://myworstsite.com")
|
37
|
+
result.accept!
|
38
|
+
result = @h.validation(bad_html, "http://myworstsite.com")
|
39
|
+
result.valid?.should be_true
|
40
|
+
(result.exceptions.length == 0).should be_false
|
41
|
+
end
|
42
|
+
|
43
|
+
it "should reset exceptions after each call to valid?" do
|
44
|
+
result = @h.validation(bad_html, "http://myuglysite.com")
|
45
|
+
result = @h.validation(good_html, "http://myuglysite.com")
|
46
|
+
(result.exceptions.length == 0).should be_true
|
47
|
+
result.valid?.should be_true
|
48
|
+
end
|
49
|
+
|
50
|
+
it "should reset accepted exceptions string after seeing valid html for a path" do
|
51
|
+
result = @h.validation(bad_html, "http://notmysite.com")
|
52
|
+
result.accept!
|
53
|
+
result = @h.validation(bad_html, "http://notmysite.com").valid?.should be_true
|
54
|
+
# now we see valid, so we should reset
|
55
|
+
result = @h.validation(good_html, "http://notmysite.com").valid?.should be_true
|
56
|
+
result = @h.validation(bad_html, "http://notmysite.com").valid?.should be_false
|
57
|
+
end
|
58
|
+
|
59
|
+
it "should not pass a different non-accepted exception" do
|
60
|
+
result = @h.validation(bad_html, "http://mycoolsite.com")
|
61
|
+
result.accept!
|
62
|
+
result = @h.validation("<html></body></html>", "http://mycoolsite.com").valid?.should be_false
|
63
|
+
end
|
64
|
+
|
65
|
+
it "should ignore proprietary tags when ignore_proprietary is passed" do
|
66
|
+
html_with_proprietary=good_html.gsub('<body>','<body><textarea wrap="true" spellcheck="true">hi</textarea>')
|
67
|
+
result = @h.validation(html_with_proprietary, "http://mycrosoft.com")
|
68
|
+
result.valid?.should be_false
|
69
|
+
@h = HTMLValidation.new('/tmp/validation', :ignore_proprietary=>true)
|
70
|
+
result = @h.validation(html_with_proprietary, "http://mycrosoft.com")
|
71
|
+
result.valid?.should be_true
|
72
|
+
end
|
73
|
+
|
74
|
+
it "should work without a data path being manually set" do
|
75
|
+
h = HTMLValidation.new()
|
76
|
+
result = h.validation(good_html, "http://mybestsite.com")
|
77
|
+
(result.exceptions == '').should be_true
|
78
|
+
end
|
79
|
+
|
80
|
+
|
81
|
+
describe "when launching HTML Tidy" do
|
82
|
+
|
83
|
+
it "should let me pass different Tidy command line options" do
|
84
|
+
@h = HTMLValidation.new('/tmp/validation', :tidy_opts=>"-e")
|
85
|
+
result = @h.validation("<html>foo", 'c:\mycoolapp\somesite.html')
|
86
|
+
result.exceptions.include?("were found!").should be_true
|
87
|
+
@h = HTMLValidation.new('/tmp/validation')
|
88
|
+
result = @h.validation("<html>foo", 'c:\mycoolapp\somesite.html')
|
89
|
+
result.exceptions.include?("were found!").should be_false
|
90
|
+
end
|
91
|
+
|
92
|
+
end
|
93
|
+
|
94
|
+
describe "when walking exception results" do
|
95
|
+
|
96
|
+
it "should yield loaded exception results" do
|
97
|
+
@h = HTMLValidation.new('/tmp/validation')
|
98
|
+
result = @h.validation("<html>foo", 'c:\evencooler.com\somesite.html')
|
99
|
+
had_exceptions = false
|
100
|
+
@h.each_exception do |e|
|
101
|
+
had_exceptions = true
|
102
|
+
e.is_a?(HTMLValidationResult).should be_true
|
103
|
+
(e.resource.length > 0).should be_true
|
104
|
+
(e.html.length > 0).should be_true
|
105
|
+
end
|
106
|
+
had_exceptions.should be_true
|
107
|
+
end
|
108
|
+
|
109
|
+
end
|
110
|
+
|
111
|
+
|
112
|
+
private
|
113
|
+
|
114
|
+
def bad_html
|
115
|
+
'<html><title>the title<title></head><body><p>blah blah</body></html>'
|
116
|
+
end
|
117
|
+
|
118
|
+
def good_html
|
119
|
+
'<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html><title>the title</title></head><body><p>a paragraph</p></body></html>'
|
120
|
+
end
|
121
|
+
|
122
|
+
def tmp_path
|
123
|
+
is_windows = (RbConfig::CONFIG['host_os'] =~ /mswin|mingw|cygwin/)
|
124
|
+
is_windows ? 'c:\temp\validation' : '/tmp/validation'
|
125
|
+
end
|
126
|
+
|
127
|
+
# clean our temp dir without killing it
|
128
|
+
def clean_dir(dir)
|
129
|
+
Dir.chdir(dir)
|
130
|
+
Dir.glob('*').each {|f| FileUtils.rm f }
|
131
|
+
end
|
132
|
+
|
133
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
2
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
3
|
+
require 'rspec'
|
4
|
+
require 'html_validation'
|
5
|
+
|
6
|
+
include PageValidations
|
7
|
+
|
8
|
+
# Requires supporting files with custom matchers and macros, etc,
|
9
|
+
# in ./support/ and its subdirectories.
|
10
|
+
Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
|
11
|
+
|
12
|
+
RSpec.configure do |config|
|
13
|
+
|
14
|
+
end
|
metadata
ADDED
@@ -0,0 +1,68 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: html_validation
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Eric Beland
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2013-03-16 00:00:00.000000000 Z
|
13
|
+
dependencies: []
|
14
|
+
description: HTML Validation lets you validate html locally. Lets you build html validation
|
15
|
+
into your test suite, but break the rules if you must.
|
16
|
+
email:
|
17
|
+
- ebeland@gmail.com
|
18
|
+
executables: []
|
19
|
+
extensions: []
|
20
|
+
extra_rdoc_files: []
|
21
|
+
files:
|
22
|
+
- .document
|
23
|
+
- .gitignore
|
24
|
+
- .rspec
|
25
|
+
- Gemfile
|
26
|
+
- Gemfile.lock
|
27
|
+
- LICENSE.txt
|
28
|
+
- README.rdoc
|
29
|
+
- Rakefile
|
30
|
+
- VERSION
|
31
|
+
- html_validation.gemspec
|
32
|
+
- lib/html_validation.rb
|
33
|
+
- lib/html_validation/have_valid_html.rb
|
34
|
+
- lib/html_validation/html_validation_matcher.rb
|
35
|
+
- lib/html_validation/html_validation_result.rb
|
36
|
+
- lib/html_validation/version.rb
|
37
|
+
- lib/tasks/validation.thor
|
38
|
+
- spec/html_validator_matcher_spec.rb
|
39
|
+
- spec/html_validator_spec.rb
|
40
|
+
- spec/spec_helper.rb
|
41
|
+
homepage: https://github.com/ericbeland/html_validation
|
42
|
+
licenses: []
|
43
|
+
post_install_message:
|
44
|
+
rdoc_options: []
|
45
|
+
require_paths:
|
46
|
+
- lib
|
47
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
48
|
+
none: false
|
49
|
+
requirements:
|
50
|
+
- - ! '>='
|
51
|
+
- !ruby/object:Gem::Version
|
52
|
+
version: '0'
|
53
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
54
|
+
none: false
|
55
|
+
requirements:
|
56
|
+
- - ! '>='
|
57
|
+
- !ruby/object:Gem::Version
|
58
|
+
version: '0'
|
59
|
+
requirements: []
|
60
|
+
rubyforge_project:
|
61
|
+
rubygems_version: 1.8.25
|
62
|
+
signing_key:
|
63
|
+
specification_version: 3
|
64
|
+
summary: Local HTML validation for tests and RSpec.
|
65
|
+
test_files:
|
66
|
+
- spec/html_validator_matcher_spec.rb
|
67
|
+
- spec/html_validator_spec.rb
|
68
|
+
- spec/spec_helper.rb
|