ada_matcher 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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
+