capybara-accessible 0.0.2 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 9916aa4b7def229c4a35a26aad3b02560b91440e
4
- data.tar.gz: f03f28c2fc5027ee3fd591903085194bf9c8b6bd
3
+ metadata.gz: ac095c1cbae4d4f383b2d82ff785b7c42297f467
4
+ data.tar.gz: 545f83a936a547ed9231b77513f4b48bdc9d0ec0
5
5
  SHA512:
6
- metadata.gz: 2883f351111bbc0c701fcb395d98a5e87cd7c8e355b013654fb52045ead485fa2cbcf40065cfbc342b0d39200709ef5cc5d3f46581504abd4424ef973e147d04
7
- data.tar.gz: 84b9457fe048585e24e1837efe5bd140a03f3d9ec8bbdc32d28e09cce4714f24929be8537d14a7b4e8d0f1f147fdee4d276b7d09e22256503e9932dfb986cf8e
6
+ metadata.gz: 7cbd721bdd6d6db70718053a2b9a1e2ec37982db2d06df2620b50ee23072a5f51aba46adf5cf3b9efccb225a69be8940e0fac54cfee6f67c3ecbd9f63ab67f67
7
+ data.tar.gz: 73b0d915dbde5ce90f0d0b617e412f4b41666249dfba82dbf5b539d37c08129028bb25e3efc18877b0d54aeabcf5d2aac3ad6ee019752ad7204f9b498a94ff26
data/.gitignore CHANGED
@@ -3,7 +3,6 @@
3
3
  .bundle
4
4
  .config
5
5
  .yardoc
6
- Gemfile.lock
7
6
  InstalledFiles
8
7
  _yardoc
9
8
  coverage
@@ -0,0 +1,69 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ capybara-accessible (0.0.1)
5
+ capybara (~> 2.0, >= 2.0.2)
6
+ selenium-webdriver
7
+
8
+ GEM
9
+ remote: https://rubygems.org/
10
+ specs:
11
+ capybara (2.1.0)
12
+ mime-types (>= 1.16)
13
+ nokogiri (>= 1.3.3)
14
+ rack (>= 1.0.0)
15
+ rack-test (>= 0.5.4)
16
+ xpath (~> 2.0)
17
+ childprocess (0.3.9)
18
+ ffi (~> 1.0, >= 1.0.11)
19
+ coderay (1.0.9)
20
+ diff-lcs (1.2.4)
21
+ ffi (1.8.1)
22
+ method_source (0.8.1)
23
+ mime-types (1.23)
24
+ multi_json (1.7.7)
25
+ nokogiri (1.5.9)
26
+ pry (0.9.12.2)
27
+ coderay (~> 1.0.5)
28
+ method_source (~> 0.8)
29
+ slop (~> 3.4)
30
+ rack (1.4.5)
31
+ rack-protection (1.4.0)
32
+ rack
33
+ rack-test (0.6.2)
34
+ rack (>= 1.0)
35
+ rake (10.0.4)
36
+ rspec (2.13.0)
37
+ rspec-core (~> 2.13.0)
38
+ rspec-expectations (~> 2.13.0)
39
+ rspec-mocks (~> 2.13.0)
40
+ rspec-core (2.13.1)
41
+ rspec-expectations (2.13.0)
42
+ diff-lcs (>= 1.1.3, < 2.0)
43
+ rspec-mocks (2.13.1)
44
+ rubyzip (0.9.9)
45
+ selenium-webdriver (2.32.1)
46
+ childprocess (>= 0.2.5)
47
+ multi_json (~> 1.0)
48
+ rubyzip
49
+ websocket (~> 1.0.4)
50
+ sinatra (1.3.6)
51
+ rack (~> 1.4)
52
+ rack-protection (~> 1.3)
53
+ tilt (~> 1.3, >= 1.3.3)
54
+ slop (3.4.5)
55
+ tilt (1.4.1)
56
+ websocket (1.0.7)
57
+ xpath (2.0.0)
58
+ nokogiri (~> 1.3)
59
+
60
+ PLATFORMS
61
+ ruby
62
+
63
+ DEPENDENCIES
64
+ bundler (~> 1.3)
65
+ capybara-accessible!
66
+ pry
67
+ rake
68
+ rspec
69
+ sinatra
data/README.md CHANGED
@@ -1,16 +1,39 @@
1
1
  # Capybara::Accessible
2
2
 
