OLD | NEW |
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 Loading... |
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 * FIXME(aboxhall) |
| 126 */ |
| 127 runA11yChecks: true, |
| 128 |
| 129 /** |
125 * Create a new class to handle |messageNames|, assign it to | 130 * Create a new class to handle |messageNames|, assign it to |
126 * |this.mockHandler|, register its messages and return it. | 131 * |this.mockHandler|, register its messages and return it. |
127 * @return {Mock} Mock handler class assigned to |this.mockHandler|. | 132 * @return {Mock} Mock handler class assigned to |this.mockHandler|. |
128 */ | 133 */ |
129 makeAndRegisterMockHandler: function(messageNames) { | 134 makeAndRegisterMockHandler: function(messageNames) { |
130 var MockClass = makeMockClass(messageNames); | 135 var MockClass = makeMockClass(messageNames); |
131 this.mockHandler = mock(MockClass); | 136 this.mockHandler = mock(MockClass); |
132 registerMockMessageCallbacks(this.mockHandler, MockClass); | 137 registerMockMessageCallbacks(this.mockHandler, MockClass); |
133 return this.mockHandler; | 138 return this.mockHandler; |
134 }, | 139 }, |
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
227 * This class is not exported and is available to hold the state of the | 232 * This class is not exported and is available to hold the state of the |
228 * |currentTestCase| throughout preload and test run. | 233 * |currentTestCase| throughout preload and test run. |
229 * @param {string} name The name of the test case. | 234 * @param {string} name The name of the test case. |
230 * @param {Test} fixture The fixture object for this test case. | 235 * @param {Test} fixture The fixture object for this test case. |
231 * @param {Function} body The code to run for the test. | 236 * @param {Function} body The code to run for the test. |
232 * @constructor | 237 * @constructor |
233 */ | 238 */ |
234 function TestCase(name, fixture, body) { | 239 function TestCase(name, fixture, body) { |
235 this.name = name; | 240 this.name = name; |
236 this.fixture = fixture; | 241 this.fixture = fixture; |
| 242 this.runA11yChecks = fixture.runA11yChecks; |
237 this.body = body; | 243 this.body = body; |
238 } | 244 } |
239 | 245 |
240 TestCase.prototype = { | 246 TestCase.prototype = { |
241 /** | 247 /** |
242 * The name of this test. | 248 * The name of this test. |
243 * @type {string} | 249 * @type {string} |
244 */ | 250 */ |
245 name: null, | 251 name: null, |
246 | 252 |
(...skipping 10 matching lines...) Expand all Loading... |
257 body: null, | 263 body: null, |
258 | 264 |
259 /** | 265 /** |
260 * True when the test fixture will run the test later. | 266 * True when the test fixture will run the test later. |
261 * @type {boolean} | 267 * @type {boolean} |
262 * @private | 268 * @private |
263 */ | 269 */ |
264 deferred_: false, | 270 deferred_: false, |
265 | 271 |
266 /** | 272 /** |
| 273 * FIXME(aboxhall) |
| 274 */ |
| 275 runA11yChecks: true, |
| 276 |
| 277 /** |
267 * Called at preload time, proxies to the fixture. | 278 * Called at preload time, proxies to the fixture. |
268 * @type {Function} | 279 * @type {Function} |
269 */ | 280 */ |
270 preLoad: function(name) { | 281 preLoad: function(name) { |
271 if (this.fixture) | 282 if (this.fixture) |
272 this.fixture.preLoad(); | 283 this.fixture.preLoad(); |
273 }, | 284 }, |
274 | 285 |
275 /** | 286 /** |
276 * Called before a test runs. | 287 * Called before a test runs. |
(...skipping 301 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
578 var testIsDone = false; | 589 var testIsDone = false; |
579 | 590 |
580 /** | 591 /** |
581 * Holds the errors, if any, caught by expects so that the test case can | 592 * 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(). | 593 * fail. Cleared when results are reported from runTest() or testDone(). |
583 * @type {Array.<Error>} | 594 * @type {Array.<Error>} |
584 */ | 595 */ |
585 var errors = []; | 596 var errors = []; |
586 | 597 |
587 /** | 598 /** |
| 599 * Hold the accessibility warnings and errors, respectively. |
| 600 * Like errors, cleared when results are reported. |
| 601 */ |
| 602 var a11y_warnings = []; |
| 603 var a11y_errors = []; |
| 604 |
| 605 /** |
588 * URL to dummy WebUI page for testing framework. | 606 * URL to dummy WebUI page for testing framework. |
589 * @type {string} | 607 * @type {string} |
590 */ | 608 */ |
591 var DUMMY_URL = 'chrome://DummyURL'; | 609 var DUMMY_URL = 'chrome://DummyURL'; |
592 | 610 |
593 /** | 611 /** |
594 * Resets test state by clearing |errors| and |testIsDone| flags. | 612 * Resets test state by clearing |errors| and |testIsDone| flags. |
595 */ | 613 */ |
596 function resetTestState() { | 614 function resetTestState() { |
597 errors.splice(0, errors.length); | 615 errors.splice(0, errors.length); |
598 testIsDone = false; | 616 testIsDone = false; |
599 } | 617 } |
600 | 618 |
601 /** | 619 /** |
602 * Notifies the running browser test of the test results. Clears |errors|. | 620 * Notifies the running browser test of the test results. Clears |errors|. |
603 * @param {Array.<boolean, string>=} result When passed, this is used for the | 621 * @param {Array.<boolean, string>=} result When passed, this is used for the |
604 * testResult message. | 622 * testResult message. |
605 */ | 623 */ |
606 function testDone(result) { | 624 function testDone(result) { |
607 if (!testIsDone) { | 625 if (!testIsDone) { |
| 626 // FIXME(aboxhall): run a11y check if not disabled; combine with result. |
| 627 var accessibilityOk = runAccessibilityAudit_(a11y_errors, a11y_warnings); |
| 628 |
608 testIsDone = true; | 629 testIsDone = true; |
609 if (currentTestCase) { | 630 if (currentTestCase) { |
610 try { | 631 try { |
611 currentTestCase.tearDown(); | 632 currentTestCase.tearDown(); |
612 } catch (e) { | 633 } catch (e) { |
613 // Caught an exception in tearDown; Register the error and recreate | 634 // Caught an exception in tearDown; Register the error and recreate |
614 // the result if it is passed in. | 635 // the result if it is passed in. |
615 errors.push(e); | 636 errors.push(e); |
616 if (result) | 637 if (result) |
617 result = [false, errorsToMessage([e], result[1])]; | 638 result = [false, errorsToMessage([e], result[1])]; |
618 } | 639 } |
619 currentTestCase = null; | 640 currentTestCase = null; |
620 } | 641 } |
621 chrome.send('testResult', result ? result : testResult()); | 642 if (!result) |
| 643 result = testResult(); |
| 644 if (!accessibilityOk) |
| 645 result.push(createAccessibilityErrorMessage(a11y_errors, |
| 646 a11y_warnings)); |
| 647 chrome.send('testResult', result); |
622 errors.splice(0, errors.length); | 648 errors.splice(0, errors.length); |
623 } else { | 649 } else { |
624 console.warn('testIsDone already'); | 650 console.warn('testIsDone already'); |
625 } | 651 } |
626 } | 652 } |
627 | 653 |
628 /** | 654 /** |
629 * Converts each Error in |errors| to a suitable message, adding them to | 655 * Converts each Error in |errors| to a suitable message, adding them to |
630 * |message|, and returns the message string. | 656 * |message|, and returns the message string. |
631 * @param {Array.<Error>} errors Array of errors to add to |message|. | 657 * @param {Array.<Error>} errors Array of errors to add to |message|. |
(...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
786 * Always aborts the current test. | 812 * Always aborts the current test. |
787 * @param {string=} message The message to include in the Error thrown. | 813 * @param {string=} message The message to include in the Error thrown. |
788 * @throws {Error} always. | 814 * @throws {Error} always. |
789 */ | 815 */ |
790 function assertNotReached(message) { | 816 function assertNotReached(message) { |
791 helper.registerCall(); | 817 helper.registerCall(); |
792 throw new Error(helper.getCallMessage(message)); | 818 throw new Error(helper.getCallMessage(message)); |
793 } | 819 } |
794 | 820 |
795 /** | 821 /** |
| 822 * FIXME(aboxhall) documentation |
| 823 */ |
| 824 function createAccessibilityErrorMessage(a11y_errors, a11y_warnings) { |
| 825 var errorMessage = 'Accessibility '; |
| 826 if (a11y_errors.length > 0) |
| 827 errorMessage += 'Errors '; |
| 828 else |
| 829 errorMessage += 'Warnings '; |
| 830 errorMessage += 'found:\n'; |
| 831 for (var i = 0; i < a11y_errors.length; i++) |
| 832 errorMessage += 'Error: ' + a11y_errors[i] + '\n'; |
| 833 for (var i = 0; i < a11y_warnings.length; i++) |
| 834 errorMessage += 'Warning: ' + a11y_warnings[i] + '\n'; |
| 835 return errorMessage; |
| 836 } |
| 837 |
| 838 /** |
| 839 * FIXME(aboxhall) documentation |
| 840 */ |
| 841 function assertAccessibilityOk() { |
| 842 helper.registerCall(); |
| 843 var a11y_errors = []; |
| 844 var a11y_warnings = []; |
| 845 if (!runAccessibilityAudit_(a11y_errors, a11y_warnings)) |
| 846 throw new Error(createAccessibilityErrorMessage(a11y_errors, |
| 847 a11y_warnings)); |
| 848 } |
| 849 |
| 850 /** |
| 851 * Run an accessibility audit on the current page state. |
| 852 * FIXME(aboxhall) documentation |
| 853 * @type {Function} |
| 854 * @return {boolean} Whether there were any errors or warnings |
| 855 * @private |
| 856 */ |
| 857 function runAccessibilityAudit_(errors, warnings) { |
| 858 for (var auditRuleName in axs.AuditRule.specs) { |
| 859 var auditRule = axs.AuditRules.getRule(auditRuleName); |
| 860 if (!auditRule) |
| 861 continue; // Shouldn't happen, but fail silently if it does. |
| 862 if (!auditRule.disabled && !auditRule.requiresConsoleAPI) { |
| 863 var result = auditRule.run(); |
| 864 if (result.result == axs.constants.AuditResult.FAIL) { |
| 865 // TODO(aboxhall): more useful error messages (sadly non-trivial) |
| 866 if (auditRule.severity == axs.constants.Severity.Severe) |
| 867 errors.push("Accessibility audit rule " + auditRule.name + |
| 868 " failed"); |
| 869 else |
| 870 warnings.push("Accessibility audit rule " + auditRule.name + |
| 871 " failed"); |
| 872 } |
| 873 } |
| 874 } |
| 875 // TODO(aboxhall): have strict (no errors or warnings) vs non-strict |
| 876 // (warnings ok) |
| 877 // TODO(aboxhall): some kind of info logging for warnings only?? |
| 878 return (errors.length == 0 && warnings.length == 0); |
| 879 } |
| 880 |
| 881 /** |
796 * Creates a function based upon a function that thows an exception on | 882 * 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 | 883 * failure. The new function stuffs any errors into the |errors| array for |
798 * checking by runTest. This allows tests to continue running other checks, | 884 * checking by runTest. This allows tests to continue running other checks, |
799 * while failing the overall test if any errors occurrred. | 885 * while failing the overall test if any errors occurrred. |
800 * @param {Function} assertFunc The function which may throw an Error. | 886 * @param {Function} assertFunc The function which may throw an Error. |
801 * @return {function(...*):bool} A function that applies its arguments to | 887 * @return {function(...*):bool} A function that applies its arguments to |
802 * |assertFunc| and returns true if |assertFunc| passes. | 888 * |assertFunc| and returns true if |assertFunc| passes. |
803 * @see errors | 889 * @see errors |
804 * @see runTestFunction | 890 * @see runTestFunction |
805 */ | 891 */ |
(...skipping 21 matching lines...) Expand all Loading... |
827 * @param {boolean} isAsync When false, call testDone() with the test result | 913 * @param {boolean} isAsync When false, call testDone() with the test result |
828 * otherwise only when assertions are caught. | 914 * otherwise only when assertions are caught. |
829 * @param {string} testFunction The function name to call. | 915 * @param {string} testFunction The function name to call. |
830 * @param {Array} testArguments The arguments to call |testFunction| with. | 916 * @param {Array} testArguments The arguments to call |testFunction| with. |
831 * @return {boolean} true always to signal successful execution (but not | 917 * @return {boolean} true always to signal successful execution (but not |
832 * necessarily successful results) of this test. | 918 * necessarily successful results) of this test. |
833 * @see errors | 919 * @see errors |
834 * @see runTestFunction | 920 * @see runTestFunction |
835 */ | 921 */ |
836 function runTest(isAsync, testFunction, testArguments) { | 922 function runTest(isAsync, testFunction, testArguments) { |
| 923 // FIXME(aboxhall): modify to add a11y phase |
837 // Avoid eval() if at all possible, since it will not work on pages | 924 // Avoid eval() if at all possible, since it will not work on pages |
838 // that have enabled content-security-policy. | 925 // that have enabled content-security-policy. |
839 var testBody = this[testFunction]; // global object -- not a method. | 926 var testBody = this[testFunction]; // global object -- not a method. |
840 var testName = testFunction; | 927 var testName = testFunction; |
841 if (typeof testBody === "undefined") { | 928 if (typeof testBody === "undefined") { |
842 testBody = eval(testFunction); | 929 testBody = eval(testFunction); |
843 testName = testBody.toString(); | 930 testName = testBody.toString(); |
844 } | 931 } |
845 if (testBody != RUN_TEST_F) { | 932 if (testBody != RUN_TEST_F) { |
846 console.log('Running test ' + testName); | 933 console.log('Running test ' + testName); |
(...skipping 535 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1382 exports.callGlobalWithSavedArgs = callGlobalWithSavedArgs; | 1469 exports.callGlobalWithSavedArgs = callGlobalWithSavedArgs; |
1383 exports.expectTrue = createExpect(assertTrue); | 1470 exports.expectTrue = createExpect(assertTrue); |
1384 exports.expectFalse = createExpect(assertFalse); | 1471 exports.expectFalse = createExpect(assertFalse); |
1385 exports.expectGE = createExpect(assertGE); | 1472 exports.expectGE = createExpect(assertGE); |
1386 exports.expectGT = createExpect(assertGT); | 1473 exports.expectGT = createExpect(assertGT); |
1387 exports.expectEquals = createExpect(assertEquals); | 1474 exports.expectEquals = createExpect(assertEquals); |
1388 exports.expectLE = createExpect(assertLE); | 1475 exports.expectLE = createExpect(assertLE); |
1389 exports.expectLT = createExpect(assertLT); | 1476 exports.expectLT = createExpect(assertLT); |
1390 exports.expectNotEquals = createExpect(assertNotEquals); | 1477 exports.expectNotEquals = createExpect(assertNotEquals); |
1391 exports.expectNotReached = createExpect(assertNotReached); | 1478 exports.expectNotReached = createExpect(assertNotReached); |
| 1479 exports.expectAccessibilityOk = createExpect(assertAccessibilityOk); |
1392 exports.preloadJavascriptLibraries = preloadJavascriptLibraries; | 1480 exports.preloadJavascriptLibraries = preloadJavascriptLibraries; |
1393 exports.registerMessageCallback = registerMessageCallback; | 1481 exports.registerMessageCallback = registerMessageCallback; |
1394 exports.registerMockGlobals = registerMockGlobals; | 1482 exports.registerMockGlobals = registerMockGlobals; |
1395 exports.registerMockMessageCallbacks = registerMockMessageCallbacks; | 1483 exports.registerMockMessageCallbacks = registerMockMessageCallbacks; |
1396 exports.resetTestState = resetTestState; | 1484 exports.resetTestState = resetTestState; |
1397 exports.runAllActions = runAllActions; | 1485 exports.runAllActions = runAllActions; |
1398 exports.runAllActionsAsync = runAllActionsAsync; | 1486 exports.runAllActionsAsync = runAllActionsAsync; |
1399 exports.runTest = runTest; | 1487 exports.runTest = runTest; |
1400 exports.runTestFunction = runTestFunction; | 1488 exports.runTestFunction = runTestFunction; |
1401 exports.SaveMockArguments = SaveMockArguments; | 1489 exports.SaveMockArguments = SaveMockArguments; |
1402 exports.DUMMY_URL = DUMMY_URL; | 1490 exports.DUMMY_URL = DUMMY_URL; |
1403 exports.TEST = TEST; | 1491 exports.TEST = TEST; |
1404 exports.TEST_F = TEST_F; | 1492 exports.TEST_F = TEST_F; |
1405 exports.GEN = GEN; | 1493 exports.GEN = GEN; |
1406 exports.GEN_INCLUDE = GEN_INCLUDE; | 1494 exports.GEN_INCLUDE = GEN_INCLUDE; |
1407 exports.WhenTestDone = WhenTestDone; | 1495 exports.WhenTestDone = WhenTestDone; |
1408 | 1496 |
1409 // Import the Mock4JS helpers. | 1497 // Import the Mock4JS helpers. |
1410 Mock4JS.addMockSupport(exports); | 1498 Mock4JS.addMockSupport(exports); |
1411 })(this); | 1499 })(this); |
OLD | NEW |