capybara-accessible 0.0.2 → 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.
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: