ada_matcher 0.1.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,4 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in ada_matcher.gemspec
4
+ gemspec
data/README.md ADDED
File without changes
data/Rakefile ADDED
@@ -0,0 +1,17 @@
1
+ require "bundler/gem_tasks"
2
+ require 'rspec/core/rake_task'
3
+
4
+ desc 'Default: run specs.'
5
+ task :default => :spec
6
+
7
+ desc "Run specs"
8
+ RSpec::Core::RakeTask.new do |t|
9
+ t.pattern = "./spec/**/*_spec.rb"
10
+ end
11
+
12
+ desc "Generate code coverage"
13
+ RSpec::Core::RakeTask.new(:coverage) do |t|
14
+ t.pattern = "./spec/**/*_spec.rb" # don't need this, it's default.
15
+ t.rcov = true
16
+ t.rcov_opts = ['--exclude', 'spec']
17
+ end
@@ -0,0 +1,27 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "ada_matcher/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "ada_matcher"
7
+ s.version = AdaMatcher::VERSION
8
+ s.authors = ["Aaron Brown"]
9
+ s.email = ["aaron@thebrownproject.com"]
10
+ s.homepage = ""
11
+ s.summary = %q{Adds custom rspec matchers that test watir Page objects for ADA compliance}
12
+ s.description = %q{Adds custom rspec matchers that test watir Page objects for ADA compliance}
13
+ s.license = 'MIT'
14
+
15
+ s.rubyforge_project = "ada_matcher"
16
+
17
+ s.files = `git ls-files`.split("\n")
18
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
19
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
20
+ s.require_paths = ["lib"]
21
+
22
+ # specify any dependencies here; for example:
23
+ s.add_development_dependency "rspec"
24
+ s.add_development_dependency "watir-webdriver", ">0"
25
+ s.add_development_dependency "headless"
26
+ # s.add_runtime_dependency "rspec"
27
+ end
@@ -0,0 +1,145 @@
1
+ require "ada_matcher/version"
2
+
3
+ module AdaMatcher
4
+
5
+ RSpec::Matchers.define :meet_ada_requirements do |reqs|
6
+ @errors = Array.new
7
+
8
+ match do |page|
9
+ browser = get_page_browser(page)
10
+ raise Exception.new("Can only test ADA on Watir::Browser and compatible objects (#{browser.class.name})") unless is_browser?(browser)
11
+
12
+ to_run = parse_args(reqs)
13
+ if (to_run.empty? || to_run.include?(:all))
14
+ @errors += image_alt(browser)
15
+ @errors += link_title(browser)
16
+ @errors += link_window_warning(browser)
17
+ @errors += htag_hierarchy(browser)
18
+ @errors += label_for(browser)
19
+ elsif to_run.include?(:image_alt)
20
+ @errors += image_alt(browser)
21
+ elsif to_run.include?(:link_title)
22
+ @errors += link_title(browser)
23
+ elsif to_run.include?(:link_window_warning)
24
+ @errors += link_window_warning(browser)
25
+ elsif to_run.include?(:htag_hierarchy)
26
+ @errors += htag_hierarchy(browser)
27
+ elsif to_run.include?(:label_for)
28
+ @errors += label_for(browser)
29
+ end
30
+
31
+ !(@errors.nil?) && (@errors.length == 0)
32
+ end
33
+
34
+ failure_message_for_should do |actual|
35
+ title = (actual.title || "Page")
36
+ "expected that page '#{title}' would meet ADA requirements, but errors were found:\n#{@errors.join("\n")}"
37
+ end
38
+
39
+ failure_message_for_should_not do |actual|
40
+ title = (actual.title || "Page")
41
+ "expected that page '#{title}' would not meet ADA requirements, but no errors were found.\n"
42
+ end
43
+
44
+ description do
45
+ "pass the following ADA requirements: #{to_run.inspect}"
46
+ end
47
+
48
+ def get_page_browser(page)
49
+ # "page" may be a browser object or, for example, a watir_page_helper object
50
+ # with a "browser" object embedded within it. Find the nested browser object
51
+ # and return it so we can continue in a consistent manner.
52
+ return page.browser if page.respond_to?(:browser)
53
+ return page.browser if page.instance_variable_defined?(:@browser)
54
+ return page.browser if page.instance_variable_defined?(:browser)
55
+ page
56
+ end
57
+
58
+ # We don't care what kind of web driver gave us "page" as long as it
59
+ # responds to all the API calls we need
60
+ def is_browser?(browser)
61
+ browser.respond_to?(:images) &&
62
+ browser.respond_to?(:links) &&
63
+ browser.respond_to?(:h1s) &&
64
+ browser.respond_to?(:h2s) &&
65
+ browser.respond_to?(:h3s) &&
66
+ browser.respond_to?(:h4s) &&
67
+ browser.respond_to?(:labels) &&
68
+ browser.respond_to?(:text_fields) &&
69
+ browser.respond_to?(:checkboxes) &&
70
+ browser.respond_to?(:file_fields) &&
71
+ browser.respond_to?(:radios) &&
72
+ browser.respond_to?(:select_lists)
73
+ end
74
+
75
+ def parse_args(args)
76
+ return [] if args.nil?
77
+ if args.respond_to? :to_a
78
+ args.to_a
79
+ else
80
+ [args]
81
+ end
82
+ end
83
+
84
+ def image_alt(page)
85
+ e = Array.new
86
+ page.images.each do |img|
87
+ e << "Image tag is missing 'alt' attribute: #{img.html}" if img.alt.empty?
88
+ end
89
+ e # return error message array
90
+ end
91
+
92
+ def link_title(page)
93
+ e = Array.new
94
+ page.links.each do |link|
95
+ e << "Link tag is missing 'title' attribute: #{link.html}" if link.title.empty?
96
+ end
97
+ e # return error message array
98
+ end
99
+
100
+ def link_window_warning(page)
101
+ e = Array.new
102
+ page.links.each do |link|
103
+ if !(link.target.empty?) && (link.title !~ /window/i)
104
+ e << "Link does not warn user about opening new window: #{link.html}"
105
+ end
106
+ end
107
+ e # return error message array
108
+ end
109
+
110
+ def htag_hierarchy(page)
111
+ e = Array.new
112
+ if page.h1s.to_a.empty? && !page.h2s.to_a.empty?
113
+ e << "H2 tag found but no H1 found on page"
114
+ end
115
+ if page.h2s.to_a.empty? && !page.h3s.to_a.empty?
116
+ e << "H3 tag found but no H2 found on page"
117
+ end
118
+ if page.h3s.to_a.empty? && !page.h4s.to_a.empty?
119
+ e << "H4 tag found but no H3 found on page"
120
+ end
121
+
122
+ e # return error message array
123
+ end
124
+
125
+ def label_for(page)
126
+ e = Array.new
127
+ fors = {}
128
+ page.labels.each do |label|
129
+ fors[label.for.to_s.to_sym] = 1 unless label.for.nil? || label.for.empty?
130
+ end
131
+
132
+ (page.text_fields.to_a + page.checkboxes.to_a + page.file_fields.to_a + page.radios.to_a + page.select_lists.to_a).each do |fld|
133
+ if fld.id.nil? || fld.id.to_s.empty?
134
+ e << "Form field without an ID or a corresponding Label: #{fld.html}"
135
+ else
136
+ e << "Form field without a corresponding Label: #{fld.html}" unless fors.has_key? fld.id.to_s.to_sym
137
+ end
138
+ end
139
+
140
+ e # return error message array
141
+ end
142
+
143
+ end
144
+
145
+ end
@@ -0,0 +1,3 @@
1
+ module AdaMatcher
2
+ VERSION = "0.1.0"
3
+ end
@@ -0,0 +1,49 @@
1
+ <html>
2
+ <head>
3
+ <title>Bad Page</title>
4
+ </head>
5
+
6
+ <body>
7
+
8
+ <h2>Section 1</h2>
9
+ <!-- img missing alt attribute -->
10
+ <a href="#" title="Stay here">
11
+ <img src="someimg.png"/>
12
+ </a>
13
+ <br/>
14
+
15
+ <h2>Section 2</h2>
16
+ <!-- link missing title attribute -->
17
+ <a href="#">
18
+ <img src="bad.png" alt="this is some alt text"/>
19
+ </a>
20
+ <br/>
21
+
22
+ <h4>H4 heading here</h4>
23
+ <!-- link opens in new window without warning -->
24
+ <a href="http://www.google.com/" title="another page" target="_blank">
25
+ Google
26
+ </a>
27
+ <br/>
28
+
29
+ <h2>Section 3</h2>
30
+ <form action="#">
31
+ <label for="someInput">textInput</label>
32
+ <input type="text" id="textInput" name="textInput"/> <br/>
33
+ <label for="checkboxInput">checkboxInput</label>
34
+ <input type="checkbox" id="checkboxInput" name="checkboxInput"/> <br/>
35
+ <label for="checkboxInput2">checkboxInput2</label>
36
+ <input type="checkbox" id="checkboxInput2" name="checkboxInput2"/> <br/>
37
+ <label for="doesNotMatch">selectInput</label>
38
+ <select id="selectInput" name="selectInput">
39
+ <option value="1">1</option>
40
+ <option value="2">2</option>
41
+ </select> <br/>
42
+ <label for="radioInput1">radioInput1</label>
43
+ <input type="radio" id="radioInput1" name="radioInput"/> <br/>
44
+ <label for="radioInput2">radioInput2</label>
45
+ <input type="radio" id="radioInput2" name="radioInput"/> <br/>
46
+ </form>
47
+
48
+ </body>
49
+ </html>
@@ -0,0 +1,41 @@
1
+ <html>
2
+ <head>
3
+ <title>Good Page</title>
4
+ </head>
5
+
6
+ <body>
7
+ <h1>Good Page</h1>
8
+
9
+ <h2>Section 1</h2>
10
+ <a href="#" title="Stay here">
11
+ <img src="someimg.png" alt="I am a test image"/>
12
+ </a>
13
+ <br/>
14
+
15
+ <h2>Section 2</h2>
16
+ <a href="http://www.google.com/" title="another page - opens in new window" target="_blank">
17
+ Google
18
+ </a>
19
+ <br/>
20
+
21
+ <h2>Section 3</h2>
22
+ <form action="#">
23
+ <label for="textInput">textInput</label>
24
+ <input type="text" id="textInput" name="textInput"/> <br/>
25
+ <label for="checkboxInput">checkboxInput</label>
26
+ <input type="checkbox" id="checkboxInput" name="checkboxInput"/> <br/>
27
+ <label for="checkboxInput2">checkboxInput2</label>
28
+ <input type="checkbox" id="checkboxInput2" name="checkboxInput2"/> <br/>
29
+ <label for="selectInput">selectInput</label>
30
+ <select id="selectInput" name="selectInput">
31
+ <option value="1">1</option>
32
+ <option value="2">2</option>
33
+ </select> <br/>
34
+ <label for="radioInput1">radioInput1</label>
35
+ <input type="radio" id="radioInput1" name="radioInput"/> <br/>
36
+ <label for="radioInput2">radioInput2</label>
37
+ <input type="radio" id="radioInput2" name="radioInput"/> <br/>
38
+ </form>
39
+
40
+ </body>
41
+ </html>
@@ -0,0 +1,57 @@
1
+ require 'rubygems'
2
+ require 'ada_matcher'
3
+ require 'watir-webdriver'
4
+ require 'headless'
5
+
6
+ describe "AdaMatcher" do
7
+ before(:all) do
8
+ @project_base_path = File.expand_path File.dirname(__FILE__) << "../"
9
+ @headless = Headless.new
10
+ @headless.start
11
+ @browser = Watir::Browser.new
12
+ end
13
+
14
+ after(:all) do
15
+ @browser.close
16
+ @headless.destroy
17
+ end
18
+
19
+ before(:each) do
20
+ end
21
+
22
+ after(:each) do
23
+ end
24
+
25
+ it "should pass ADA compliant page" do
26
+ @browser.goto "file://#{@project_base_path}/../resources/good_page.html"
27
+ @browser.should meet_ada_requirements
28
+ # can also say:
29
+ # @browser.should meet_ada_requirements(:all)
30
+ end
31
+
32
+ it "should fail with bad image tags" do
33
+ @browser.goto "file://#{@project_base_path}/../resources/bad_page.html"
34
+ @browser.should_not meet_ada_requirements(:image_alt)
35
+ end
36
+
37
+ it "should fail with bad link tags" do
38
+ @browser.goto "file://#{@project_base_path}/../resources/bad_page.html"
39
+ @browser.should_not meet_ada_requirements(:link_title)
40
+ end
41
+
42
+ it "should fail with new window links without warnings" do
43
+ @browser.goto "file://#{@project_base_path}/../resources/bad_page.html"
44
+ @browser.should_not meet_ada_requirements(:link_window_warning)
45
+ end
46
+
47
+ it "should fail if H2-H4 tags exist without lower-index H tags" do
48
+ @browser.goto "file://#{@project_base_path}/../resources/bad_page.html"
49
+ @browser.should_not meet_ada_requirements(:htag_hierarchy)
50
+ end
51
+
52
+ it "should fail if a Form field exists without a corresponding Label" do
53
+ @browser.goto "file://#{@project_base_path}/../resources/bad_page.html"
54
+ @browser.should_not meet_ada_requirements(:label_for)
55
+ end
56
+
57
+ end
metadata ADDED
@@ -0,0 +1,112 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ada_matcher
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 1
8
+ - 0
9
+ version: 0.1.0
10
+ platform: ruby
11
+ authors:
12
+ - Aaron Brown
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2012-02-26 00:00:00 -05:00
18
+ default_executable:
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: rspec
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
+ none: false
25
+ requirements:
26
+ - - ">="
27
+ - !ruby/object:Gem::Version
28
+ segments:
29
+ - 0
30
+ version: "0"
31
+ type: :development
32
+ version_requirements: *id001
33
+ - !ruby/object:Gem::Dependency
34
+ name: watir-webdriver
35
+ prerelease: false
36
+ requirement: &id002 !ruby/object:Gem::Requirement
37
+ none: false
38
+ requirements:
39
+ - - ">"
40
+ - !ruby/object:Gem::Version
41
+ segments:
42
+ - 0
43
+ version: "0"
44
+ type: :development
45
+ version_requirements: *id002
46
+ - !ruby/object:Gem::Dependency
47
+ name: headless
48
+ prerelease: false
49
+ requirement: &id003 !ruby/object:Gem::Requirement
50
+ none: false
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ segments:
55
+ - 0
56
+ version: "0"
57
+ type: :development
58
+ version_requirements: *id003
59
+ description: Adds custom rspec matchers that test watir Page objects for ADA compliance
60
+ email:
61
+ - aaron@thebrownproject.com
62
+ executables: []
63
+
64
+ extensions: []
65
+
66
+ extra_rdoc_files: []
67
+
68
+ files:
69
+ - .gitignore
70
+ - Gemfile
71
+ - README.md
72
+ - Rakefile
73
+ - ada_matcher.gemspec
74
+ - lib/ada_matcher.rb
75
+ - lib/ada_matcher/version.rb
76
+ - resources/bad_page.html
77
+ - resources/good_page.html
78
+ - spec/ada_matcher_spec.rb
79
+ has_rdoc: true
80
+ homepage: ""
81
+ licenses:
82
+ - MIT
83
+ post_install_message:
84
+ rdoc_options: []
85
+
86
+ require_paths:
87
+ - lib
88
+ required_ruby_version: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ">="
92
+ - !ruby/object:Gem::Version
93
+ segments:
94
+ - 0
95
+ version: "0"
96
+ required_rubygems_version: !ruby/object:Gem::Requirement
97
+ none: false
98
+ requirements:
99
+ - - ">="
100
+ - !ruby/object:Gem::Version
101
+ segments:
102
+ - 0
103
+ version: "0"
104
+ requirements: []
105
+
106
+ rubyforge_project: ada_matcher
107
+ rubygems_version: 1.3.7
108
+ signing_key:
109
+ specification_version: 3
110
+ summary: Adds custom rspec matchers that test watir Page objects for ADA compliance
111
+ test_files: []
112
+