3
- Defines a web driver and extends Capybara to assert accessibility on page visits in [RSpec feature specs](https://www.relishapp.com/rspec/rspec-rails/docs/feature-specs/feature-spec).
3
+ [![](https://api.tddium.com/pivotal-casebook/capybara-accessible/badges/25347.png?badge_token=1e276156136851abb3ca113d37e1cddca332e098)](https://api.tddium.com/pivotal-casebook/capybara-accessible/suites/25347)
4
4
 
5
- capybara-accessible uses [Google's Accessibility Developer Tools](https://code.google.com/p/accessibility-developer-tools/) assertions to performs automated accessibility audits.
5
+ Automated accessibility testing for Rails integration tests (Rspec + Capybara)
6
+ capybara-accessible automatically runs [Google's Accessibility Developer Tools](https://code.google.com/p/accessibility-developer-tools/) audits within your Ruby on Rails project integration test suite, using [RSpec feature specs](https://www.relishapp.com/rspec/rspec-rails/docs/feature-specs/feature-spec).
6
7
 
7
- Use capybara-accessible in place of the Selenium or capybara-webkit drivers to invoke these assertions on link clicks and page visits.
8
+ Some of the checks that are included:
9
+ * minimum color contrast
10
+ * label associations with inputs
11
+ * presence of alt attributes
12
+ * valid use of ARIA roles
13
+
14
+ The full list of accessibility audit rules is on the [Google Accessibility Developer Tools wiki](https://code.google.com/p/accessibility-developer-tools/wiki/AuditRules).
15
+
16
+ capybara-accessible extends Capybara and defines a custom webdriver that runs javascript assertions on every page visit and link/button click.
17
+ This way you do not need to make explicit assertions on accessibility. Instead, the test will simply fail with a message indicating the accessibility errors, like so:
18
+
19
+ Failure/Error: visit '/inaccessible'
20
+ Capybara::Accessible::InaccessibleError:
21
+ *** Begin accessibility audit results ***
22
+ An accessibility audit found
23
+ Errors:
24
+ Error: AX_ARIA_01 (Elements with ARIA roles must use a valid, non-abstract ARIA role) failed on the following element:
25
+ body > .outer > .standup > .block.buttons
26
+ See https://code.google.com/p/accessibility-developer-tools/wiki/AuditRules#AX_ARIA_01:_Elements_with_ARIA_roles_must_use_a_valid,_non-abstr for more information.
27
+
28
+
29
+ *** End accessibility audit results ***
30
+
31
+ Need help? Ask on the mailing list (please do not open an issue on GitHub): https://groups.google.com/forum/#!forum/capybara-accessible
8
32
 
9
33
  ## Installation
10
34
 
11
35
  Add this line to your application's Gemfile:
12
36
 
13
- gem 'selenium-webdriver'
14
37
  gem 'capybara-accessible'
15
38
 
16
39
  And then execute:
@@ -23,18 +46,20 @@ Or install it yourself as:
23
46
 
24
47
  ## Usage
25
48
 
26
- Require and register the driver in spec_helper.rb:
49
+ You can use capybara-accessible as a drop-in replacement for Rack::Test, Selenium or capybara-webkit drivers for Capybara. Simply set the driver in spec_helper.rb:
27
50
 
28
51
  require 'capybara/rspec'
29
52
  require 'capybara/accessible'
30
53
 
31
54
  Capybara.current_driver = :accessible
32
55
 
33
- Optionally exclude rules from being run:
56
+ You can also optionally exclude individual accessibility assertions from being run:
57
+
58
+ Capybara::Accessible::Auditor.exclusions = ['AX_FOCUS_01', 'AX_TEXT_01']
34
59
 
35
- Capybara::Accessible::Auditor.exclusions = ['AX_FOCUS_01']
60
+ You can use exclusions to supress failures for accessibility errors that you cannot immediately address, without turning off all assertions.
36
61
 
37
- The full list of rules is on the [Google Accessibility Developer Tools wiki](https://code.google.com/p/accessibility-developer-tools/wiki/AuditRules).
62
+ See the [Google Accessibility Developer Tools wiki](https://code.google.com/p/accessibility-developer-tools/wiki/AuditRules) for the complete list of codes.
38
63
 
39
64
  ## Contributing
40
65
 
@@ -14,23 +14,47 @@ module Capybara::Accessible
14
14
  File.read(File.expand_path("../axs_testing.js", __FILE__))
15
15
  end
16
16
 
17
- def audit_results
18
- excluded_assertions = Capybara::Accessible::Auditor.exclusions
17
+ def audit_failures
18
+ script =<<-JAVASCRIPT
19
+ var config = new axs.AuditConfiguration();
20
+ config.auditRulesToIgnore = #{excluded_rules.to_json};
21
+ results = axs.Audit.run(config);
22
+ return axs.Audit.auditResults(results).getErrors();
23
+ JAVASCRIPT
19
24
 
20
- results.reject do |r|
21
- excluded_assertions.include?(r['rule']['code'])
22
- end
25
+ run_script("#{audit_rules} #{script}")
23
26
  end
24
27
 
25
28
  def failure_messages
26
- audit_results.collect do |f|
27
- "<#{f['elements'].first.tag_name}> tag with text \"#{f['elements'].first.text}\" - #{f['rule']['heading']}" if f['result'] == 'FAIL'
28
- end.join("\n")
29
+ run_script("#{audit_rules} var results = axs.Audit.run(); return axs.Audit.createReport(results)")
29
30
  end
30
31
 
31
- def results
32
- script = "#{audit_rules} return axs.Audit.run();"
32
+ private
33
+
34
+ def excluded_rules
35
+ codes = Capybara::Accessible::Auditor.exclusions
36
+ mapping = {
37
+ 'AX_ARIA_01' => 'badAriaRole',
38
+ 'AX_ARIA_02' => 'nonExistentAriaLabelledbyElement',
39
+ 'AX_ARIA_03' => 'requiredAriaAttributeMissing',
40
+ 'AX_ARIA_04' => 'badAriaAttributeValue',
41
+ 'AX_TEXT_01' => 'controlsWithoutLabel',
42
+ 'AX_TEXT_02' => 'imagesWithoutAltText',
43
+ 'AX_TITLE_01' => 'pageWithoutTitle',
44
+ 'AX_IMAGE_01' => 'elementsWithMeaningfulBackgroundImage',
45
+ 'AX_FOCUS_01' => 'focusableElementNotVisibleAndNotAriaHidden',
46
+ 'AX_FOCUS_02' => 'unfocusableElementsWithOnClick',
47
+ 'AX_COLOR_01' => 'lowContrastElements',
48
+ 'AX_VIDEO_01' => 'videoWithoutCaptions',
49
+ 'AX_AUDIO_01' => 'audioWithoutControls'
50
+ # 'AX_TITLE_01' => 'linkWithUnclearPurpose', # This has a duplicate name
51
+ # 'AX_ARIA_05' => '', # This has no rule associated with it
52
+ }
53
+
54
+ names = codes.map { |code| mapping[code]}
55
+ end
33
56
 
57
+ def run_script(script)
34
58
  if @session
35
59
  @session.driver.execute_script(script)
36
60
  else
@@ -1,3 +1,391 @@
1
+ var COMPILED = !0, goog = goog || {};
2
+ goog.global = this;
3
+ goog.exportPath_ = function(a, b, c) {
4
+ a = a.split(".");
5
+ c = c || goog.global;
6
+ a[0] in c || !c.execScript || c.execScript("var " + a[0]);
7
+ for(var d;a.length && (d = a.shift());) {
8
+ a.length || void 0 === b ? c = c[d] ? c[d] : c[d] = {} : c[d] = b
9
+ }
10
+ };
11
+ goog.define = function(a, b) {
12
+ var c = b;
13
+ COMPILED || goog.global.CLOSURE_DEFINES && Object.prototype.hasOwnProperty.call(goog.global.CLOSURE_DEFINES, a) && (c = goog.global.CLOSURE_DEFINES[a]);
14
+ goog.exportPath_(a, c)
15
+ };
16
+ goog.DEBUG = !0;
17
+ goog.LOCALE = "en";
18
+ goog.TRUSTED_SITE = !0;
19
+ goog.provide = function(a) {
20
+ if(!COMPILED) {
21
+ if(goog.isProvided_(a)) {
22
+ throw Error('Namespace "' + a + '" already declared.');
23
+ }
24
+ delete goog.implicitNamespaces_[a];
25
+ for(var b = a;(b = b.substring(0, b.lastIndexOf("."))) && !goog.getObjectByName(b);) {
26
+ goog.implicitNamespaces_[b] = !0
27
+ }
28
+ }
29
+ goog.exportPath_(a)
30
+ };
31
+ goog.setTestOnly = function(a) {
32
+ if(COMPILED && !goog.DEBUG) {
33
+ throw a = a || "", Error("Importing test-only code into non-debug environment" + a ? ": " + a : ".");
34
+ }
35
+ };
36
+ COMPILED || (goog.isProvided_ = function(a) {
37
+ return!goog.implicitNamespaces_[a] && !!goog.getObjectByName(a)
38
+ }, goog.implicitNamespaces_ = {});
39
+ goog.getObjectByName = function(a, b) {
40
+ for(var c = a.split("."), d = b || goog.global, e;e = c.shift();) {
41
+ if(goog.isDefAndNotNull(d[e])) {
42
+ d = d[e]
43
+ }else {
44
+ return null
45
+ }
46
+ }
47
+ return d
48
+ };
49
+ goog.globalize = function(a, b) {
50
+ var c = b || goog.global, d;
51
+ for(d in a) {
52
+ c[d] = a[d]
53
+ }
54
+ };
55
+ goog.addDependency = function(a, b, c) {
56
+ if(goog.DEPENDENCIES_ENABLED) {
57
+ var d;
58
+ a = a.replace(/\\/g, "/");
59
+ for(var e = goog.dependencies_, f = 0;d = b[f];f++) {
60
+ e.nameToPath[d] = a, a in e.pathToNames || (e.pathToNames[a] = {}), e.pathToNames[a][d] = !0
61
+ }
62
+ for(d = 0;b = c[d];d++) {
63
+ a in e.requires || (e.requires[a] = {}), e.requires[a][b] = !0
64
+ }
65
+ }
66
+ };
67
+ goog.ENABLE_DEBUG_LOADER = !0;
68
+ goog.require = function(a) {
69
+ if(!COMPILED && !goog.isProvided_(a)) {
70
+ if(goog.ENABLE_DEBUG_LOADER) {
71
+ var b = goog.getPathFromDeps_(a);
72
+ if(b) {
73
+ goog.included_[b] = !0;
74
+ goog.writeScripts_();
75
+ return
76
+ }
77
+ }
78
+ a = "goog.require could not find: " + a;
79
+ goog.global.console && goog.global.console.error(a);
80
+ throw Error(a);
81
+ }
82
+ };
83
+ goog.basePath = "";
84
+ goog.nullFunction = function() {
85
+ };
86
+ goog.identityFunction = function(a, b) {
87
+ return a
88
+ };
89
+ goog.abstractMethod = function() {
90
+ throw Error("unimplemented abstract method");
91
+ };
92
+ goog.addSingletonGetter = function(a) {
93
+ a.getInstance = function() {
94
+ if(a.instance_) {
95
+ return a.instance_
96
+ }
97
+ goog.DEBUG && (goog.instantiatedSingletons_[goog.instantiatedSingletons_.length] = a);
98
+ return a.instance_ = new a
99
+ }
100
+ };
101
+ goog.instantiatedSingletons_ = [];
102
+ goog.DEPENDENCIES_ENABLED = !COMPILED && goog.ENABLE_DEBUG_LOADER;
103
+ goog.DEPENDENCIES_ENABLED && (goog.included_ = {}, goog.dependencies_ = {pathToNames:{}, nameToPath:{}, requires:{}, visited:{}, written:{}}, goog.inHtmlDocument_ = function() {
104
+ var a = goog.global.document;
105
+ return"undefined" != typeof a && "write" in a
106
+ }, goog.findBasePath_ = function() {
107
+ if(goog.global.CLOSURE_BASE_PATH) {
108
+ goog.basePath = goog.global.CLOSURE_BASE_PATH
109
+ }else {
110
+ if(goog.inHtmlDocument_()) {
111
+ for(var a = goog.global.document.getElementsByTagName("script"), b = a.length - 1;0 <= b;--b) {
112
+ var c = a[b].src, d = c.lastIndexOf("?"), d = -1 == d ? c.length : d;
113
+ if("base.js" == c.substr(d - 7, 7)) {
114
+ goog.basePath = c.substr(0, d - 7);
115
+ break
116
+ }
117
+ }
118
+ }
119
+ }
120
+ }, goog.importScript_ = function(a) {
121
+ var b = goog.global.CLOSURE_IMPORT_SCRIPT || goog.writeScriptTag_;
122
+ !goog.dependencies_.written[a] && b(a) && (goog.dependencies_.written[a] = !0)
123
+ }, goog.writeScriptTag_ = function(a) {
124
+ if(goog.inHtmlDocument_()) {
125
+ var b = goog.global.document;
126
+ if("complete" == b.readyState) {
127
+ if(/\bdeps.js$/.test(a)) {
128
+ return!1
129
+ }
130
+ throw Error('Cannot write "' + a + '" after document load');
131
+ }
132
+ b.write('<script type="text/javascript" src="' + a + '">\x3c/script>');
133
+ return!0
134
+ }
135
+ return!1
136
+ }, goog.writeScripts_ = function() {
137
+ function a(e) {
138
+ if(!(e in d.written)) {
139
+ if(!(e in d.visited) && (d.visited[e] = !0, e in d.requires)) {
140
+ for(var g in d.requires[e]) {
141
+ if(!goog.isProvided_(g)) {
142
+ if(g in d.nameToPath) {
143
+ a(d.nameToPath[g])
144
+ }else {
145
+ throw Error("Undefined nameToPath for " + g);
146
+ }
147
+ }
148
+ }
149
+ }
150
+ e in c || (c[e] = !0, b.push(e))
151
+ }
152
+ }
153
+ var b = [], c = {}, d = goog.dependencies_, e;
154
+ for(e in goog.included_) {
155
+ d.written[e] || a(e)
156
+ }
157
+ for(e = 0;e < b.length;e++) {
158
+ if(b[e]) {
159
+ goog.importScript_(goog.basePath + b[e])
160
+ }else {
161
+ throw Error("Undefined script input");
162
+ }
163
+ }
164
+ }, goog.getPathFromDeps_ = function(a) {
165
+ return a in goog.dependencies_.nameToPath ? goog.dependencies_.nameToPath[a] : null
166
+ }, goog.findBasePath_(), goog.global.CLOSURE_NO_DEPS || goog.importScript_(goog.basePath + "deps.js"));
167
+ goog.typeOf = function(a) {
168
+ var b = typeof a;
169
+ if("object" == b) {
170
+ if(a) {
171
+ if(a instanceof Array) {
172
+ return"array"
173
+ }
174
+ if(a instanceof Object) {
175
+ return b
176
+ }
177
+ var c = Object.prototype.toString.call(a);
178
+ if("[object Window]" == c) {
179
+ return"object"
180
+ }
181
+ if("[object Array]" == c || "number" == typeof a.length && "undefined" != typeof a.splice && "undefined" != typeof a.propertyIsEnumerable && !a.propertyIsEnumerable("splice")) {
182
+ return"array"
183
+ }
184
+ if("[object Function]" == c || "undefined" != typeof a.call && "undefined" != typeof a.propertyIsEnumerable && !a.propertyIsEnumerable("call")) {
185
+ return"function"
186
+ }
187
+ }else {
188
+ return"null"
189
+ }
190
+ }else {
191
+ if("function" == b && "undefined" == typeof a.call) {
192
+ return"object"
193
+ }
194
+ }
195
+ return b
196
+ };
197
+ goog.isDef = function(a) {
198
+ return void 0 !== a
199
+ };
200
+ goog.isNull = function(a) {
201
+ return null === a
202
+ };
203
+ goog.isDefAndNotNull = function(a) {
204
+ return null != a
205
+ };
206
+ goog.isArray = function(a) {
207
+ return"array" == goog.typeOf(a)
208
+ };
209
+ goog.isArrayLike = function(a) {
210
+ var b = goog.typeOf(a);
211
+ return"array" == b || "object" == b && "number" == typeof a.length
212
+ };
213
+ goog.isDateLike = function(a) {
214
+ return goog.isObject(a) && "function" == typeof a.getFullYear
215
+ };
216
+ goog.isString = function(a) {
217
+ return"string" == typeof a
218
+ };
219
+ goog.isBoolean = function(a) {
220
+ return"boolean" == typeof a
221
+ };
222
+ goog.isNumber = function(a) {
223
+ return"number" == typeof a
224
+ };
225
+ goog.isFunction = function(a) {
226
+ return"function" == goog.typeOf(a)
227
+ };
228
+ goog.isObject = function(a) {
229
+ var b = typeof a;
230
+ return"object" == b && null != a || "function" == b
231
+ };
232
+ goog.getUid = function(a) {
233
+ return a[goog.UID_PROPERTY_] || (a[goog.UID_PROPERTY_] = ++goog.uidCounter_)
234
+ };
235
+ goog.removeUid = function(a) {
236
+ "removeAttribute" in a && a.removeAttribute(goog.UID_PROPERTY_);
237
+ try {
238
+ delete a[goog.UID_PROPERTY_]
239
+ }catch(b) {
240
+ }
241
+ };
242
+ goog.UID_PROPERTY_ = "closure_uid_" + (1E9 * Math.random() >>> 0);
243
+ goog.uidCounter_ = 0;
244
+ goog.getHashCode = goog.getUid;
245
+ goog.removeHashCode = goog.removeUid;
246
+ goog.cloneObject = function(a) {
247
+ var b = goog.typeOf(a);
248
+ if("object" == b || "array" == b) {
249
+ if(a.clone) {
250
+ return a.clone()
251
+ }
252
+ var b = "array" == b ? [] : {}, c;
253
+ for(c in a) {
254
+ b[c] = goog.cloneObject(a[c])
255
+ }
256
+ return b
257
+ }
258
+ return a
259
+ };
260
+ goog.bindNative_ = function(a, b, c) {
261
+ return a.call.apply(a.bind, arguments)
262
+ };
263
+ goog.bindJs_ = function(a, b, c) {
264
+ if(!a) {
265
+ throw Error();
266
+ }
267
+ if(2 < arguments.length) {
268
+ var d = Array.prototype.slice.call(arguments, 2);
269
+ return function() {
270
+ var c = Array.prototype.slice.call(arguments);
271
+ Array.prototype.unshift.apply(c, d);
272
+ return a.apply(b, c)
273
+ }
274
+ }
275
+ return function() {
276
+ return a.apply(b, arguments)
277
+ }
278
+ };
279
+ goog.bind = function(a, b, c) {
280
+ Function.prototype.bind && -1 != Function.prototype.bind.toString().indexOf("native code") ? goog.bind = goog.bindNative_ : goog.bind = goog.bindJs_;
281
+ return goog.bind.apply(null, arguments)
282
+ };
283
+ goog.partial = function(a, b) {
284
+ var c = Array.prototype.slice.call(arguments, 1);
285
+ return function() {
286
+ var b = Array.prototype.slice.call(arguments);
287
+ b.unshift.apply(b, c);
288
+ return a.apply(this, b)
289
+ }
290
+ };
291
+ goog.mixin = function(a, b) {
292
+ for(var c in b) {
293
+ a[c] = b[c]
294
+ }
295
+ };
296
+ goog.now = goog.TRUSTED_SITE && Date.now || function() {
297
+ return+new Date
298
+ };
299
+ goog.globalEval = function(a) {
300
+ if(goog.global.execScript) {
301
+ goog.global.execScript(a, "JavaScript")
302
+ }else {
303
+ if(goog.global.eval) {
304
+ if(null == goog.evalWorksForGlobals_ && (goog.global.eval("var _et_ = 1;"), "undefined" != typeof goog.global._et_ ? (delete goog.global._et_, goog.evalWorksForGlobals_ = !0) : goog.evalWorksForGlobals_ = !1), goog.evalWorksForGlobals_) {
305
+ goog.global.eval(a)
306
+ }else {
307
+ var b = goog.global.document, c = b.createElement("script");
308
+ c.type = "text/javascript";
309
+ c.defer = !1;
310
+ c.appendChild(b.createTextNode(a));
311
+ b.body.appendChild(c);
312
+ b.body.removeChild(c)
313
+ }
314
+ }else {
315
+ throw Error("goog.globalEval not available");
316
+ }
317
+ }
318
+ };
319
+ goog.evalWorksForGlobals_ = null;
320
+ goog.getCssName = function(a, b) {
321
+ var c = function(a) {
322
+ return goog.cssNameMapping_[a] || a
323
+ }, d = function(a) {
324
+ a = a.split("-");
325
+ for(var b = [], d = 0;d < a.length;d++) {
326
+ b.push(c(a[d]))
327
+ }
328
+ return b.join("-")
329
+ }, d = goog.cssNameMapping_ ? "BY_WHOLE" == goog.cssNameMappingStyle_ ? c : d : function(a) {
330
+ return a
331
+ };
332
+ return b ? a + "-" + d(b) : d(a)
333
+ };
334
+ goog.setCssNameMapping = function(a, b) {
335
+ goog.cssNameMapping_ = a;
336
+ goog.cssNameMappingStyle_ = b
337
+ };
338
+ !COMPILED && goog.global.CLOSURE_CSS_NAME_MAPPING && (goog.cssNameMapping_ = goog.global.CLOSURE_CSS_NAME_MAPPING);
339
+ goog.getMsg = function(a, b) {
340
+ var c = b || {}, d;
341
+ for(d in c) {
342
+ var e = ("" + c[d]).replace(/\$/g, "$$$$");
343
+ a = a.replace(RegExp("\\{\\$" + d + "\\}", "gi"), e)
344
+ }
345
+ return a
346
+ };
347
+ goog.getMsgWithFallback = function(a, b) {
348
+ return a
349
+ };
350
+ goog.exportSymbol = function(a, b, c) {
351
+ goog.exportPath_(a, b, c)
352
+ };
353
+ goog.exportProperty = function(a, b, c) {
354
+ a[b] = c
355
+ };
356
+ goog.inherits = function(a, b) {
357
+ function c() {
358
+ }
359
+ c.prototype = b.prototype;
360
+ a.superClass_ = b.prototype;
361
+ a.prototype = new c;
362
+ a.prototype.constructor = a
363
+ };
364
+ goog.base = function(a, b, c) {
365
+ var d = arguments.callee.caller;
366
+ if(goog.DEBUG && !d) {
367
+ throw Error("arguments.caller not defined. goog.base() expects not to be running in strict mode. See http://www.ecma-international.org/ecma-262/5.1/#sec-C");
368
+ }
369
+ if(d.superClass_) {
370
+ return d.superClass_.constructor.apply(a, Array.prototype.slice.call(arguments, 1))
371
+ }
372
+ for(var e = Array.prototype.slice.call(arguments, 2), f = !1, g = a.constructor;g;g = g.superClass_ && g.superClass_.constructor) {
373
+ if(g.prototype[b] === d) {
374
+ f = !0
375
+ }else {
376
+ if(f) {
377
+ return g.prototype[b].apply(a, e)
378
+ }
379
+ }
380
+ }
381
+ if(a[b] === d) {
382
+ return a.constructor.prototype[b].apply(a, e)
383
+ }
384
+ throw Error("goog.base called from a method of one name to a method of a different name");
385
+ };
386
+ goog.scope = function(a) {
387
+ a.call(goog.global)
388
+ };
1
389
  var axs = {};
2
390
  axs.constants = {};
3
391
  axs.constants.ARIA_ROLES = {alert:{namefrom:["author"], parent:["region"]}, alertdialog:{namefrom:["author"], namerequired:!0, parent:["alert", "dialog"]}, application:{namefrom:["author"], namerequired:!0, parent:["landmark"]}, article:{namefrom:["author"], parent:["document", "region"]}, banner:{namefrom:["author"], parent:["landmark"]}, button:{childpresentational:!0, namefrom:["contents", "author"], namerequired:!0, parent:["command"], properties:["aria-expanded", "aria-pressed"]}, checkbox:{namefrom:["contents",
@@ -33,8 +421,7 @@ axs.constants.addAllPropertiesToSet_ = function(a, b, c) {
33
421
  }
34
422
  }
35
423
  if(a.parent) {
36
- a = a.parent;
37
- for(d = 0;d < a.length;d++) {
424
+ for(a = a.parent, d = 0;d < a.length;d++) {
38
425
  axs.constants.addAllPropertiesToSet_(axs.constants.ARIA_ROLES[a[d]], b, c)
39
426
  }
40
427
  }
@@ -104,7 +491,7 @@ axs.utils.elementIsTransparent = function(a) {
104
491
  axs.utils.elementHasZeroArea = function(a) {
105
492
  a = a.getBoundingClientRect();
106
493
  var b = a.top - a.bottom;
107
- return!(a.right - a.left) || !b ? !0 : !1
494
+ return a.right - a.left && b ? !1 : !0
108
495
  };
109
496
  axs.utils.elementIsOutsideScrollArea = function(a) {
110
497
  a = a.getBoundingClientRect();
@@ -119,18 +506,14 @@ axs.utils.overlappingElement = function(a) {
119
506
  return null
120
507
  }
121
508
  var c = a.getBoundingClientRect(), c = document.elementFromPoint((c.left + c.right) / 2, (c.top + c.bottom) / 2);
122
- return null != c && c != a && !b(c, a) ? c : null
509
+ return null == c || c == a || b(c, a) ? null : c
123
510
  };
124
511
  axs.utils.elementIsHtmlControl = function(a) {
125
- return a instanceof HTMLButtonElement || a instanceof HTMLInputElement || a instanceof HTMLSelectElement || a instanceof HTMLTextAreaElement ? !0 : !1
512
+ var b = a.ownerDocument.defaultView;
513
+ return a instanceof b.HTMLButtonElement || a instanceof b.HTMLInputElement || a instanceof b.HTMLSelectElement || a instanceof b.HTMLTextAreaElement ? !0 : !1
126
514
  };
127
515
  axs.utils.elementIsAriaWidget = function(a) {
128
- if(a.hasAttribute("role") && (a = a.getAttribute("role"))) {
129
- if((a = axs.constants.ARIA_ROLES[a]) && "widget" in a.allParentRolesSet) {
130
- return!0
131
- }
132
- }
133
- return!1
516
+ return a.hasAttribute("role") && (a = a.getAttribute("role")) && (a = axs.constants.ARIA_ROLES[a]) && "widget" in a.allParentRolesSet ? !0 : !1
134
517
  };
135
518
  axs.utils.elementIsVisible = function(a) {
136
519
  if(axs.utils.elementIsTransparent(a) || axs.utils.elementHasZeroArea(a) || axs.utils.elementIsOutsideScrollArea(a)) {
@@ -178,11 +561,9 @@ axs.utils.getBgColor = function(a, b) {
178
561
  if(f.backgroundImage && "none" != f.backgroundImage) {
179
562
  return null
180
563
  }
181
- if((f = axs.utils.parseColor(f.backgroundColor)) && 0 != f.alpha) {
182
- if(e.push(f), 1 == f.alpha) {
183
- c = null;
184
- break
185
- }
564
+ if((f = axs.utils.parseColor(f.backgroundColor)) && 0 != f.alpha && (e.push(f), 1 == f.alpha)) {
565
+ c = null;
566
+ break
186
567
  }
187
568
  }
188
569
  }
@@ -239,7 +620,7 @@ axs.utils.getContrastRatioForElementWithComputedStyle = function(a, b) {
239
620
  return null
240
621
  }
241
622
  var d = axs.utils.getFgColor(a, c);
242
- return!d ? null : axs.utils.calculateContrastRatio(d, c)
623
+ return d ? axs.utils.calculateContrastRatio(d, c) : null
243
624
  };
244
625
  axs.utils.isNativeTextElement = function(a) {
245
626
  var b = a.tagName.toLowerCase();
@@ -288,7 +669,7 @@ axs.utils.hasLabel = function(a) {
288
669
  return!1
289
670
  };
290
671
  axs.utils.isElementHidden = function(a) {
291
- if(!(a instanceof HTMLElement)) {
672
+ if(!(a instanceof a.ownerDocument.defaultView.HTMLElement)) {
292
673
  return!1
293
674
  }
294
675
  if(a.hasAttribute("chromevoxignoreariahidden")) {
@@ -360,7 +741,7 @@ axs.utils.isValidTokenValue = function(a, b) {
360
741
  return axs.utils.isPossibleValue(b, axs.constants.ARIA_PROPERTIES[c].valuesSet, a)
361
742
  };
362
743
  axs.utils.isPossibleValue = function(a, b, c) {
363
- return!b[a] ? {valid:!1, value:a, reason:'"' + a + '" is not a valid value for ' + c, possibleValues:Object.keys(b)} : {valid:!0, value:a}
744
+ return b[a] ? {valid:!0, value:a} : {valid:!1, value:a, reason:'"' + a + '" is not a valid value for ' + c, possibleValues:Object.keys(b)}
364
745
  };
365
746
  axs.utils.isValidBoolean = function(a) {
366
747
  try {
@@ -371,14 +752,15 @@ axs.utils.isValidBoolean = function(a) {
371
752
  return"boolean" != typeof b ? {valid:!1, value:a, reason:'"' + a + '" is not a true/false value'} : {valid:!0, value:b}
372
753
  };
373
754
  axs.utils.isValidIDRefValue = function(a, b) {
374
- return!b.ownerDocument.getElementById(a) ? {valid:!1, idref:a, reason:'No element with ID "' + a + '"'} : {valid:!0, idref:a}
755
+ return b.ownerDocument.getElementById(a) ? {valid:!0, idref:a} : {valid:!1, idref:a, reason:'No element with ID "' + a + '"'}
375
756
  };
376
757
  axs.utils.isValidNumber = function(a) {
377
758
  var b = JSON.parse(a);
378
759
  return"number" != typeof b ? {valid:!1, value:a, reason:'"' + a + '" is not a number'} : {valid:!0, value:b}
379
760
  };
380
761
  axs.utils.isElementImplicitlyFocusable = function(a) {
381
- return a instanceof HTMLAnchorElement || a instanceof HTMLAreaElement ? a.hasAttribute("href") : a instanceof HTMLInputElement || a instanceof HTMLSelectElement || a instanceof HTMLTextAreaElement || a instanceof HTMLButtonElement || a instanceof HTMLIFrameElement ? !a.disabled : !1
762
+ var b = a.ownerDocument.defaultView;
763
+ return a instanceof b.HTMLAnchorElement || a instanceof b.HTMLAreaElement ? a.hasAttribute("href") : a instanceof b.HTMLInputElement || a instanceof b.HTMLSelectElement || a instanceof b.HTMLTextAreaElement || a instanceof b.HTMLButtonElement || a instanceof b.HTMLIFrameElement ? !a.disabled : !1
382
764
  };
383
765
  axs.utils.values = function(a) {
384
766
  var b = [], c;
@@ -413,7 +795,7 @@ axs.utils.getQuerySelectorText = function(a) {
413
795
  if(a.parentNode) {
414
796
  for(c = 0;c < a.parentNode.children.length;c++) {
415
797
  var e = a.parentNode.children[c];
416
- e.webkitMatchesSelector(b) && d++;
798
+ axs.browserUtils.matchSelector(e, b) && d++;
417
799
  if(e === a) {
418
800
  break
419
801
  }
@@ -465,7 +847,7 @@ axs.AuditRule.prototype.addNode = function(a, b) {
465
847
  axs.AuditRule.prototype.run = function(a, b) {
466
848
  function c(a) {
467
849
  for(var b = 0;b < d.length;b++) {
468
- if(a.webkitMatchesSelector(d[b])) {
850
+ if(axs.browserUtils.matchSelector(a, d[b])) {
469
851
  return!0
470
852
  }
471
853
  }
@@ -510,24 +892,31 @@ axs.AuditResults = function() {
510
892
  this.errors_ = [];
511
893
  this.warnings_ = []
512
894
  };
895
+ goog.exportSymbol("axs.AuditResults", axs.AuditResults);
513
896
  axs.AuditResults.prototype.addError = function(a) {
514
897
  "" != a && this.errors_.push(a)
515
898
  };
899
+ goog.exportProperty(axs.AuditResults.prototype, "addError", axs.AuditResults.prototype.addError);
516
900
  axs.AuditResults.prototype.addWarning = function(a) {
517
901
  "" != a && this.warnings_.push(a)
518
902
  };
903
+ goog.exportProperty(axs.AuditResults.prototype, "addWarning", axs.AuditResults.prototype.addWarning);
519
904
  axs.AuditResults.prototype.numErrors = function() {
520
905
  return this.errors_.length
521
906
  };
907
+ goog.exportProperty(axs.AuditResults.prototype, "numErrors", axs.AuditResults.prototype.numErrors);
522
908
  axs.AuditResults.prototype.numWarnings = function() {
523
909
  return this.warnings_.length
524
910
  };
911
+ goog.exportProperty(axs.AuditResults.prototype, "numWarnings", axs.AuditResults.prototype.numWarnings);
525
912
  axs.AuditResults.prototype.getErrors = function() {
526
913
  return this.errors_
527
914
  };
915
+ goog.exportProperty(axs.AuditResults.prototype, "getErrors", axs.AuditResults.prototype.getErrors);
528
916
  axs.AuditResults.prototype.getWarnings = function() {
529
917
  return this.warnings_
530
918
  };
919
+ goog.exportProperty(axs.AuditResults.prototype, "getWarnings", axs.AuditResults.prototype.getWarnings);
531
920
  axs.AuditResults.prototype.toString = function() {
532
921
  for(var a = "", b = 0;b < this.errors_.length;b++) {
533
922
  0 == b && (a += "\nErrors:\n");
@@ -538,12 +927,18 @@ axs.AuditResults.prototype.toString = function() {
538
927
  }
539
928
  return a
540
929
  };
930
+ goog.exportProperty(axs.AuditResults.prototype, "toString", axs.AuditResults.prototype.toString);
541
931
  axs.Audit = {};
542
932
  axs.AuditConfiguration = function() {
543
933
  this.rules_ = {};
544
934
  this.auditRulesToIgnore = this.auditRulesToRun = this.scope = null;
545
- this.withConsoleApi = !1
935
+ this.withConsoleApi = !1;
936
+ goog.exportProperty(this, "scope", this.scope);
937
+ goog.exportProperty(this, "auditRulesToRun", this.auditRulesToRun);
938
+ goog.exportProperty(this, "auditRulesToIgnore", this.auditRulesToIgnore);
939
+ goog.exportProperty(this, "withConsoleApi", this.withConsoleApi)
546
940
  };
941
+ goog.exportSymbol("axs.AuditConfiguration", axs.AuditConfiguration);
547
942
  axs.AuditConfiguration.prototype = {ignoreSelectors:function(a, b) {
548
943
  a in this.rules_ || (this.rules_[a] = {});
549
944
  "ignore" in this.rules_[a] || (this.rules_[a].ignore = []);
@@ -551,6 +946,8 @@ axs.AuditConfiguration.prototype = {ignoreSelectors:function(a, b) {
551
946
  }, getIgnoreSelectors:function(a) {
552
947
  return a in this.rules_ && "ignore" in this.rules_[a] ? this.rules_[a].ignore : []
553
948
  }};
949
+ goog.exportProperty(axs.AuditConfiguration.prototype, "ignoreSelectors", axs.AuditConfiguration.prototype.ignoreSelectors);
950
+ goog.exportProperty(axs.AuditConfiguration.prototype, "getIgnoreSelectors", axs.AuditConfiguration.prototype.getIgnoreSelectors);
554
951
  axs.Audit.run = function(a) {
555
952
  a = a || new axs.AuditConfiguration;
556
953
  var b = a.withConsoleApi, c = [], d;
@@ -573,6 +970,7 @@ axs.Audit.run = function(a) {
573
970
  }
574
971
  return c
575
972
  };
973
+ goog.exportSymbol("axs.Audit.run", axs.Audit.run);
576
974
  axs.Audit.auditResults = function(a) {
577
975
  for(var b = new axs.AuditResults, c = 0;c < a.length;c++) {
578
976
  var d = a[c];
@@ -580,12 +978,14 @@ axs.Audit.auditResults = function(a) {
580
978
  }
581
979
  return b
582
980
  };
981
+ goog.exportSymbol("axs.Audit.auditResults", axs.Audit.auditResults);
583
982
  axs.Audit.createReport = function(a, b) {
584
983
  var c;
585
984
  c = "*** Begin accessibility audit results ***\nAn accessibility audit found " + axs.Audit.auditResults(a).toString();
586
985
  b && (c += "\nFor more information, please see ", c += b);
587
986
  return c += "\n*** End accessibility audit results ***"
588
987
  };
988
+ goog.exportSymbol("axs.Audit.createReport", axs.Audit.createReport);
589
989
  axs.Audit.accessibilityErrorMessage = function(a) {
590
990
  for(var b = a.rule.severity == axs.constants.Severity.SEVERE ? "Error: " : "Warning: ", b = b + (a.rule.code + " (" + a.rule.heading + ") failed on the following " + (1 == a.elements.length ? "element" : "elements")), b = 1 == a.elements.length ? b + ":" : b + (" (1 - " + Math.min(5, a.elements.length) + " of " + a.elements.length + "):"), c = Math.min(a.elements.length, 5), d = 0;d < c;d++) {
591
991
  var e = a.elements[d], b = b + "\n";
@@ -598,6 +998,11 @@ axs.Audit.accessibilityErrorMessage = function(a) {
598
998
  "" != a.rule.url && (b += "\nSee " + a.rule.url + " for more information.");
599
999
  return b
600
1000
  };
1001
+ goog.exportSymbol("axs.Audit.accessibilityErrorMessage", axs.Audit.accessibilityErrorMessage);
1002
+ axs.browserUtils = {};
1003
+ axs.browserUtils.matchSelector = function(a, b) {
1004
+ return a.webkitMatchesSelector ? a.webkitMatchesSelector(b) : a.mozMatchesSelector(b)
1005
+ };
601
1006
  axs.AuditRule.specs.audioWithoutControls = {name:"audioWithoutControls", heading:"Audio elements should have controls", url:"", severity:axs.constants.Severity.WARNING, relevantNodesSelector:function(a) {
602
1007
  return a.querySelectorAll("audio[autoplay]")
603
1008
  }, test:function(a) {
@@ -630,7 +1035,7 @@ axs.AuditRule.specs.badAriaRole = {name:"badAriaRole", heading:"Elements with AR
630
1035
  axs.AuditRule.specs.controlsWithoutLabel = {name:"controlsWithoutLabel", heading:"Controls and media elements should have labels", url:"https://code.google.com/p/accessibility-developer-tools/wiki/AuditRules#AX_TEXT_01:_Controls_and_media_elements_should_have_labels", severity:axs.constants.Severity.SEVERE, relevantNodesSelector:function(a) {
631
1036
  return a.querySelectorAll('input:not([type="hidden"]):not([disabled]), select:not([disabled]), textarea:not([disabled]), button:not([disabled]), video:not([disabled])')
632
1037
  }, test:function(a) {
633
- return axs.utils.isElementOrAncestorHidden(a) || "button" == a.tagName.toLowerCase() && a.textContent.replace(/^\s+|\s+$/g, "").length ? !1 : !axs.utils.hasLabel(a) ? !0 : !1
1038
+ return axs.utils.isElementOrAncestorHidden(a) || "button" == a.tagName.toLowerCase() && a.textContent.replace(/^\s+|\s+$/g, "").length ? !1 : axs.utils.hasLabel(a) ? !1 : !0
634
1039
  }, code:"AX_TEXT_01", ruleName:"Controls and media elements should have labels"};
635
1040
  axs.AuditRule.specs.focusableElementNotVisibleAndNotAriaHidden = {name:"focusableElementNotVisibleAndNotAriaHidden", heading:"These elements are focusable but either invisible or obscured by another element", url:"https://code.google.com/p/accessibility-developer-tools/wiki/AuditRules#AX_FOCUS_01:_These_elements_are_focusable_but_either_invisible_o", severity:axs.constants.Severity.WARNING, relevantNodesSelector:function(a) {
636
1041
  return a.querySelectorAll(axs.utils.FOCUSABLE_ELEMENTS_SELECTOR)
@@ -658,6 +1063,26 @@ axs.AuditRule.specs.lowContrastElements = {name:"lowContrastElements", heading:"
658
1063
  var b = window.getComputedStyle(a, null);
659
1064
  return(a = axs.utils.getContrastRatioForElementWithComputedStyle(b, a)) && axs.utils.isLowContrast(a, b)
660
1065
  }, code:"AX_COLOR_01"};
1066
+ axs.AuditRule.specs.elementsWithMeaningfulBackgroundImage = {name:"elementsWithMeaningfulBackgroundImage", severity:axs.constants.Severity.WARNING, relevantNodesSelector:function(a) {
1067
+ a = a.querySelectorAll("*");
1068
+ for(var b = [], c = 0;c < a.length;c++) {
1069
+ var d = a[c];
1070
+ axs.utils.isElementOrAncestorHidden(d) || b.push(d)
1071
+ }
1072
+ return b
1073
+ }, heading:"Meaningful images should not be used in element backgrounds", url:"https://code.google.com/p/accessibility-developer-tools/wiki/AuditRules?ts=1368336558&updated=AuditRules#AX_IMAGE_01:_Meaningful_images_should_not_be_used_in_element_bac", test:function(a) {
1074
+ if(a.textContent && 0 < a.textContent.length) {
1075
+ return!1
1076
+ }
1077
+ a = window.getComputedStyle(a, null);
1078
+ var b = a.backgroundImage;
1079
+ if(!b || "undefined" === b || "none" === b) {
1080
+ return!1
1081
+ }
1082
+ b = parseInt(a.width, 10);
1083
+ a = parseInt(a.height, 10);
1084
+ return 150 > b && 150 > a
1085
+ }, code:"AX_IMAGE_01"};
661
1086
  axs.AuditRule.specs.nonExistentAriaLabelledbyElement = {name:"nonExistentAriaLabelledbyElement", heading:"aria-labelledby attributes should refer to an element which exists in the DOM", url:"https://code.google.com/p/accessibility-developer-tools/wiki/AuditRules#AX_ARIA_02:__aria-labelledby_attributes_should_refer_to_an_eleme", severity:axs.constants.Severity.WARNING, relevantNodesSelector:function(a) {
662
1087
  return a.querySelectorAll("[aria-labelledby]")
663
1088
  }, test:function(a) {
@@ -669,7 +1094,7 @@ axs.AuditRule.specs.nonExistentAriaLabelledbyElement = {name:"nonExistentAriaLab
669
1094
  }
670
1095
  return!1
671
1096
  }, code:"AX_ARIA_02"};
672
- axs.AuditRule.specs.pageWithoutTitle = {name:"pageWithoutTitle", heading:"Web pages have titles that describe topic or purpose", url:"", severity:axs.constants.Severity.WARNING, relevantNodesSelector:function(a) {
1097
+ axs.AuditRule.specs.pageWithoutTitle = {name:"pageWithoutTitle", heading:"The web page should have a title that describes topic or purpose", url:"", severity:axs.constants.Severity.WARNING, relevantNodesSelector:function(a) {
673
1098
  return a
674
1099
  }, test:function(a) {
675
1100
  a = a.querySelector("head");
@@ -701,7 +1126,7 @@ axs.AuditRule.specs.unfocusableElementsWithOnClick = {name:"unfocusableElementsW
701
1126
  a = a.querySelectorAll("*");
702
1127
  for(var b = [], c = 0;c < a.length;c++) {
703
1128
  var d = a[c];
704
- d instanceof HTMLBodyElement || axs.utils.isElementOrAncestorHidden(d) || "click" in getEventListeners(d) && b.push(d)
1129
+ d instanceof d.ownerDocument.defaultView.HTMLBodyElement || axs.utils.isElementOrAncestorHidden(d) || "click" in getEventListeners(d) && b.push(d)
705
1130
  }
706
1131
  return b
707
1132
  }, test:function(a) {
@@ -4,7 +4,7 @@ module Capybara::Accessible
4
4
 
5
5
  def visit(path)
6
6
  super
7
- if audit_results.any? { |r| r['result'] == 'FAIL' }
7
+ if audit_failures.any?
8
8
  raise Capybara::Accessible::InaccessibleError, failure_messages
9
9
  end
10
10
  end
@@ -6,7 +6,7 @@ module Capybara
6
6
  def click
7
7
  synchronize { base.click }
8
8
  begin
9
- if Capybara.current_driver == :accessible && audit_results.any? { |r| r['result'] == 'FAIL' }
9
+ if Capybara.current_driver == :accessible && audit_failures.any?
10
10
  raise Capybara::Accessible::InaccessibleError, failure_messages
11
11
  end
12
12
  rescue ::Selenium::WebDriver::Error::UnhandledAlertError => e
@@ -1,5 +1,5 @@
1
1
  module Capybara
2
2
  module Accessible
3
- VERSION = "0.0.2"
3
+ VERSION = "0.1.0"
4
4
  end
5
5
  end
@@ -6,6 +6,10 @@ class AccessibleApp < TestApp
6
6
  end
7
7
 
8
8
  get '/inaccessible' do
9
+ '<div role="zomg"></div>'
10
+ end
11
+
12
+ get '/excluded' do
9
13
  '<form><input type="text" name="foo" id="foo"/></form>'
10
14
  end
11
15
 
@@ -27,7 +27,7 @@ describe Capybara::Accessible::Driver do
27
27
  end
28
28
 
29
29
  it 'does not raise an error on an excluded rule' do
30
- expect { @session.visit('/inaccessible') }.to_not raise_error(Capybara::Accessible::InaccessibleError)
30
+ expect { @session.visit('/excluded') }.to_not raise_error(Capybara::Accessible::InaccessibleError)
31
31
  end
32
32
  end
33
33
  end
@@ -0,0 +1,7 @@
1
+ language: ruby
2
+
3
+ rvm:
4
+ - 1.9.3
5
+ - 2.0.0
6
+
7
+ script: "bundle exec rake"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: capybara-accessible
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Case Commons
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-06-27 00:00:00.000000000 Z
11
+ date: 2013-07-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: capybara
@@ -123,6 +123,7 @@ extra_rdoc_files: []
123
123
  files:
124
124
  - .gitignore
125
125
  - Gemfile
126
+ - Gemfile.lock
126
127
  - LICENSE.txt
127
128
  - README.md
128
129
  - Rakefile
@@ -136,6 +137,7 @@ files:
136
137
  - spec/accessible_app.rb
137
138
  - spec/driver_spec.rb
138
139
  - spec/spec_helper.rb
140
+ - travis.yml
139
141
  homepage: https://github.com/Casecommons/capybara-accessible
140
142
  licenses:
141
143
  - MIT
@@ -156,7 +158,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
156
158
  version: '0'
157
159
  requirements: []
158
160
  rubyforge_project:
159
- rubygems_version: 2.0.2
161
+ rubygems_version: 2.0.3
160
162
  signing_key:
161
163
  specification_version: 4
162
164
  summary: A Selenium based webdriver and Capybara extension that runs Google Accessibility
@@ -165,4 +167,3 @@ test_files:
165
167
  - spec/accessible_app.rb
166
168
  - spec/driver_spec.rb
167
169
  - spec/spec_helper.rb
168
- has_rdoc: