Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(450)

Side by Side Diff: chrome/test/data/webui/test_api.js

Issue 11363170: Add an accessibility audit test for WebUI pages (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Reinstate copyright header Created 7 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « chrome/test/data/webui/accessibility_audit_browsertest.js ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 /** 5 /**
6 * @fileoverview Library providing basic test framework functionality. 6 * @fileoverview Library providing basic test framework functionality.
7 */ 7 */
8 8
9 /** 9 /**
10 * Namespace for |Test|. 10 * Namespace for |Test|.
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after
115 */ 115 */
116 testShouldFail: false, 116 testShouldFail: false,
117 117
118 /** 118 /**
119 * Extra libraries to add before loading this test file. 119 * Extra libraries to add before loading this test file.
120 * @type {Array.<string>} 120 * @type {Array.<string>}
121 */ 121 */
122 extraLibraries: [], 122 extraLibraries: [],
123 123
124 /** 124 /**
125 * Whether to run the accessibility checks.
126 * @type {boolean}
127 */
128 runAccessibilityChecks : true,
129
130 /**
131 * Whether to treat accessibility issues (errors or warnings) as test
132 * failures. If true, any accessibility issues will cause the test to fail.
133 * If false, accessibility issues will cause a console.warn.
134 * Off by default to begin with; as we add the ability to suppress false
135 * positives, we will transition this to true.
136 * @type {boolean}
137 */
138 accessibilityIssuesAreErrors: false,
139
140 /**
141 * Holds any accessibility errors found during the accessibility audit.
142 * @type {Array.<string>}
143 */
144 a11yErrors_: [],
145
146 /**
147 * Holds any accessibility warnings found during the accessibility audit.
148 * @type {Array.<string>}
149 */
150 a11yWarnings_: [],
151
152 /**
153 * Gets the list of accessibility errors found during the accessibility
154 * audit. Only for use in testing.
155 * @return {Array.<string>}
156 */
157 getAccessibilityErrors: function() {
158 return this.a11yErrors_;
159 },
160
161 /**
162 * Gets the list of accessibility warnings found during the accessibility
163 * audit. Only for use in testing.
164 * @return {Array.<string>}
165 */
166 getAccessibilityWarnings: function() {
167 return this.a11yWarnings_;
168 },
169
170 /**
171 * Run accessibility checks after this test completes.
172 */
173 enableAccessibilityChecks: function() {
174 this.runAccessibilityChecks = true;
175 },
176
177 /**
178 * Don't run accessibility checks after this test completes.
179 */
180 disableAccessibilityChecks: function() {
181 this.runAccessibilityChecks = false;
182 },
183
184 /**
125 * Create a new class to handle |messageNames|, assign it to 185 * Create a new class to handle |messageNames|, assign it to
126 * |this.mockHandler|, register its messages and return it. 186 * |this.mockHandler|, register its messages and return it.
127 * @return {Mock} Mock handler class assigned to |this.mockHandler|. 187 * @return {Mock} Mock handler class assigned to |this.mockHandler|.
128 */ 188 */
129 makeAndRegisterMockHandler: function(messageNames) { 189 makeAndRegisterMockHandler: function(messageNames) {
130 var MockClass = makeMockClass(messageNames); 190 var MockClass = makeMockClass(messageNames);
131 this.mockHandler = mock(MockClass); 191 this.mockHandler = mock(MockClass);
132 registerMockMessageCallbacks(this.mockHandler, MockClass); 192 registerMockMessageCallbacks(this.mockHandler, MockClass);
133 return this.mockHandler; 193 return this.mockHandler;
134 }, 194 },
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
171 231
172 /** 232 /**
173 * Called to run the body from the perspective of this fixture. 233 * Called to run the body from the perspective of this fixture.
174 * @type {Function} 234 * @type {Function}
175 */ 235 */
176 runTest: function(testBody) { 236 runTest: function(testBody) {
177 testBody.call(this); 237 testBody.call(this);
178 }, 238 },
179 239
180 /** 240 /**
241 * Called to run the accessibility audit from the perspective of this
242 * fixture.
243 */
244 runAccessibilityAudit: function() {
245 if (!this.runAccessibilityChecks || typeof document === 'undefined')
246 return;
247
248 if (!runAccessibilityAudit(this.a11yErrors_, this.a11yWarnings_)) {
249 var report = accessibilityAuditReport(this.a11yErrors_,
250 this.a11yWarnings_);
251 if (this.accessibilityIssuesAreErrors)
252 throw new Error(report);
253 else
254 console.warn(report);
255 }
256 },
257
258 /**
181 * Create a closure function for continuing the test at a later time. May be 259 * Create a closure function for continuing the test at a later time. May be
182 * used as a listener function. 260 * used as a listener function.
183 * @param {WhenTestDone} whenTestDone Call testDone() at the appropriate 261 * @param {WhenTestDone} whenTestDone Call testDone() at the appropriate
184 * time. 262 * time.
185 * @param {Function} completion The function to call to complete the test. 263 * @param {Function} completion The function to call to complete the test.
186 * @param {...*} var_args Arguments to pass when calling completionAction. 264 * @param {...*} var_args Arguments to pass when calling completionAction.
187 * @return {function(): void} Return a function, bound to this test fixture, 265 * @return {function(): void} Return a function, bound to this test fixture,
188 * which continues the test. 266 * which continues the test.
189 */ 267 */
190 continueTest: function(whenTestDone, completion) { 268 continueTest: function(whenTestDone, completion) {
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after
290 368
291 /** 369 /**
292 * Called to run this test's body. 370 * Called to run this test's body.
293 */ 371 */
294 runTest: function() { 372 runTest: function() {
295 if (this.body && this.fixture) 373 if (this.body && this.fixture)
296 this.fixture.runTest(this.body); 374 this.fixture.runTest(this.body);
297 }, 375 },
298 376
299 /** 377 /**
378 * Called after a test is run (in testDone) to test accessibility.
379 */
380 runAccessibilityAudit: function() {
381 if (this.fixture)
382 this.fixture.runAccessibilityAudit();
383 },
384
385 /**
300 * Runs this test case with |this| set to the |fixture|. 386 * Runs this test case with |this| set to the |fixture|.
301 * 387 *
302 * Note: Tests created with TEST_F may depend upon |this| being set to an 388 * Note: Tests created with TEST_F may depend upon |this| being set to an
303 * instance of this.fixture. The current implementation of TEST creates a 389 * instance of this.fixture. The current implementation of TEST creates a
304 * dummy constructor, but tests created with TEST should not rely on |this| 390 * dummy constructor, but tests created with TEST should not rely on |this|
305 * being set. 391 * being set.
306 * @type {Function} 392 * @type {Function}
307 */ 393 */
308 run: function() { 394 run: function() {
309 try { 395 try {
(...skipping 290 matching lines...) Expand 10 before | Expand all | Expand 10 after
600 686
601 /** 687 /**
602 * Notifies the running browser test of the test results. Clears |errors|. 688 * Notifies the running browser test of the test results. Clears |errors|.
603 * @param {Array.<boolean, string>=} result When passed, this is used for the 689 * @param {Array.<boolean, string>=} result When passed, this is used for the
604 * testResult message. 690 * testResult message.
605 */ 691 */
606 function testDone(result) { 692 function testDone(result) {
607 if (!testIsDone) { 693 if (!testIsDone) {
608 testIsDone = true; 694 testIsDone = true;
609 if (currentTestCase) { 695 if (currentTestCase) {
610 try { 696 var ok = true;
611 currentTestCase.tearDown(); 697 ok = createExpect(currentTestCase.runAccessibilityAudit.bind(
612 } catch (e) { 698 currentTestCase)).call(null) && ok;
613 // Caught an exception in tearDown; Register the error and recreate 699 ok = createExpect(currentTestCase.tearDown.bind(
614 // the result if it is passed in. 700 currentTestCase)).call(null) && ok;
615 errors.push(e); 701
616 if (result) 702 if (!ok && result)
617 result = [false, errorsToMessage([e], result[1])]; 703 result = [false, errorsToMessage(errors, result[1])];
618 } 704
619 currentTestCase = null; 705 currentTestCase = null;
620 } 706 }
621 chrome.send('testResult', result ? result : testResult()); 707 if (!result)
708 result = testResult();
709 chrome.send('testResult', result);
622 errors.splice(0, errors.length); 710 errors.splice(0, errors.length);
623 } else { 711 } else {
624 console.warn('testIsDone already'); 712 console.warn('testIsDone already');
625 } 713 }
626 } 714 }
627 715
628 /** 716 /**
629 * Converts each Error in |errors| to a suitable message, adding them to 717 * Converts each Error in |errors| to a suitable message, adding them to
630 * |message|, and returns the message string. 718 * |message|, and returns the message string.
631 * @param {Array.<Error>} errors Array of errors to add to |message|. 719 * @param {Array.<Error>} errors Array of errors to add to |message|.
(...skipping 13 matching lines...) Expand all
645 return message; 733 return message;
646 } 734 }
647 735
648 /** 736 /**
649 * Returns [success, message] & clears |errors|. 737 * Returns [success, message] & clears |errors|.
650 * @param {boolean} errorsOk When true, errors are ok. 738 * @param {boolean} errorsOk When true, errors are ok.
651 * @return {Array.<boolean, string>} 739 * @return {Array.<boolean, string>}
652 */ 740 */
653 function testResult(errorsOk) { 741 function testResult(errorsOk) {
654 var result = [true, '']; 742 var result = [true, ''];
655 if (errors.length) { 743 if (errors.length)
656 result = [!!errorsOk, errorsToMessage(errors)]; 744 result = [!!errorsOk, errorsToMessage(errors)];
657 } 745
658 return result; 746 return result;
659 } 747 }
660 748
661 // Asserts. 749 // Asserts.
662 // Use the following assertions to verify a condition within a test. 750 // Use the following assertions to verify a condition within a test.
663 // If assertion fails, throw an Error with information pertinent to the test. 751 // If assertion fails, throw an Error with information pertinent to the test.
664 752
665 /** 753 /**
666 * When |test| !== true, aborts the current test. 754 * When |test| !== true, aborts the current test.
667 * @param {boolean} test The predicate to check against |expected|. 755 * @param {boolean} test The predicate to check against |expected|.
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after
786 * Always aborts the current test. 874 * Always aborts the current test.
787 * @param {string=} message The message to include in the Error thrown. 875 * @param {string=} message The message to include in the Error thrown.
788 * @throws {Error} always. 876 * @throws {Error} always.
789 */ 877 */
790 function assertNotReached(message) { 878 function assertNotReached(message) {
791 helper.registerCall(); 879 helper.registerCall();
792 throw new Error(helper.getCallMessage(message)); 880 throw new Error(helper.getCallMessage(message));
793 } 881 }
794 882
795 /** 883 /**
884 * Run an accessibility audit on the current page state.
885 * @type {Function}
886 * @return {boolean} Whether there were any errors or warnings
887 * @private
888 */
889 function runAccessibilityAudit(a11yErrors, a11yWarnings) {
890 var auditResults = axs.Audit.run();
891 for (var i = 0; i < auditResults.length; i++) {
892 var auditResult = auditResults[i];
893 if (auditResult.result == axs.constants.AuditResult.FAIL) {
894 var auditRule = auditResult.rule;
895 // TODO(aboxhall): more useful error messages (sadly non-trivial)
896 if (auditRule.severity == axs.constants.Severity.Severe)
897 a11yErrors.push(accessibilityErrorMessage(auditRule, auditResult));
898 else
899 a11yWarnings.push(accessibilityErrorMessage(auditRule, auditResult));
900 }
901 }
902
903 // TODO(aboxhall): have strict (no errors or warnings) vs non-strict
904 // (warnings ok)
905 // TODO(aboxhall): some kind of info logging for warnings only??
906 return (a11yErrors.length == 0 && a11yWarnings.length == 0);
907 }
908
909 /**
910 * Concatenates the accessibility error messages in |a11yErrors| and
911 * |a11yWarnings| in to an accessibility report, appends it to the given
912 * |message| and returns the resulting message string.
913 * @param {Array.<string>} a11yErrors The list of accessibility error messages
914 * @param {Array.<string>} a11yWarnings The list of accessibility warning
915 * messages.
916 * @return {string} |message| + accessibility report.
917 */
918 function accessibilityAuditReport(a11yErrors, a11yWarnings, message) {
919 message = message ? message + '\n' : '';
920 message += '\n*** Begin accessibility audit results ***';
921 message += '\nAn accessibility audit found ';
922
923 if (a11yErrors.length > 0) {
924 message += a11yErrors.length +
925 (a11yErrors.length == 1 ? ' error ' : ' errors ');
926 if (a11yWarnings.length > 0)
927 message += 'and ';
928 }
929 if (a11yWarnings.length > 0) {
930 message += a11yWarnings.length +
931 (a11yWarnings.length == 1 ? ' warning ' : ' warnings ');
932 }
933 message += 'on this page.\n';
934 message += 'For more information, please see ' +
935 'http://chromium.org/developers/accessibility/webui-accessibility-audit';
936
937 for (var i = 0; i < a11yErrors.length; i++)
938 message += '\n\n' + a11yErrors[i];
939
940 for (var i = 0; i < a11yWarnings.length; i++)
941 message += '\n\n' + a11yWarnings[i];
942 message += '\n*** End accessibility audit results ***';
943 return message;
944 }
945
946 /**
947 * Creates an error message for a given accessibility audit rule and
948 * corresponding result.
949 * @param {axs.AuditRule} rule The audit rule which the result is for
950 * @param {Object.<string, (string|Array.<Element>)>} result The result
951 * object returned from the audit.
952 * @return {string} An error message describing the failure and listing
953 * up to five elements which failed the audit rule.
954 */
955 function accessibilityErrorMessage(rule, result) {
956 if (rule.severity == axs.constants.Severity.Severe)
957 var message = 'Error: '
958 else
959 var message = 'Warning: '
960 message += rule.name + ' failed on the following ' +
961 (result.elements.length == 1 ? 'element' : 'elements');
962
963 if (result.elements.length == 1)
964 message += ':'
965 else {
966 message += ' (1 - ' + Math.min(5, result.elements.length) +
967 ' of ' + result.elements.length + '):';
968 }
969
970 var maxElements = Math.min(result.elements.length, 5);
971 for (var i = 0; i < maxElements; i++)
972 message += '\n' + axs.utils.getQuerySelectorText(result.elements[i]);
973 return message;
974 }
975
976 /**
977 * Asserts that the current page state passes the accessibility audit.
978 */
979 function assertAccessibilityOk() {
980 helper.registerCall();
981 var a11yErrors = [];
982 var a11yWarnings = [];
983 if (!runAccessibilityAudit(a11yErrors, a11yWarnings))
984 throw new Error(accessibilityAuditReport(a11yErrors, a11yWarnings));
985 }
986
987 /**
796 * Creates a function based upon a function that thows an exception on 988 * Creates a function based upon a function that thows an exception on
797 * failure. The new function stuffs any errors into the |errors| array for 989 * failure. The new function stuffs any errors into the |errors| array for
798 * checking by runTest. This allows tests to continue running other checks, 990 * checking by runTest. This allows tests to continue running other checks,
799 * while failing the overall test if any errors occurrred. 991 * while failing the overall test if any errors occurrred.
800 * @param {Function} assertFunc The function which may throw an Error. 992 * @param {Function} assertFunc The function which may throw an Error.
801 * @return {function(...*):bool} A function that applies its arguments to 993 * @return {function(...*):bool} A function that applies its arguments to
802 * |assertFunc| and returns true if |assertFunc| passes. 994 * |assertFunc| and returns true if |assertFunc| passes.
803 * @see errors 995 * @see errors
804 * @see runTestFunction 996 * @see runTestFunction
805 */ 997 */
(...skipping 564 matching lines...) Expand 10 before | Expand all | Expand 10 after
1370 exports.testDone = testDone; 1562 exports.testDone = testDone;
1371 exports.assertTrue = assertTrue; 1563 exports.assertTrue = assertTrue;
1372 exports.assertFalse = assertFalse; 1564 exports.assertFalse = assertFalse;
1373 exports.assertGE = assertGE; 1565 exports.assertGE = assertGE;
1374 exports.assertGT = assertGT; 1566 exports.assertGT = assertGT;
1375 exports.assertEquals = assertEquals; 1567 exports.assertEquals = assertEquals;
1376 exports.assertLE = assertLE; 1568 exports.assertLE = assertLE;
1377 exports.assertLT = assertLT; 1569 exports.assertLT = assertLT;
1378 exports.assertNotEquals = assertNotEquals; 1570 exports.assertNotEquals = assertNotEquals;
1379 exports.assertNotReached = assertNotReached; 1571 exports.assertNotReached = assertNotReached;
1572 exports.assertAccessibilityOk = assertAccessibilityOk;
1380 exports.callFunction = callFunction; 1573 exports.callFunction = callFunction;
1381 exports.callFunctionWithSavedArgs = callFunctionWithSavedArgs; 1574 exports.callFunctionWithSavedArgs = callFunctionWithSavedArgs;
1382 exports.callGlobalWithSavedArgs = callGlobalWithSavedArgs; 1575 exports.callGlobalWithSavedArgs = callGlobalWithSavedArgs;
1383 exports.expectTrue = createExpect(assertTrue); 1576 exports.expectTrue = createExpect(assertTrue);
1384 exports.expectFalse = createExpect(assertFalse); 1577 exports.expectFalse = createExpect(assertFalse);
1385 exports.expectGE = createExpect(assertGE); 1578 exports.expectGE = createExpect(assertGE);
1386 exports.expectGT = createExpect(assertGT); 1579 exports.expectGT = createExpect(assertGT);
1387 exports.expectEquals = createExpect(assertEquals); 1580 exports.expectEquals = createExpect(assertEquals);
1388 exports.expectLE = createExpect(assertLE); 1581 exports.expectLE = createExpect(assertLE);
1389 exports.expectLT = createExpect(assertLT); 1582 exports.expectLT = createExpect(assertLT);
1390 exports.expectNotEquals = createExpect(assertNotEquals); 1583 exports.expectNotEquals = createExpect(assertNotEquals);
1391 exports.expectNotReached = createExpect(assertNotReached); 1584 exports.expectNotReached = createExpect(assertNotReached);
1585 exports.expectAccessibilityOk = createExpect(assertAccessibilityOk);
1392 exports.preloadJavascriptLibraries = preloadJavascriptLibraries; 1586 exports.preloadJavascriptLibraries = preloadJavascriptLibraries;
1393 exports.registerMessageCallback = registerMessageCallback; 1587 exports.registerMessageCallback = registerMessageCallback;
1394 exports.registerMockGlobals = registerMockGlobals; 1588 exports.registerMockGlobals = registerMockGlobals;
1395 exports.registerMockMessageCallbacks = registerMockMessageCallbacks; 1589 exports.registerMockMessageCallbacks = registerMockMessageCallbacks;
1396 exports.resetTestState = resetTestState; 1590 exports.resetTestState = resetTestState;
1591 exports.runAccessibilityAudit = runAccessibilityAudit;
1397 exports.runAllActions = runAllActions; 1592 exports.runAllActions = runAllActions;
1398 exports.runAllActionsAsync = runAllActionsAsync; 1593 exports.runAllActionsAsync = runAllActionsAsync;
1399 exports.runTest = runTest; 1594 exports.runTest = runTest;
1400 exports.runTestFunction = runTestFunction; 1595 exports.runTestFunction = runTestFunction;
1401 exports.SaveMockArguments = SaveMockArguments; 1596 exports.SaveMockArguments = SaveMockArguments;
1402 exports.DUMMY_URL = DUMMY_URL; 1597 exports.DUMMY_URL = DUMMY_URL;
1403 exports.TEST = TEST; 1598 exports.TEST = TEST;
1404 exports.TEST_F = TEST_F; 1599 exports.TEST_F = TEST_F;
1600 exports.RUNTIME_TEST_F = TEST_F;
1405 exports.GEN = GEN; 1601 exports.GEN = GEN;
1406 exports.GEN_INCLUDE = GEN_INCLUDE; 1602 exports.GEN_INCLUDE = GEN_INCLUDE;
1407 exports.WhenTestDone = WhenTestDone; 1603 exports.WhenTestDone = WhenTestDone;
1408 1604
1409 // Import the Mock4JS helpers. 1605 // Import the Mock4JS helpers.
1410 Mock4JS.addMockSupport(exports); 1606 Mock4JS.addMockSupport(exports);
1411 })(this); 1607 })(this);
OLDNEW
« no previous file with comments | « chrome/test/data/webui/accessibility_audit_browsertest.js ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698