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