OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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|. |
11 * @type {Object} | 11 * @type {Object} |
12 */ | 12 */ |
13 var testing = {}; | 13 var testing = {}; |
14 (function(exports) { | 14 (function(exports) { |
15 /** | 15 /** |
16 * Holds the original version of the |chrome| object. | |
17 */ | |
18 var originalChrome = null; | |
19 | |
20 /** | |
21 * Hold the currentTestCase across between preLoad and run. | 16 * Hold the currentTestCase across between preLoad and run. |
22 * @type {TestCase} | 17 * @type {TestCase} |
23 */ | 18 */ |
24 var currentTestCase = null; | 19 var currentTestCase = null; |
25 | 20 |
26 /** | 21 /** |
27 * The string representation of the currently running test function. | 22 * The string representation of the currently running test function. |
28 * @type {?string} | 23 * @type {?string} |
29 */ | 24 */ |
30 var currentTestFunction = null; | 25 var currentTestFunction = null; |
(...skipping 305 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
336 sendCallbacks[name] = [messageHandler, callback]; | 331 sendCallbacks[name] = [messageHandler, callback]; |
337 } | 332 } |
338 | 333 |
339 /** | 334 /** |
340 * Register all methods of {@code mockClass.prototype} with messages of the | 335 * Register all methods of {@code mockClass.prototype} with messages of the |
341 * same name as the method, using the proxy of the |mockObject| as the | 336 * same name as the method, using the proxy of the |mockObject| as the |
342 * |messageHandler| when registering. | 337 * |messageHandler| when registering. |
343 * @param {Mock4JS.Mock} mockObject The mock to register callbacks against. | 338 * @param {Mock4JS.Mock} mockObject The mock to register callbacks against. |
344 * @param {function(new:Object)} mockClAss Constructor for the mocked class. | 339 * @param {function(new:Object)} mockClAss Constructor for the mocked class. |
345 * @see registerMessageCallback | 340 * @see registerMessageCallback |
346 * @see overrideChrome | |
347 */ | 341 */ |
348 function registerMockMessageCallbacks(mockObject, mockClass) { | 342 function registerMockMessageCallbacks(mockObject, mockClass) { |
349 if (!deferGlobalOverrides && !originalChrome) | |
350 overrideChrome(); | |
351 var mockProxy = mockObject.proxy(); | 343 var mockProxy = mockObject.proxy(); |
352 for (var func in mockClass.prototype) { | 344 for (var func in mockClass.prototype) { |
353 if (typeof mockClass.prototype[func] === 'function') { | 345 if (typeof mockClass.prototype[func] === 'function') { |
354 registerMessageCallback(func, mockProxy, mockProxy[func]); | 346 registerMessageCallback(func, mockProxy, mockProxy[func]); |
355 } | 347 } |
356 } | 348 } |
357 } | 349 } |
358 | 350 |
359 /** | 351 /** |
360 * Holds the mapping of name -> global override information. | 352 * Holds the mapping of name -> global override information. |
(...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
557 * @param {Array.<boolean, string>=} result When passed, this is used for the | 549 * @param {Array.<boolean, string>=} result When passed, this is used for the |
558 * testResult message. | 550 * testResult message. |
559 */ | 551 */ |
560 function testDone(result) { | 552 function testDone(result) { |
561 if (!testIsDone) { | 553 if (!testIsDone) { |
562 testIsDone = true; | 554 testIsDone = true; |
563 if (currentTestCase) { | 555 if (currentTestCase) { |
564 try { | 556 try { |
565 currentTestCase.tearDown(); | 557 currentTestCase.tearDown(); |
566 } catch (e) { | 558 } catch (e) { |
567 // Caught an exception in tearDown; Register the error and recreate | |
568 // the result if it is passed in. | |
569 errors.push(e); | 559 errors.push(e); |
570 if (result) | |
571 result = [false, errorsToMessage([e], result[1])]; | |
572 } | 560 } |
573 currentTestCase = null; | 561 currentTestCase = null; |
574 } | 562 } |
575 chrome.send('testResult', result ? result : testResult()); | 563 chrome.send('testResult', result ? result : testResult()); |
576 errors.splice(0, errors.length); | 564 errors.splice(0, errors.length); |
577 } else { | 565 } else { |
578 console.warn('testIsDone already'); | 566 console.warn('testIsDone already'); |
579 } | 567 } |
580 } | 568 } |
581 | 569 |
582 /** | 570 /** |
583 * Converts each Error in |errors| to a suitable message, adding them to | |
584 * |message|, and returns the message string. | |
585 * @param {Array.<Error>} errors Array of errors to add to |message|. | |
586 * @param {string?} message When supplied, error messages are appended to it. | |
587 * @return {string} |message| + messages of all |errors|. | |
588 */ | |
589 function errorsToMessage(errors, message) { | |
590 for (var i = 0; i < errors.length; ++i) { | |
591 var errorMessage = errors[i].stack || errors[i].message; | |
592 if (message) | |
593 message += '\n'; | |
594 | |
595 message += 'Failed: ' + currentTestFunction + '(' + | |
596 currentTestArguments.map(JSON.stringify) + | |
597 ')\n' + errorMessage; | |
598 } | |
599 return message; | |
600 } | |
601 | |
602 /** | |
603 * Returns [success, message] & clears |errors|. | 571 * Returns [success, message] & clears |errors|. |
604 * @param {boolean} errorsOk When true, errors are ok. | 572 * @param {boolean} errorsOk When true, errors are ok. |
605 * @return {Array.<boolean, string>} | 573 * @return {Array.<boolean, string>} |
606 */ | 574 */ |
607 function testResult(errorsOk) { | 575 function testResult(errorsOk) { |
608 var result = [true, '']; | 576 var result = [true, '']; |
609 if (errors.length) { | 577 if (errors.length) { |
610 result = [!!errorsOk, errorsToMessage(errors)]; | 578 var message = ''; |
| 579 for (var i = 0; i < errors.length; ++i) { |
| 580 message += 'Failed: ' + currentTestFunction + '(' + |
| 581 currentTestArguments.map(JSON.stringify) + |
| 582 ')\n' + errors[i].stack; |
| 583 } |
| 584 result = [!!errorsOk, message]; |
611 } | 585 } |
612 return result; | 586 return result; |
613 } | 587 } |
614 | 588 |
615 // Asserts. | 589 // Asserts. |
616 // Use the following assertions to verify a condition within a test. | 590 // Use the following assertions to verify a condition within a test. |
617 // If assertion fails, throw an Error with information pertinent to the test. | 591 // If assertion fails, throw an Error with information pertinent to the test. |
618 | 592 |
619 /** | 593 /** |
620 * When |test| !== true, aborts the current test. | 594 * When |test| !== true, aborts the current test. |
(...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
840 */ | 814 */ |
841 function createTestCase(testFixture, testName) { | 815 function createTestCase(testFixture, testName) { |
842 var fixtureConstructor = this[testFixture]; | 816 var fixtureConstructor = this[testFixture]; |
843 var testBody = fixtureConstructor.testCaseBodies[testName]; | 817 var testBody = fixtureConstructor.testCaseBodies[testName]; |
844 var fixture = new fixtureConstructor(); | 818 var fixture = new fixtureConstructor(); |
845 fixture.name = testFixture; | 819 fixture.name = testFixture; |
846 return new TestCase(testName, fixture, testBody); | 820 return new TestCase(testName, fixture, testBody); |
847 } | 821 } |
848 | 822 |
849 /** | 823 /** |
850 * Overrides the |chrome| object to enable mocking calls to chrome.send(). | |
851 */ | |
852 function overrideChrome() { | |
853 if (originalChrome) { | |
854 console.error('chrome object already overridden'); | |
855 return; | |
856 } | |
857 | |
858 originalChrome = chrome; | |
859 chrome = { | |
860 __proto__: originalChrome, | |
861 send: send, | |
862 originalSend: originalChrome.send.bind(originalChrome), | |
863 }; | |
864 } | |
865 | |
866 /** | |
867 * Used by WebUIBrowserTest to preload the javascript libraries at the | 824 * Used by WebUIBrowserTest to preload the javascript libraries at the |
868 * appropriate time for javascript injection into the current page. This | 825 * appropriate time for javascript injection into the current page. This |
869 * creates a test case and calls its preLoad for any early initialization such | 826 * creates a test case and calls its preLoad for any early initialization such |
870 * as registering handlers before the page's javascript runs it's OnLoad | 827 * as registering handlers before the page's javascript runs it's OnLoad |
871 * method. This is called before the page is loaded, so the |chrome| object is | 828 * method. This is called before the page is loaded, so the |chrome| object is |
872 * not yet bound and this DOMContentLoaded listener will be called first to | 829 * not yet bound and this DOMContentLoaded listener will be called first to |
873 * override |chrome| in order to route messages registered in |sendCallbacks|. | 830 * override |chrome| in order to route messages registered in |sendCallbacks|. |
874 * @param {string} testFixture The test fixture name. | 831 * @param {string} testFixture The test fixture name. |
875 * @param {string} testName The test name. | 832 * @param {string} testName The test name. |
876 * @see sendCallbacks | 833 * @see sendCallbacks |
877 */ | 834 */ |
878 function preloadJavascriptLibraries(testFixture, testName) { | 835 function preloadJavascriptLibraries(testFixture, testName) { |
879 deferGlobalOverrides = true; | 836 deferGlobalOverrides = true; |
880 | 837 |
881 window.addEventListener('DOMContentLoaded', function() { | 838 exports.addEventListener('DOMContentLoaded', function() { |
882 overrideChrome(); | 839 var oldChrome = chrome; |
| 840 chrome = { |
| 841 __proto__: oldChrome, |
| 842 send: send, |
| 843 }; |
883 | 844 |
884 // Override globals at load time so they will be defined. | 845 // Override globals at load time so they will be defined. |
885 assertTrue(deferGlobalOverrides); | 846 assertTrue(deferGlobalOverrides); |
886 deferGlobalOverrides = false; | 847 deferGlobalOverrides = false; |
887 for (var funcName in globalOverrides) | 848 for (var funcName in globalOverrides) |
888 overrideGlobal(funcName); | 849 overrideGlobal(funcName); |
889 }); | 850 }); |
890 currentTestCase = createTestCase(testFixture, testName); | 851 currentTestCase = createTestCase(testFixture, testName); |
891 currentTestCase.preLoad(); | 852 currentTestCase.preLoad(); |
892 } | 853 } |
(...skipping 460 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1353 exports.DUMMY_URL = DUMMY_URL; | 1314 exports.DUMMY_URL = DUMMY_URL; |
1354 exports.TEST = TEST; | 1315 exports.TEST = TEST; |
1355 exports.TEST_F = TEST_F; | 1316 exports.TEST_F = TEST_F; |
1356 exports.GEN = GEN; | 1317 exports.GEN = GEN; |
1357 exports.GEN_INCLUDE = GEN_INCLUDE; | 1318 exports.GEN_INCLUDE = GEN_INCLUDE; |
1358 exports.WhenTestDone = WhenTestDone; | 1319 exports.WhenTestDone = WhenTestDone; |
1359 | 1320 |
1360 // Import the Mock4JS helpers. | 1321 // Import the Mock4JS helpers. |
1361 Mock4JS.addMockSupport(exports); | 1322 Mock4JS.addMockSupport(exports); |
1362 })(this); | 1323 })(this); |
OLD | NEW |