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 * 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 Loading... | |
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 { | |
James Hawkins
2013/01/03 21:23:39
nit: No braces for single-line blocks.
aboxhall
2013/01/04 00:26:50
Done.
| |
254 console.warn(report); | |
255 } | |
256 } | |
257 }, | |
258 | |
259 /** | |
181 * Create a closure function for continuing the test at a later time. May be | 260 * Create a closure function for continuing the test at a later time. May be |
182 * used as a listener function. | 261 * used as a listener function. |
183 * @param {WhenTestDone} whenTestDone Call testDone() at the appropriate | 262 * @param {WhenTestDone} whenTestDone Call testDone() at the appropriate |
184 * time. | 263 * time. |
185 * @param {Function} completion The function to call to complete the test. | 264 * @param {Function} completion The function to call to complete the test. |
186 * @param {...*} var_args Arguments to pass when calling completionAction. | 265 * @param {...*} var_args Arguments to pass when calling completionAction. |
187 * @return {function(): void} Return a function, bound to this test fixture, | 266 * @return {function(): void} Return a function, bound to this test fixture, |
188 * which continues the test. | 267 * which continues the test. |
189 */ | 268 */ |
190 continueTest: function(whenTestDone, completion) { | 269 continueTest: function(whenTestDone, completion) { |
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
290 | 369 |
291 /** | 370 /** |
292 * Called to run this test's body. | 371 * Called to run this test's body. |
293 */ | 372 */ |
294 runTest: function() { | 373 runTest: function() { |
295 if (this.body && this.fixture) | 374 if (this.body && this.fixture) |
296 this.fixture.runTest(this.body); | 375 this.fixture.runTest(this.body); |
297 }, | 376 }, |
298 | 377 |
299 /** | 378 /** |
379 * Called after a test is run (in testDone) to test accessibility. | |
380 */ | |
381 runAccessibilityAudit: function() { | |
382 if (this.fixture) | |
383 this.fixture.runAccessibilityAudit(); | |
384 }, | |
385 | |
386 /** | |
300 * Runs this test case with |this| set to the |fixture|. | 387 * Runs this test case with |this| set to the |fixture|. |
301 * | 388 * |
302 * Note: Tests created with TEST_F may depend upon |this| being set to an | 389 * 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 | 390 * instance of this.fixture. The current implementation of TEST creates a |
304 * dummy constructor, but tests created with TEST should not rely on |this| | 391 * dummy constructor, but tests created with TEST should not rely on |this| |
305 * being set. | 392 * being set. |
306 * @type {Function} | 393 * @type {Function} |
307 */ | 394 */ |
308 run: function() { | 395 run: function() { |
309 try { | 396 try { |
(...skipping 290 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
600 | 687 |
601 /** | 688 /** |
602 * Notifies the running browser test of the test results. Clears |errors|. | 689 * Notifies the running browser test of the test results. Clears |errors|. |
603 * @param {Array.<boolean, string>=} result When passed, this is used for the | 690 * @param {Array.<boolean, string>=} result When passed, this is used for the |
604 * testResult message. | 691 * testResult message. |
605 */ | 692 */ |
606 function testDone(result) { | 693 function testDone(result) { |
607 if (!testIsDone) { | 694 if (!testIsDone) { |
608 testIsDone = true; | 695 testIsDone = true; |
609 if (currentTestCase) { | 696 if (currentTestCase) { |
610 try { | 697 var ok = true; |
611 currentTestCase.tearDown(); | 698 ok = createExpect(currentTestCase.runAccessibilityAudit.bind( |
612 } catch (e) { | 699 currentTestCase)).call(null) && ok; |
613 // Caught an exception in tearDown; Register the error and recreate | 700 ok = createExpect(currentTestCase.tearDown.bind( |
614 // the result if it is passed in. | 701 currentTestCase)).call(null) && ok; |
615 errors.push(e); | 702 |
616 if (result) | 703 if (!ok && result) |
617 result = [false, errorsToMessage([e], result[1])]; | 704 result = [false, errorsToMessage(errors, result[1])]; |
618 } | 705 |
619 currentTestCase = null; | 706 currentTestCase = null; |
620 } | 707 } |
621 chrome.send('testResult', result ? result : testResult()); | 708 if (!result) |
709 result = testResult(); | |
710 chrome.send('testResult', result); | |
622 errors.splice(0, errors.length); | 711 errors.splice(0, errors.length); |
623 } else { | 712 } else { |
624 console.warn('testIsDone already'); | 713 console.warn('testIsDone already'); |
625 } | 714 } |
626 } | 715 } |
627 | 716 |
628 /** | 717 /** |
629 * Converts each Error in |errors| to a suitable message, adding them to | 718 * Converts each Error in |errors| to a suitable message, adding them to |
630 * |message|, and returns the message string. | 719 * |message|, and returns the message string. |
631 * @param {Array.<Error>} errors Array of errors to add to |message|. | 720 * @param {Array.<Error>} errors Array of errors to add to |message|. |
(...skipping 13 matching lines...) Expand all Loading... | |
645 return message; | 734 return message; |
646 } | 735 } |
647 | 736 |
648 /** | 737 /** |
649 * Returns [success, message] & clears |errors|. | 738 * Returns [success, message] & clears |errors|. |
650 * @param {boolean} errorsOk When true, errors are ok. | 739 * @param {boolean} errorsOk When true, errors are ok. |
651 * @return {Array.<boolean, string>} | 740 * @return {Array.<boolean, string>} |
652 */ | 741 */ |
653 function testResult(errorsOk) { | 742 function testResult(errorsOk) { |
654 var result = [true, '']; | 743 var result = [true, '']; |
655 if (errors.length) { | 744 if (errors.length) |
656 result = [!!errorsOk, errorsToMessage(errors)]; | 745 result = [!!errorsOk, errorsToMessage(errors)]; |
657 } | 746 |
658 return result; | 747 return result; |
659 } | 748 } |
660 | 749 |
661 // Asserts. | 750 // Asserts. |
662 // Use the following assertions to verify a condition within a test. | 751 // Use the following assertions to verify a condition within a test. |
663 // If assertion fails, throw an Error with information pertinent to the test. | 752 // If assertion fails, throw an Error with information pertinent to the test. |
664 | 753 |
665 /** | 754 /** |
666 * When |test| !== true, aborts the current test. | 755 * When |test| !== true, aborts the current test. |
667 * @param {boolean} test The predicate to check against |expected|. | 756 * @param {boolean} test The predicate to check against |expected|. |
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
786 * Always aborts the current test. | 875 * Always aborts the current test. |
787 * @param {string=} message The message to include in the Error thrown. | 876 * @param {string=} message The message to include in the Error thrown. |
788 * @throws {Error} always. | 877 * @throws {Error} always. |
789 */ | 878 */ |
790 function assertNotReached(message) { | 879 function assertNotReached(message) { |
791 helper.registerCall(); | 880 helper.registerCall(); |
792 throw new Error(helper.getCallMessage(message)); | 881 throw new Error(helper.getCallMessage(message)); |
793 } | 882 } |
794 | 883 |
795 /** | 884 /** |
885 * Run an accessibility audit on the current page state. | |
886 * @type {Function} | |
887 * @return {boolean} Whether there were any errors or warnings | |
888 * @private | |
889 */ | |
890 function runAccessibilityAudit(a11yErrors, a11yWarnings) { | |
891 var auditResults = axs.Audit.run(); | |
892 for (var i = 0; i < auditResults.length; i++) { | |
893 var auditResult = auditResults[i]; | |
894 if (auditResult.result == axs.constants.AuditResult.FAIL) { | |
895 var auditRule = auditResult.rule; | |
896 // TODO(aboxhall): more useful error messages (sadly non-trivial) | |
897 if (auditRule.severity == axs.constants.Severity.Severe) | |
898 a11yErrors.push(accessibilityErrorMessage(auditRule, auditResult)); | |
899 else | |
900 a11yWarnings.push(accessibilityErrorMessage(auditRule, auditResult)); | |
901 } | |
902 } | |
903 | |
904 // TODO(aboxhall): have strict (no errors or warnings) vs non-strict | |
905 // (warnings ok) | |
906 // TODO(aboxhall): some kind of info logging for warnings only?? | |
907 return (a11yErrors.length == 0 && a11yWarnings.length == 0); | |
908 } | |
909 | |
910 /** | |
911 * Concatenates the accessibility error messages in |a11yErrors| and | |
912 * |a11yWarnings| in to an accessibility report, appends it to the given | |
913 * |message| and returns the resulting message string. | |
914 * @param {Array.<string>} a11yErrors The list of accessibility error messages | |
915 * @param {Array.<string>} a11yWarnings The list of accessibility warning | |
916 * messages. | |
917 * @return {string} |message| + accessibility report. | |
918 */ | |
919 function accessibilityAuditReport(a11yErrors, a11yWarnings, message) { | |
920 message = message ? message + '\n' : ''; | |
921 message += '\n*** Begin accessibility audit results ***'; | |
922 message += '\nAn accessibility audit found '; | |
923 | |
924 if (a11yErrors.length > 0) { | |
925 message += a11yErrors.length + | |
926 (a11yErrors.length == 1 ? ' error ' : ' errors '); | |
927 if (a11yWarnings.length > 0) | |
928 message += 'and '; | |
929 } | |
930 if (a11yWarnings.length > 0) { | |
931 message += a11yWarnings.length + | |
932 (a11yWarnings.length == 1 ? ' warning ' : ' warnings '); | |
933 } | |
934 message += 'on this page.\n'; | |
935 message += 'For more information, please see ' + | |
936 'http://chromium.org/developers/accessibility/webui-accessibility-audit'; | |
937 | |
938 for (var i = 0; i < a11yErrors.length; i++) | |
939 message += '\n\n' + a11yErrors[i]; | |
940 | |
941 for (var i = 0; i < a11yWarnings.length; i++) | |
942 message += '\n\n' + a11yWarnings[i]; | |
943 message += '\n*** End accessibility audit results ***'; | |
944 return message; | |
945 } | |
946 | |
947 /** | |
948 * Creates an error message for a given accessibility audit rule and | |
949 * corresponding result. | |
950 * @param {axs.AuditRule} rule The audit rule which the result is for | |
951 * @param {Object.<string, (string|Array.<Element>)>} result The result | |
952 * object returned from the audit. | |
953 * @return {string} An error message describing the failure and listing | |
954 * up to five elements which failed the audit rule. | |
955 */ | |
956 function accessibilityErrorMessage(rule, result) { | |
957 if (rule.severity == axs.constants.Severity.Severe) | |
958 var message = 'Error: ' | |
959 else | |
960 var message = 'Warning: ' | |
961 message += rule.name + ' failed on the following ' + | |
962 (result.elements.length == 1 ? 'element' : 'elements'); | |
963 | |
964 if (result.elements.length == 1) | |
965 message += ':' | |
966 else | |
James Hawkins
2013/01/03 21:23:39
nit: Braces required for multi-line blocks.
aboxhall
2013/01/04 00:26:50
Done.
aboxhall
2013/01/04 00:26:50
Done.
| |
967 message += ' (1 - ' + Math.min(5, result.elements.length) + | |
968 ' of ' + result.elements.length + '):'; | |
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 Loading... | |
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); |
OLD | NEW |