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

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: Doing accessibility check in javascript, with flags for whether to run a11y checks and whether to t… Created 8 years 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
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 103 matching lines...) Expand 10 before | Expand all | Expand 10 after
114 * @type {boolean} 114 * @type {boolean}
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 runA11yChecks : true,
125
126 /**
127 * FIXME(aboxhall)
128 */
129 a11yIssuesAreErrors: true,
130
124 /** 131 /**
125 * Create a new class to handle |messageNames|, assign it to 132 * Create a new class to handle |messageNames|, assign it to
126 * |this.mockHandler|, register its messages and return it. 133 * |this.mockHandler|, register its messages and return it.
127 * @return {Mock} Mock handler class assigned to |this.mockHandler|. 134 * @return {Mock} Mock handler class assigned to |this.mockHandler|.
128 */ 135 */
129 makeAndRegisterMockHandler: function(messageNames) { 136 makeAndRegisterMockHandler: function(messageNames) {
130 var MockClass = makeMockClass(messageNames); 137 var MockClass = makeMockClass(messageNames);
131 this.mockHandler = mock(MockClass); 138 this.mockHandler = mock(MockClass);
132 registerMockMessageCallbacks(this.mockHandler, MockClass); 139 registerMockMessageCallbacks(this.mockHandler, MockClass);
133 return this.mockHandler; 140 return this.mockHandler;
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after
227 * This class is not exported and is available to hold the state of the 234 * This class is not exported and is available to hold the state of the
228 * |currentTestCase| throughout preload and test run. 235 * |currentTestCase| throughout preload and test run.
229 * @param {string} name The name of the test case. 236 * @param {string} name The name of the test case.
230 * @param {Test} fixture The fixture object for this test case. 237 * @param {Test} fixture The fixture object for this test case.
231 * @param {Function} body The code to run for the test. 238 * @param {Function} body The code to run for the test.
232 * @constructor 239 * @constructor
233 */ 240 */
234 function TestCase(name, fixture, body) { 241 function TestCase(name, fixture, body) {
235 this.name = name; 242 this.name = name;
236 this.fixture = fixture; 243 this.fixture = fixture;
244 this.runA11yChecks = fixture.runA11yChecks;
245 this.a11yIssuesAreErrors = fixture.a11yIssuesAreErrors;
237 this.body = body; 246 this.body = body;
238 } 247 }
239 248
240 TestCase.prototype = { 249 TestCase.prototype = {
241 /** 250 /**
242 * The name of this test. 251 * The name of this test.
243 * @type {string} 252 * @type {string}
244 */ 253 */
245 name: null, 254 name: null,
246 255
247 /** 256 /**
248 * The test fixture to set |this| to when running the test |body|. 257 * The test fixture to set |this| to when running the test |body|.
249 * @type {testing.Test} 258 * @type {testing.Test}
250 */ 259 */
251 fixture: null, 260 fixture: null,
252 261
253 /** 262 /**
254 * The test body to execute in runTest(). 263 * The test body to execute in runTest().
255 * @type {Function} 264 * @type {Function}
256 */ 265 */
257 body: null, 266 body: null,
258 267
259 /** 268 /**
260 * True when the test fixture will run the test later. 269 * True when the test fixture will run the test later.
261 * @type {boolean} 270 * @type {boolean}
262 * @private 271 * @private
263 */ 272 */
264 deferred_: false, 273 deferred_: false,
265 274
275 runA11yChecks: true,
276
277 /**
278 * FIXME(aboxhall)
279 */
280 a11yIssuesAreErrors: true,
281
266 /** 282 /**
267 * Called at preload time, proxies to the fixture. 283 * Called at preload time, proxies to the fixture.
268 * @type {Function} 284 * @type {Function}
269 */ 285 */
270 preLoad: function(name) { 286 preLoad: function(name) {
271 if (this.fixture) 287 if (this.fixture)
272 this.fixture.preLoad(); 288 this.fixture.preLoad();
273 }, 289 },
274 290
275 /** 291 /**
(...skipping 302 matching lines...) Expand 10 before | Expand all | Expand 10 after
578 var testIsDone = false; 594 var testIsDone = false;
579 595
580 /** 596 /**
581 * Holds the errors, if any, caught by expects so that the test case can 597 * Holds the errors, if any, caught by expects so that the test case can
582 * fail. Cleared when results are reported from runTest() or testDone(). 598 * fail. Cleared when results are reported from runTest() or testDone().
583 * @type {Array.<Error>} 599 * @type {Array.<Error>}
584 */ 600 */
585 var errors = []; 601 var errors = [];
586 602
587 /** 603 /**
604 * Hold the accessibility warnings and errors, respectively.
605 * Like errors, cleared when results are reported.
606 */
607 var a11y_warnings = [];
608 var a11y_errors = [];
609
610 /**
588 * URL to dummy WebUI page for testing framework. 611 * URL to dummy WebUI page for testing framework.
589 * @type {string} 612 * @type {string}
590 */ 613 */
591 var DUMMY_URL = 'chrome://DummyURL'; 614 var DUMMY_URL = 'chrome://DummyURL';
592 615
593 /** 616 /**
594 * Resets test state by clearing |errors| and |testIsDone| flags. 617 * Resets test state by clearing |errors| and |testIsDone| flags.
595 */ 618 */
596 function resetTestState() { 619 function resetTestState() {
597 errors.splice(0, errors.length); 620 errors.splice(0, errors.length);
598 testIsDone = false; 621 testIsDone = false;
599 } 622 }
600 623
601 /** 624 /**
602 * Notifies the running browser test of the test results. Clears |errors|. 625 * Notifies the running browser test of the test results. Clears |errors|.
603 * @param {Array.<boolean, string>=} result When passed, this is used for the 626 * @param {Array.<boolean, string>=} result When passed, this is used for the
604 * testResult message. 627 * testResult message.
605 */ 628 */
606 function testDone(result) { 629 function testDone(result) {
607 if (!testIsDone) { 630 if (!testIsDone) {
608 testIsDone = true; 631 testIsDone = true;
609 if (currentTestCase) { 632 if (currentTestCase) {
633 if (currentTestCase.runA11yChecks &&
634 !runAccessibilityAudit_(a11y_errors, a11y_warnings)) {
635 if (currentTestCase.a11yIssuesAreErrors) {
636 if (!result)
637 result = testResult();
638 result = [false, accessibilityErrorsToMessage(a11y_errors,
639 a11y_warnings,
640 result[1])];
641 } else { /* a11yIssuesAreErrors */
642 console.warn(accessibilityErrorsToMessage(a11y_errors,
643 a11y_warnings));
644 }
645 }
646
610 try { 647 try {
611 currentTestCase.tearDown(); 648 currentTestCase.tearDown();
612 } catch (e) { 649 } catch (e) {
613 // Caught an exception in tearDown; Register the error and recreate 650 // Caught an exception in tearDown; Register the error and recreate
614 // the result if it is passed in. 651 // the result if it is passed in.
615 errors.push(e); 652 errors.push(e);
616 if (result) 653 if (result)
617 result = [false, errorsToMessage([e], result[1])]; 654 result = [false, errorsToMessage([e], result[1])];
618 } 655 }
619 currentTestCase = null; 656 currentTestCase = null;
620 } 657 }
621 chrome.send('testResult', result ? result : testResult()); 658 if (!result)
659 result = testResult();
660 chrome.send('testResult', result);
622 errors.splice(0, errors.length); 661 errors.splice(0, errors.length);
623 } else { 662 } else {
624 console.warn('testIsDone already'); 663 console.warn('testIsDone already');
625 } 664 }
626 } 665 }
627 666
628 /** 667 /**
629 * Converts each Error in |errors| to a suitable message, adding them to 668 * Converts each Error in |errors| to a suitable message, adding them to
630 * |message|, and returns the message string. 669 * |message|, and returns the message string.
631 * @param {Array.<Error>} errors Array of errors to add to |message|. 670 * @param {Array.<Error>} errors Array of errors to add to |message|.
(...skipping 13 matching lines...) Expand all
645 return message; 684 return message;
646 } 685 }
647 686
648 /** 687 /**
649 * Returns [success, message] & clears |errors|. 688 * Returns [success, message] & clears |errors|.
650 * @param {boolean} errorsOk When true, errors are ok. 689 * @param {boolean} errorsOk When true, errors are ok.
651 * @return {Array.<boolean, string>} 690 * @return {Array.<boolean, string>}
652 */ 691 */
653 function testResult(errorsOk) { 692 function testResult(errorsOk) {
654 var result = [true, '']; 693 var result = [true, ''];
655 if (errors.length) { 694 if (errors.length)
656 result = [!!errorsOk, errorsToMessage(errors)]; 695 result = [!!errorsOk, errorsToMessage(errors)];
657 } 696
658 return result; 697 return result;
659 } 698 }
660 699
661 // Asserts. 700 // Asserts.
662 // Use the following assertions to verify a condition within a test. 701 // Use the following assertions to verify a condition within a test.
663 // If assertion fails, throw an Error with information pertinent to the test. 702 // If assertion fails, throw an Error with information pertinent to the test.
664 703
665 /** 704 /**
666 * When |test| !== true, aborts the current test. 705 * When |test| !== true, aborts the current test.
667 * @param {boolean} test The predicate to check against |expected|. 706 * @param {boolean} test The predicate to check against |expected|.
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after
785 /** 824 /**
786 * Always aborts the current test. 825 * Always aborts the current test.
787 * @param {string=} message The message to include in the Error thrown. 826 * @param {string=} message The message to include in the Error thrown.
788 * @throws {Error} always. 827 * @throws {Error} always.
789 */ 828 */
790 function assertNotReached(message) { 829 function assertNotReached(message) {
791 helper.registerCall(); 830 helper.registerCall();
792 throw new Error(helper.getCallMessage(message)); 831 throw new Error(helper.getCallMessage(message));
793 } 832 }
794 833
834 function disableA11yChecks() {
835 if (!currentTestCase)
836 return;
837 currentTestCase.runA11yChecks = false;
838 }
839
840 function enableA11yChecks() {
841 if (!currentTestCase)
842 return;
843 currentTestCase.runA11yChecks = true;
844 }
845
846 function a11yIssuesAreErrors(flag) {
847 if (!currentTestCase)
848 return;
849 currentTestCase.a11yIssuesAreErrors = flag;
850 }
851
852 /**
853 * FIXME(aboxhall) documentation
854 */
855 function accessibilityErrorsToMessage(a11y_errors, a11y_warnings, message) {
856 if (message)
857 message += '\n';
858 else
859 message = '';
860
861 message += 'Accessibility ';
862 if (a11y_errors.length > 0) {
863 message += 'errors ';
864 if (a11y_warnings.length > 0)
865 message += 'and ';
866 }
867 if (a11y_warnings.length > 0)
868 message += 'warnings ';
869 message += 'found:';
870 for (var i = 0; i < a11y_errors.length; i++)
871 message += '\n' + a11y_errors[i];
872 for (var i = 0; i < a11y_warnings.length; i++)
873 message += '\n' + a11y_warnings[i];
874 return message;
875 }
876
877 /**
878 * FIXME(aboxhall): more distinct names for this and above function
879 * FIXME(aboxhall): documentation
880 */
881 function createAccessibilityIssueMessage(rule, result) {
882 if (rule.severity == axs.constants.Severity.Severe)
883 var message = 'Error: '
884 else
885 var message = 'Warning: '
886 message += rule.name + ' failed on the following elements:';
887 for (var i = 0; i < result.elements.length; i++)
888 message += '\n' + result.elements[i];
889 return message;
890 }
891
892 /**
893 * FIXME(aboxhall) documentation
894 */
895 function assertAccessibilityOk() {
896 helper.registerCall();
897 var a11y_errors = [];
898 var a11y_warnings = [];
899 if (!runAccessibilityAudit_(a11y_errors, a11y_warnings))
900 throw new Error(accessibilityErrorsToMessage(a11y_errors,
901 a11y_warnings));
902 }
903
904 /**
905 * Run an accessibility audit on the current page state.
906 * FIXME(aboxhall) documentation
907 * @type {Function}
908 * @return {boolean} Whether there were any errors or warnings
909 * @private
910 */
911 function runAccessibilityAudit_(a11yErrors, a11yWarnings) {
912 for (var auditRuleName in axs.AuditRule.specs) {
913 var auditRule = axs.AuditRules.getRule(auditRuleName);
914 if (!auditRule)
915 continue; // Shouldn't happen, but fail silently if it does.
916
917 if (auditRule.disabled || auditRule.requiresConsoleAPI)
918 continue;
919
920 var result = auditRule.run();
921 if (result.result == axs.constants.AuditResult.FAIL) {
922 // TODO(aboxhall): more useful error messages (sadly non-trivial)
923 if (auditRule.severity == axs.constants.Severity.Severe)
924 a11yErrors.push(createAccessibilityIssueMessage(auditRule, result));
925 else
926 a11yWarnings.push(createAccessibilityIssueMessage(auditRule, result));
927 }
928 }
929 // TODO(aboxhall): have strict (no errors or warnings) vs non-strict
930 // (warnings ok)
931 // TODO(aboxhall): some kind of info logging for warnings only??
932 return (a11yErrors.length == 0 && a11yWarnings.length == 0);
933 }
934
795 /** 935 /**
796 * Creates a function based upon a function that thows an exception on 936 * 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 937 * failure. The new function stuffs any errors into the |errors| array for
798 * checking by runTest. This allows tests to continue running other checks, 938 * checking by runTest. This allows tests to continue running other checks,
799 * while failing the overall test if any errors occurrred. 939 * while failing the overall test if any errors occurrred.
800 * @param {Function} assertFunc The function which may throw an Error. 940 * @param {Function} assertFunc The function which may throw an Error.
801 * @return {function(...*):bool} A function that applies its arguments to 941 * @return {function(...*):bool} A function that applies its arguments to
802 * |assertFunc| and returns true if |assertFunc| passes. 942 * |assertFunc| and returns true if |assertFunc| passes.
803 * @see errors 943 * @see errors
804 * @see runTestFunction 944 * @see runTestFunction
(...skipping 22 matching lines...) Expand all
827 * @param {boolean} isAsync When false, call testDone() with the test result 967 * @param {boolean} isAsync When false, call testDone() with the test result
828 * otherwise only when assertions are caught. 968 * otherwise only when assertions are caught.
829 * @param {string} testFunction The function name to call. 969 * @param {string} testFunction The function name to call.
830 * @param {Array} testArguments The arguments to call |testFunction| with. 970 * @param {Array} testArguments The arguments to call |testFunction| with.
831 * @return {boolean} true always to signal successful execution (but not 971 * @return {boolean} true always to signal successful execution (but not
832 * necessarily successful results) of this test. 972 * necessarily successful results) of this test.
833 * @see errors 973 * @see errors
834 * @see runTestFunction 974 * @see runTestFunction
835 */ 975 */
836 function runTest(isAsync, testFunction, testArguments) { 976 function runTest(isAsync, testFunction, testArguments) {
977 // FIXME(aboxhall): modify to add a11y phase
837 // Avoid eval() if at all possible, since it will not work on pages 978 // Avoid eval() if at all possible, since it will not work on pages
838 // that have enabled content-security-policy. 979 // that have enabled content-security-policy.
839 var testBody = this[testFunction]; // global object -- not a method. 980 var testBody = this[testFunction]; // global object -- not a method.
840 var testName = testFunction; 981 var testName = testFunction;
841 if (typeof testBody === "undefined") { 982 if (typeof testBody === "undefined") {
842 testBody = eval(testFunction); 983 testBody = eval(testFunction);
843 testName = testBody.toString(); 984 testName = testBody.toString();
844 } 985 }
845 if (testBody != RUN_TEST_F) { 986 if (testBody != RUN_TEST_F) {
846 console.log('Running test ' + testName); 987 console.log('Running test ' + testName);
(...skipping 523 matching lines...) Expand 10 before | Expand all | Expand 10 after
1370 exports.testDone = testDone; 1511 exports.testDone = testDone;
1371 exports.assertTrue = assertTrue; 1512 exports.assertTrue = assertTrue;
1372 exports.assertFalse = assertFalse; 1513 exports.assertFalse = assertFalse;
1373 exports.assertGE = assertGE; 1514 exports.assertGE = assertGE;
1374 exports.assertGT = assertGT; 1515 exports.assertGT = assertGT;
1375 exports.assertEquals = assertEquals; 1516 exports.assertEquals = assertEquals;
1376 exports.assertLE = assertLE; 1517 exports.assertLE = assertLE;
1377 exports.assertLT = assertLT; 1518 exports.assertLT = assertLT;
1378 exports.assertNotEquals = assertNotEquals; 1519 exports.assertNotEquals = assertNotEquals;
1379 exports.assertNotReached = assertNotReached; 1520 exports.assertNotReached = assertNotReached;
1521 exports.assertAccessibilityOk = assertAccessibilityOk;
1380 exports.callFunction = callFunction; 1522 exports.callFunction = callFunction;
1381 exports.callFunctionWithSavedArgs = callFunctionWithSavedArgs; 1523 exports.callFunctionWithSavedArgs = callFunctionWithSavedArgs;
1382 exports.callGlobalWithSavedArgs = callGlobalWithSavedArgs; 1524 exports.callGlobalWithSavedArgs = callGlobalWithSavedArgs;
1525 exports.disableA11yChecks = disableA11yChecks;
1526 exports.enableA11yChecks = enableA11yChecks;
1383 exports.expectTrue = createExpect(assertTrue); 1527 exports.expectTrue = createExpect(assertTrue);
1384 exports.expectFalse = createExpect(assertFalse); 1528 exports.expectFalse = createExpect(assertFalse);
1385 exports.expectGE = createExpect(assertGE); 1529 exports.expectGE = createExpect(assertGE);
1386 exports.expectGT = createExpect(assertGT); 1530 exports.expectGT = createExpect(assertGT);
1387 exports.expectEquals = createExpect(assertEquals); 1531 exports.expectEquals = createExpect(assertEquals);
1388 exports.expectLE = createExpect(assertLE); 1532 exports.expectLE = createExpect(assertLE);
1389 exports.expectLT = createExpect(assertLT); 1533 exports.expectLT = createExpect(assertLT);
1390 exports.expectNotEquals = createExpect(assertNotEquals); 1534 exports.expectNotEquals = createExpect(assertNotEquals);
1391 exports.expectNotReached = createExpect(assertNotReached); 1535 exports.expectNotReached = createExpect(assertNotReached);
1536 exports.expectAccessibilityOk = createExpect(assertAccessibilityOk);
1392 exports.preloadJavascriptLibraries = preloadJavascriptLibraries; 1537 exports.preloadJavascriptLibraries = preloadJavascriptLibraries;
1393 exports.registerMessageCallback = registerMessageCallback; 1538 exports.registerMessageCallback = registerMessageCallback;
1394 exports.registerMockGlobals = registerMockGlobals; 1539 exports.registerMockGlobals = registerMockGlobals;
1395 exports.registerMockMessageCallbacks = registerMockMessageCallbacks; 1540 exports.registerMockMessageCallbacks = registerMockMessageCallbacks;
1396 exports.resetTestState = resetTestState; 1541 exports.resetTestState = resetTestState;
1397 exports.runAllActions = runAllActions; 1542 exports.runAllActions = runAllActions;
1398 exports.runAllActionsAsync = runAllActionsAsync; 1543 exports.runAllActionsAsync = runAllActionsAsync;
1399 exports.runTest = runTest; 1544 exports.runTest = runTest;
1400 exports.runTestFunction = runTestFunction; 1545 exports.runTestFunction = runTestFunction;
1401 exports.SaveMockArguments = SaveMockArguments; 1546 exports.SaveMockArguments = SaveMockArguments;
1402 exports.DUMMY_URL = DUMMY_URL; 1547 exports.DUMMY_URL = DUMMY_URL;
1403 exports.TEST = TEST; 1548 exports.TEST = TEST;
1404 exports.TEST_F = TEST_F; 1549 exports.TEST_F = TEST_F;
1405 exports.GEN = GEN; 1550 exports.GEN = GEN;
1406 exports.GEN_INCLUDE = GEN_INCLUDE; 1551 exports.GEN_INCLUDE = GEN_INCLUDE;
1407 exports.WhenTestDone = WhenTestDone; 1552 exports.WhenTestDone = WhenTestDone;
1408 1553
1409 // Import the Mock4JS helpers. 1554 // Import the Mock4JS helpers.
1410 Mock4JS.addMockSupport(exports); 1555 Mock4JS.addMockSupport(exports);
1411 })(this); 1556 })(this);
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698