acop 1.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.
data/.gitignore ADDED
@@ -0,0 +1 @@
1
+ acop-1.0.0.gem
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # gem's dependencies in the tagfu gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,19 @@
1
+ Copyright (C) 2013 by Avinash Padmanabhan
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ of this software and associated documentation files (the "Software"), to deal
5
+ in the Software without restriction, including without limitation the rights
6
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ copies of the Software, and to permit persons to whom the Software is
8
+ furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in
11
+ all copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,69 @@
1
+ acop - enforcing accessibility for web pages
2
+ ============================================
3
+
4
+ Acop
5
+ ----
6
+
7
+ [Acop](http://eveningsamurai.github.io/acop/)
8
+
9
+ Description
10
+ -----------
11
+
12
+ acop is a command line utility for verifying accessibility in web pages
13
+
14
+ With acop, you can specify a url you want to test for accessibility and acop would run through a checklist of accessibility concerns and return any issues found
15
+
16
+ Installation
17
+ ------------
18
+
19
+ `gem install acop`
20
+
21
+ Synopsis
22
+ --------
23
+
24
+ Access the command line help
25
+
26
+ `acop --help`
27
+
28
+ Specify the url you want accessibility tested
29
+
30
+ `acop -u http://www.google.com`
31
+
32
+ Checkpoints
33
+ -----------
34
+ ### Images
35
+ `<input type='image'...`
36
+ * Image inputs elements should have alt attributes
37
+ * Image inputs elements should not have alt attributes empty
38
+
39
+ `<img...`
40
+ * Image elements should have alt attributes
41
+ * Image elements should not have alt attributes empty
42
+
43
+ `<a><img...`
44
+ * Image elements inside anchor tags should have empty alt attributes
45
+
46
+ ### Title
47
+ `<title></title>`
48
+ * Page title element should not be empty
49
+
50
+ `<!DOCTYPE Resource SYSTEM 'foo.dtd'>`
51
+ * doctype should be specified if frame or iframe elements exist on the page
52
+
53
+ `<frameset><frame title=""...`
54
+ * Frame elements should have title attributes
55
+ * Frame elements should not have title attributes empty
56
+
57
+ `<iframe title=""...`
58
+ * iFrame elements should have title attributes
59
+ * iFrame elements should not have title attributes empty
60
+
61
+ Bugs
62
+ ----
63
+ Report bugs and requests at [the Github page](https://github.com/eveningsamurai/acop).
64
+
65
+
66
+ Copyright
67
+ ---------
68
+
69
+ Copyright 2013 by [Avinash Padmanabhan](http://eveningsamurai.wordpress.com) under the MIT license (see the LICENSE file).
data/acop.gemspec ADDED
@@ -0,0 +1,24 @@
1
+ require './lib/acop/version.rb'
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = 'acop'
5
+ s.version = Acop::VERSION
6
+ s.date = '2013-04-22'
7
+ s.summary = "Accessibility Cop"
8
+ s.description = "A gem to enforce accessibility testing of urls'"
9
+ s.authors = ["Avinash Padmanabhan"]
10
+ s.email = ['avinashpadmanabhan@gmail.com']
11
+ s.files = `git ls-files`.split("\n")
12
+ s.test_files = ['spec/acop_spec.rb']
13
+ s.homepage = "https://github.com/eveningsamurai/acop"
14
+
15
+ s.add_development_dependency "OptionParser"
16
+ s.add_development_dependency "rspec"
17
+ s.add_development_dependency "nokogiri"
18
+ s.add_development_dependency "webmock"
19
+ s.require_paths = ["lib"]
20
+
21
+ s.executables << 'acop'
22
+
23
+ s.post_install_message = "Thanks for installing Accessibility Cop(acop)!"
24
+ end
data/bin/acop ADDED
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'acop'
4
+
5
+ Acop.run(*ARGV)
data/lib/acop.rb ADDED
@@ -0,0 +1,41 @@
1
+ require 'optparse'
2
+ require 'open-uri'
3
+ require_relative 'acop/accessibility.rb'
4
+
5
+ module Acop
6
+ def self.run(*args)
7
+ options = {}
8
+
9
+ option_parser = OptionParser.new do |opts|
10
+ opts.banner = 'Usage: acop -u URL'
11
+
12
+ opts.on('-u', '--url URL', 'Url to be accessibility tested') do |tag|
13
+ options[:url] = tag
14
+ end
15
+ end
16
+
17
+ begin
18
+ option_parser.parse!
19
+ raise OptionParser::MissingArgument, "Url should be provided!" if options.keys.empty?
20
+ raise OptionParser::InvalidArgument, "Url cannot be resolved!" unless valid_url?(options[:url])
21
+ rescue OptionParser::ParseError => e
22
+ puts e.message
23
+ puts
24
+ puts option_parser
25
+ exit -1
26
+ end
27
+
28
+ Enforcer.new(options).accessibility_checks
29
+ end
30
+
31
+ def self.valid_url?(url)
32
+ begin
33
+ url = "http://" + url unless url.include?("http")
34
+ contents = open(url)
35
+ return true
36
+ rescue Exception => e
37
+ return false
38
+ end
39
+ end
40
+
41
+ end
@@ -0,0 +1,114 @@
1
+ require 'open-uri'
2
+ require 'nokogiri'
3
+ require 'rexml/document'
4
+
5
+ module Acop
6
+ class Enforcer
7
+ attr_reader :ah, :source, :contents
8
+
9
+ def initialize(options={})
10
+ @ah = Helpers.new
11
+ url = options[:url]
12
+ url = "http://" + options[:url] unless options[:url].include?("http")
13
+ @source = open(url)
14
+ @contents = Nokogiri::HTML(@source)
15
+ end
16
+
17
+ def accessibility_checks
18
+ error_messages = []
19
+
20
+ self.methods.each do |method|
21
+ error_messages << (self.public_send(method)) if method[0..5] == "check_"
22
+ end
23
+
24
+ puts error_messages
25
+ end
26
+
27
+ def check_image_input_alt(source=@contents)
28
+ input_elements = source.css('input')
29
+ image_inputs = input_elements.select {|image_input| image_input['type'] =~ /image/i}
30
+ error_messages = []
31
+ image_inputs.each do |input|
32
+ if (@ah.attribute_empty_or_nil(input, "alt") and input.parent.name != "a")
33
+ error_messages.push("Missing alt text/attribute for image button with id/name: " + (input['name'] || input['id'] || ""))
34
+ end
35
+ end
36
+ error_messages
37
+ end
38
+
39
+ def check_image_alt(source=@contents)
40
+ image_elements = source.css('img')
41
+ error_messages = []
42
+ image_elements.each do |element|
43
+ if (@ah.attribute_empty_or_nil(element, "alt") and element.parent.name != "a")
44
+ error_messages.push("Missing alt text/attribute for image with src: " + element['src'])
45
+ end
46
+ end
47
+ error_messages
48
+ end
49
+
50
+ def check_image_links(source=@contents)
51
+ link_elements = source.css('a img')
52
+ error_messages = []
53
+ image_links = []
54
+ link_elements.each do |link_element|
55
+ if(link_element['alt'] != "")
56
+ error_messages.push("Alt Text not empty or nil for image link with src: " + link_element['src'])
57
+ end
58
+ end
59
+ error_messages
60
+ end
61
+
62
+ def check_page_title(source=@contents)
63
+ title_element = source.css('title')
64
+ error_messages = []
65
+ error_messages.push("Missing title element") if title_element.empty?
66
+ error_messages.push("Empty title element") if(title_element.first and title_element.first.text == "")
67
+ error_messages.push("More than 1 title element") if title_element.length > 1
68
+
69
+ error_messages
70
+ end
71
+
72
+ def check_doctype(source=@contents)
73
+ frame_elements = source.css("frame")
74
+ iframe_elements = source.css("iframe")
75
+ error_messages = []
76
+ if(frame_elements.length > 0 or iframe_elements.length > 0)
77
+ doctype = REXML::Document.new(@source.string).doctype
78
+ error_messages.push("Frames/iFrames present but doctype is missing") unless doctype
79
+ end
80
+ error_messages
81
+ end
82
+
83
+ def check_frame_title(source=@contents)
84
+ return [] if source.css("frameset").length < 1
85
+ frame_elements = source.css("frame")
86
+ error_messages = []
87
+ frame_elements.each do |frame|
88
+ error_messages.push("Missing frame title element") unless frame['title']
89
+ error_messages.push("Empty frame title element") if frame['title'] == ""
90
+ end
91
+ error_messages
92
+ end
93
+
94
+ def check_iframe_title(source=@contents)
95
+ iframe_elements = source.css("iframe")
96
+ error_messages = []
97
+ iframe_elements.each do |iframe|
98
+ error_messages.push("Missing iframe title element") unless iframe['title']
99
+ error_messages.push("Empty iframe title element") if iframe['title'] == ""
100
+ end
101
+ error_messages
102
+ end
103
+ end
104
+
105
+ class Helpers
106
+ def attribute_empty_or_nil(element, attribute)
107
+ if(element[attribute] == nil || element[attribute] == "")
108
+ return true
109
+ end
110
+ false
111
+ end
112
+ end
113
+
114
+ end
@@ -0,0 +1,3 @@
1
+ module Acop
2
+ VERSION = "1.0.0"
3
+ end
data/spec/acop_spec.rb ADDED
@@ -0,0 +1,155 @@
1
+ require '../lib/acop/accessibility.rb'
2
+ require 'rspec/expectations'
3
+ require 'webmock/rspec'
4
+ require 'open-uri'
5
+
6
+ RSpec.configure do |config|
7
+ config.before(:all) do
8
+ end
9
+
10
+ config.after(:all) do
11
+ end
12
+
13
+ describe Acop::Enforcer do
14
+ it "should not return error messages when no issues with image tags" do
15
+ stub_request(:any, "www.example.com").to_return(:body => "<html><body><input type='image' alt='alt text'/></body></html>", :status => 200)
16
+ enf = Acop::Enforcer.new({:url => "www.example.com"})
17
+ error_messages = enf.check_image_input_alt
18
+ error_messages.should be_empty
19
+ end
20
+
21
+ it "should return error messages when alt tags absent from input image elements" do
22
+ stub_request(:any, "www.example.com").to_return(:body => "<html><body><input type='image'/></body></html>", :status => 200)
23
+ enf = Acop::Enforcer.new({:url => "www.example.com"})
24
+ error_messages = enf.check_image_input_alt
25
+ error_messages.should_not be_empty
26
+ error_messages[0].should match("Missing alt text/attribute for image button")
27
+ end
28
+
29
+ it "should return error messages when alt tags empty in input image elements" do
30
+ stub_request(:any, "www.example.com").to_return(:body => "<html><body><input type='image' alt=''/></body></html>", :status => 200)
31
+ enf = Acop::Enforcer.new({:url => "www.example.com"})
32
+ error_messages = enf.check_image_input_alt
33
+ error_messages.should_not be_empty
34
+ error_messages[0].should match("Missing alt text/attribute for image button")
35
+ end
36
+
37
+ it "should return error messages when alt tags absent from image elements" do
38
+ stub_request(:any, "www.example.com").to_return(:body => "<html><body><img src='www.intuit.com'></body></html>", :status => 200)
39
+ enf = Acop::Enforcer.new({:url => "www.example.com"})
40
+ error_messages = enf.check_image_alt
41
+ error_messages.should_not be_empty
42
+ error_messages[0].should match("Missing alt text/attribute for image with src")
43
+ end
44
+
45
+ it "should return error messages when alt tags empty in image elements" do
46
+ stub_request(:any, "www.example.com").to_return(:body => "<html><body><img alt='' src='www.intuit.com'></body></html>", :status => 200)
47
+ enf = Acop::Enforcer.new({:url => "www.example.com"})
48
+ error_messages = enf.check_image_alt
49
+ error_messages.should_not be_empty
50
+ error_messages[0].should match("Missing alt text/attribute for image with src")
51
+ end
52
+
53
+ it "should return error messages when alt tags absent from image links" do
54
+ stub_request(:any, "www.example.com").to_return(:body => "<html><body><img src='www.intuit.com'></body></html>", :status => 200)
55
+ enf = Acop::Enforcer.new({:url => "www.example.com"})
56
+ error_messages = enf.check_image_alt
57
+ error_messages.should_not be_empty
58
+ error_messages[0].should match("Missing alt text/attribute for image with src")
59
+ end
60
+
61
+ it "should have alt tags empty in image links" do
62
+ stub_request(:any, "www.example.com").to_return(:body => "<a class='visually-hidden'><img id='img_link' src='\/try_qbo_free.png' alt=''/>Try QuickBooks Online for Free</a>", :status => 200)
63
+ enf = Acop::Enforcer.new({:url => "www.example.com"})
64
+ error_messages = enf.check_image_links
65
+ error_messages.should be_empty
66
+ end
67
+
68
+ it "should return error messages when alt tags not empty in image links" do
69
+ stub_request(:any, "www.example.com").to_return(:body => "<a class='visually-hidden'><img id='img_link' src='\/try_qbo_free.png' alt='bla bla'/>Try QuickBooks Online for Free</a>", :status => 200)
70
+ enf = Acop::Enforcer.new({:url => "www.example.com"})
71
+ error_messages = enf.check_image_links
72
+ error_messages.should_not be_empty
73
+ error_messages[0].should match("Alt Text not empty or nil for image link with src")
74
+ end
75
+
76
+ it "should return error messages when alt tags nil in image links" do
77
+ stub_request(:any, "www.example.com").to_return(:body => "<a class='visually-hidden'><img id='img_link' src='\/try_qbo_free.png' alt='bla bla'/>Try QuickBooks Online for Free</a>", :status => 200)
78
+ enf = Acop::Enforcer.new({:url => "www.example.com"})
79
+ error_messages = enf.check_image_links
80
+ error_messages.should_not be_empty
81
+ error_messages[0].should match("Alt Text not empty or nil for image link with src")
82
+ end
83
+
84
+ it "should return error messages when title not present" do
85
+ stub_request(:any, "www.example.com").to_return(:body => "<html><head></head></html>", :status => 200)
86
+ enf = Acop::Enforcer.new({:url => "www.example.com"})
87
+ error_messages = enf.check_page_title
88
+ error_messages.should_not be_empty
89
+ error_messages[0].should match("Missing title element")
90
+ end
91
+
92
+ it "should return error messages when title element empty" do
93
+ stub_request(:any, "www.example.com").to_return(:body => "<html><head><title></title></head></html>", :status => 200)
94
+ enf = Acop::Enforcer.new({:url => "www.example.com"})
95
+ error_messages = enf.check_page_title
96
+ error_messages.should_not be_empty
97
+ error_messages[0].should match("Empty title element")
98
+ end
99
+
100
+ it "should return error messages when more than 1 title element" do
101
+ stub_request(:any, "www.example.com").to_return(:body => "<html><head><title>Some Title</title><title>Another title</title></head></html>", :status => 200)
102
+ enf = Acop::Enforcer.new({:url => "www.example.com"})
103
+ error_messages = enf.check_page_title
104
+ error_messages.should_not be_empty
105
+ error_messages[0].should match("More than 1 title element")
106
+ end
107
+
108
+ it "should return no error messages when frameset is not present" do
109
+ stub_request(:any, "www.example.com").to_return(:body => "<frame src='frame_a.htm' title=''><frame src='frame_b.htm' title='bla'>", :status => 200)
110
+ enf = Acop::Enforcer.new({:url => "www.example.com"})
111
+ error_messages = enf.check_frame_title
112
+ error_messages.should be_empty
113
+ end
114
+
115
+ it "should return error messages when frame/iframe present but no doctype" do
116
+ stub_request(:any, "www.example.com").to_return(:body => "<!DOCTYPE Resource SYSTEM 'foo.dtd'><frameset cols='50%,50%'><frame src='frame_a.htm'/><frame src='frame_b.htm'/></frameset>", :status => 200)
117
+ enf = Acop::Enforcer.new({:url => "www.example.com"})
118
+ error_messages = enf.check_doctype
119
+ puts error_messages
120
+ error_messages.should be_empty
121
+ end
122
+
123
+ it "should return error messages when frame does not have a title" do
124
+ stub_request(:any, "www.example.com").to_return(:body => "<frameset cols='50%,50%'><frame src='frame_a.htm'><frame src='frame_b.htm'></frameset>", :status => 200)
125
+ enf = Acop::Enforcer.new({:url => "www.example.com"})
126
+ error_messages = enf.check_frame_title
127
+ error_messages.should_not be_empty
128
+ error_messages[0].should match("Missing frame title element")
129
+ end
130
+
131
+ it "should return error messages when frame title is empty" do
132
+ stub_request(:any, "www.example.com").to_return(:body => "<frameset cols='50%,50%'><frame src='frame_a.htm' title=''><frame src='frame_b.htm' title='bla'></frameset>", :status => 200)
133
+ enf = Acop::Enforcer.new({:url => "www.example.com"})
134
+ error_messages = enf.check_frame_title
135
+ error_messages.should_not be_empty
136
+ error_messages[0].should match("Empty frame title element")
137
+ end
138
+
139
+ it "should return error messages when iframe does not have a title" do
140
+ stub_request(:any, "www.example.com").to_return(:body => "<iframe src='www.google.com'></iframe>", :status => 200)
141
+ enf = Acop::Enforcer.new({:url => "www.example.com"})
142
+ error_messages = enf.check_iframe_title
143
+ error_messages.should_not be_empty
144
+ error_messages[0].should match("Missing iframe title element")
145
+ end
146
+
147
+ it "should return error messages when iframe title is empty" do
148
+ stub_request(:any, "www.example.com").to_return(:body => "<iframe title='' src='www.google.com'></iframe>", :status => 200)
149
+ enf = Acop::Enforcer.new({:url => "www.example.com"})
150
+ error_messages = enf.check_iframe_title
151
+ error_messages.should_not be_empty
152
+ error_messages[0].should match("Empty iframe title element")
153
+ end
154
+ end
155
+ end
metadata ADDED
@@ -0,0 +1,121 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: acop
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Avinash Padmanabhan
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-04-22 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: OptionParser
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: rspec
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :development
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ - !ruby/object:Gem::Dependency
47
+ name: nokogiri
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ - !ruby/object:Gem::Dependency
63
+ name: webmock
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ! '>='
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ type: :development
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ! '>='
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
78
+ description: A gem to enforce accessibility testing of urls'
79
+ email:
80
+ - avinashpadmanabhan@gmail.com
81
+ executables:
82
+ - acop
83
+ extensions: []
84
+ extra_rdoc_files: []
85
+ files:
86
+ - .gitignore
87
+ - Gemfile
88
+ - LICENSE
89
+ - README.md
90
+ - acop.gemspec
91
+ - bin/acop
92
+ - lib/acop.rb
93
+ - lib/acop/accessibility.rb
94
+ - lib/acop/version.rb
95
+ - spec/acop_spec.rb
96
+ homepage: https://github.com/eveningsamurai/acop
97
+ licenses: []
98
+ post_install_message: Thanks for installing Accessibility Cop(acop)!
99
+ rdoc_options: []
100
+ require_paths:
101
+ - lib
102
+ required_ruby_version: !ruby/object:Gem::Requirement
103
+ none: false
104
+ requirements:
105
+ - - ! '>='
106
+ - !ruby/object:Gem::Version
107
+ version: '0'
108
+ required_rubygems_version: !ruby/object:Gem::Requirement
109
+ none: false
110
+ requirements:
111
+ - - ! '>='
112
+ - !ruby/object:Gem::Version
113
+ version: '0'
114
+ requirements: []
115
+ rubyforge_project:
116
+ rubygems_version: 1.8.25
117
+ signing_key:
118
+ specification_version: 3
119
+ summary: Accessibility Cop
120
+ test_files:
121
+ - spec/acop_spec.rb