1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
6 * @fileoverview Tests to ensure that the accessibility audit and mechanisms
7 * to enable/disable it work as expected.
8 * @author aboxhall@google.com (Alice Boxhall)
13 * Test fixture for accessibility audit test.
15 * @extends testing.Test
17 function WebUIAccessibilityAuditBrowserTest() {}
19 WebUIAccessibilityAuditBrowserTest
.prototype = {
20 __proto__
: testing
.Test
.prototype,
22 browsePreload
: 'chrome://terms',
24 runAccessibilityChecks
: true,
25 accessibilityIssuesAreErrors
: true,
28 * Number of expected accessibility errors, if it should be checked, otherwise
29 * null. Note: 'a11y' is short for 'accessibility'
32 expectedWarnings
: null,
35 * Number of expected accessibility warnings, if it should be checked,
45 this.accessibilityAuditConfig
.auditRulesToIgnore
= [];
46 this.accessibilityAuditConfig
.auditRulesToRun
= ['lowContrastElements',
48 'controlsWithoutLabel'];
51 tearDown: function() {
52 var accessibilityResults
= this.getAccessibilityResults();
53 var numAccessibilityErrors
= 0;
54 var numAccessibilityWarnings
= 0;
55 for (var i
= 0; i
< accessibilityResults
.length
; i
++) {
56 var result
= accessibilityResults
[i
];
57 if (result
.rule
.severity
== axs
.constants
.Severity
.Warning
)
58 numAccessibilityWarnings
++;
60 numAccessibilityErrors
++;
63 if (this.expectedErrors
!= null)
64 expectEquals(this.expectedErrors
, numAccessibilityErrors
);
65 if (this.expectedWarnings
!= null) {
66 expectEquals(this.expectedWarnings
, numAccessibilityWarnings
);
68 testing
.Test
.prototype.tearDown
.call(this);
73 * Test fixture for tests that are expected to fail.
75 function WebUIAccessibilityAuditBrowserTest_ShouldFail() {}
77 WebUIAccessibilityAuditBrowserTest_ShouldFail
.prototype = {
78 __proto__
: WebUIAccessibilityAuditBrowserTest
.prototype,
84 * Adds some canned audit failures to the page being tested:
85 * - A low-contrast (white on white) element
86 * - An element with a non-existent ARIA role
87 * - A control without a label
89 function addAuditFailures() {
91 var style
= document
.createElement('style');
92 style
.innerText
= 'body { background-color: #ffff }\n' +
93 'p { color: #ffffff }';
94 document
.head
.appendChild(style
);
97 var div
= document
.createElement('div');
98 div
.setAttribute('role', 'not-a-role');
99 document
.body
.appendChild(div
);
101 // Unlabelled control
102 var input
= document
.createElement('input');
104 document
.body
.appendChild(input
);
108 * Adds an expectation that console.warn() will be called at least once with
109 * a string matching '.*accessibility.*'.
111 function expectReportConsoleWarning() {
112 function StubConsole() {};
113 StubConsole
.prototype.warn = function() {};
114 StubConsole
.prototype.log = function() {};
115 StubConsole
.prototype.info = function() {};
116 StubConsole
.prototype.error = function() {};
117 var mockConsole
= mock(StubConsole
);
118 mockConsole
.expects(atLeastOnce()).warn(stringContains('accessibility'));
119 mockConsole
.stubs().log(ANYTHING
);
120 mockConsole
.stubs().info(ANYTHING
);
121 mockConsole
.stubs().error(ANYTHING
);
122 console
= mockConsole
.proxy();
126 * Creates a mock axs.Audit object.
127 * @return {object} a mock object with a run() method.
129 function createMockAudit() {
130 function StubAudit() {};
131 StubAudit
.prototype.run = function() {};
133 return mock(StubAudit
);
137 * Creates an expectation that the global axs.Audit object will never have its
138 * run() method called.
140 function expectAuditWillNotRun() {
141 var audit
= createMockAudit();
142 audit
.expects(never()).run();
143 axs
.Audit
= audit
.proxy();
147 * Creates an expectation that the global axs.Audit object will have its run()
148 * method called |times| times.
149 * This creates an interstitial mock axs.Audit object with the expectation, and
150 * delegates to the real axs.Audit object to run the actual audit.
151 * @param {number} times The number of times the audit is expected to run.
153 function expectAuditWillRun(times
, auditConfig
) {
154 var audit
= createMockAudit();
155 var realAudit
= axs
.Audit
;
156 var expectedInvocation
= audit
.expects(exactly(times
)).run(ANYTHING
);
158 for (var i
= 0; i
< times
; i
++)
159 willArgs
.push(callFunction(realAudit
.run
, auditConfig
));
160 expectedInvocation
.will
.apply(expectedInvocation
, willArgs
);
161 axs
.Audit
= audit
.proxy();
162 axs
.Audit
.createReport
= realAudit
.createReport
;
163 axs
.Audit
.auditResults
= realAudit
.auditResults
;
164 axs
.Audit
.accessibilityErrorMessage
= realAudit
.accessibilityErrorMessage
;
167 // Test that an audit failure causes a test failure, if both
168 // |runAccessibilityChecks| and |accessibilityIssuesAreErrors| are true.
169 TEST_F('WebUIAccessibilityAuditBrowserTest_ShouldFail', 'testWithAuditFailures',
171 expectAuditWillRun(1, this.accessibilityAuditConfig
);
175 // Test that the accessibility audit does not run if |runAccessibilityChecks|
177 TEST_F('WebUIAccessibilityAuditBrowserTest',
178 'testWithAuditFailures_a11yChecksDisabled',
180 expectAuditWillNotRun();
181 this.disableAccessibilityChecks();
185 // Tests that the accessibility audit will run but not cause a test failure when
186 // accessibilityIssuesAreErrors(false) is called in the test function
187 TEST_F('WebUIAccessibilityAuditBrowserTest',
188 'testWithAuditFailures_a11yIssuesAreWarnings',
190 this.accessibilityIssuesAreErrors
= false;
191 expectAuditWillRun(1, this.accessibilityAuditConfig
);
192 expectReportConsoleWarning();
194 this.expectedWarnings
= 1;
195 this.expectedErrors
= 2;
196 this.enableAccessibilityChecks();
201 * Test fixture with |runAccessibilityChecks| set to false.
203 * @extends {WebUIAccessibilityAuditBrowserTest}
205 function WebUIAccessibilityAuditBrowserTest_TestsDisabledInFixture() {}
207 WebUIAccessibilityAuditBrowserTest_TestsDisabledInFixture
.prototype = {
208 __proto__
: WebUIAccessibilityAuditBrowserTest
.prototype,
210 runAccessibilityChecks
: false,
211 accessibilityIssuesAreErrors
: true,
215 * Test fixture with |runAccessibilityChecks| set to false for tests that should
218 * @extends {WebUIAccessibilityAuditBrowserTest_TestsDisabledInFixture}
220 function WebUIAccessibilityAuditBrowserTest_TestsDisabledInFixture_ShouldFail()
223 WebUIAccessibilityAuditBrowserTest_TestsDisabledInFixture_ShouldFail
.prototype =
226 WebUIAccessibilityAuditBrowserTest_TestsDisabledInFixture
.prototype,
233 // Test that the accessibility audit does not run when |runAccessibilityChecks|
234 // is set to false in the test fixture.
235 TEST_F('WebUIAccessibilityAuditBrowserTest_TestsDisabledInFixture',
236 'testWithAuditFailures_a11yChecksNotEnabled',
238 expectAuditWillNotRun();
242 // Test that the accessibility audit does run if the enableAccessibilityChecks()
243 // method is called in the test function.
244 TEST_F('WebUIAccessibilityAuditBrowserTest_TestsDisabledInFixture_ShouldFail',
245 'testWithAuditFailures',
247 expectAuditWillRun(1, this.accessibilityAuditConfig
);
248 this.enableAccessibilityChecks();
252 // Test that the accessibility audit runs when the expectAccessibilityOk()
254 TEST_F('WebUIAccessibilityAuditBrowserTest_TestsDisabledInFixture',
255 'testRunningAuditManually_noErrors',
257 expectAuditWillRun(1, this.accessibilityAuditConfig
);
258 expectAccessibilityOk();
261 // Test that calling expectAccessibilityOk() when there are accessibility issues
262 // on the page causes the test to fail.
263 TEST_F('WebUIAccessibilityAuditBrowserTest_TestsDisabledInFixture_ShouldFail',
264 'testRunningAuditManually_withErrors',
266 expectAuditWillRun(1, this.accessibilityAuditConfig
);
268 expectAccessibilityOk();
271 // Test that calling expectAccessibilityOk() multiple times will cause the
272 // accessibility audit to run multiple times.
273 TEST_F('WebUIAccessibilityAuditBrowserTest_TestsDisabledInFixture',
274 'testRunningAuditManuallySeveralTimes', function() {
275 expectAuditWillRun(2, this.accessibilityAuditConfig
);
276 expectAccessibilityOk();
277 expectAccessibilityOk();
281 * Test fixture with |accessibilityIssuesAreErrors| set to false.
283 * @extends {WebUIAccessibilityAuditBrowserTest}
285 function WebUIAccessibilityAuditBrowserTest_IssuesAreWarnings() {}
287 WebUIAccessibilityAuditBrowserTest_IssuesAreWarnings
.prototype = {
288 __proto__
: WebUIAccessibilityAuditBrowserTest
.prototype,
290 accessibilityIssuesAreErrors
: false,
294 * Test fixture with |accessibilityIssuesAreErrors| set to false for tests that
297 * @extends {WebUIAccessibilityAuditBrowserTest_IssuesAreWarnings}
299 function WebUIAccessibilityAuditBrowserTest_IssuesAreWarnings_ShouldFail() {}
301 WebUIAccessibilityAuditBrowserTest_IssuesAreWarnings_ShouldFail
.prototype = {
302 __proto__
: WebUIAccessibilityAuditBrowserTest_IssuesAreWarnings
.prototype,
308 // Tests that the accessibility audit will run but not cause a test failure when
309 // |accessibilityIssuesAreErrors| is false in the test fixture.
310 TEST_F('WebUIAccessibilityAuditBrowserTest_IssuesAreWarnings',
311 'testWithAuditFailures',
313 expectAuditWillRun(1, this.accessibilityAuditConfig
);
314 expectReportConsoleWarning();
315 this.expectedWarnings
= 1;
316 this.expectedErrors
= 2;
318 this.enableAccessibilityChecks();
322 // Tests that the accessibility audit will run and call a test failure when
323 // accessibilityIssuesAreErrors(true) is called in the test function.
324 TEST_F('WebUIAccessibilityAuditBrowserTest_IssuesAreWarnings_ShouldFail',
325 'testWithAuditFailuresAndIssuesAreErrors',
327 expectAuditWillRun(1, this.accessibilityAuditConfig
);
328 this.expectedWarnings
= 1;
329 this.expectedErrors
= 2;
331 this.accessibilityIssuesAreErrors
= true;
332 this.enableAccessibilityChecks();
337 // Tests that the accessibility audit will run twice if expectAccessibilityOk()
338 // is called during the test function and |runAccessibilityChecks| is true in
340 TEST_F('WebUIAccessibilityAuditBrowserTest_IssuesAreWarnings',
341 'testWithAuditFailuresAndExpectA11yOk',
343 expectAuditWillRun(2, this.accessibilityAuditConfig
);
345 expectAccessibilityOk();
347 this.expectedWarnings
= 1;
348 this.expectedErrors
= 2;
349 expectReportConsoleWarning();
351 this.enableAccessibilityChecks();
356 // Tests that parts of the page can be ignored on a per-audit rule basis.
357 TEST_F('WebUIAccessibilityAuditBrowserTest_IssuesAreWarnings',
358 'testCanIgnoreSelectors',
360 this.disableAccessibilityChecks();
362 var accessibilityResults
= [];
364 assertAccessibilityOk(accessibilityResults
);
366 // Expected error from assertion
368 expectEquals(3, accessibilityResults
.length
);
370 accessibilityResults
.length
= 0;
371 this.accessibilityAuditConfig
.ignoreSelectors('lowContrastElements', '*');
373 assertAccessibilityOk(accessibilityResults
);
375 // Expected error from assertion
377 expectEquals(2, accessibilityResults
.length
);
378 for (var i
= 0; i
< accessibilityResults
.length
; i
++) {
379 expectFalse(accessibilityResults
[i
].rule
.name
== 'lowContrastElements');