html_validation 0.0.1
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.
- 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
|