Index: chrome/test/data/webui/test_api.js |
diff --git a/chrome/test/data/webui/test_api.js b/chrome/test/data/webui/test_api.js |
index c9dddc252f351a37714c5fbc80980648d4680103..47abc4772ab17b6e57760c98e508bd16a9b997bd 100644 |
--- a/chrome/test/data/webui/test_api.js |
+++ b/chrome/test/data/webui/test_api.js |
@@ -4,7 +4,144 @@ |
// Library providing basic test framework functionality. |
+var testing = {}; |
+var currentTest = null; |
+var currentTestCase = null; |
+ |
(function() { |
+ // Provide global objects for generation case. |
+ if (!('window' in this)) |
+ this['window'] = this; |
+ if (!('chrome' in this)) { |
+ this['chrome'] = { |
+ 'send': function() {}, |
+ }; |
+ } |
+ if (!('console' in this)) { |
+ this['console'] = { |
+ 'log': print, |
+ }; |
+ } |
+ |
+ /** |
+ * This class will be exported as testing.Test, and is provided to hold the |
+ * fixture's configuration and callback methods for the various phases of |
+ * invoking a test. It is called "Test" rather than TestFixture to roughly |
+ * mimic the gtest's class names. |
+ * @constructor |
+ **/ |
+ function Test() {} |
+ |
+ Test.prototype = { |
+ /** |
+ * The name of the test. |
+ **/ |
+ 'name': null, |
+ |
+ /** |
+ * When set to a string value representing a url, generate BrowsePreload |
+ * call, which will browse to the url and call fixture.PreLoad of the |
+ * currentTestCase. |
+ * @type {String} |
+ **/ |
+ 'browsePreload': null, |
+ |
+ /** |
+ * When set to a string value representing an html page in the test |
+ * directory, generate BrowsePrintPreload call, which will browse to a url |
+ * representing the file, cause print, and call fixture.PreLoad of the |
+ * currentTestCase. |
+ * @type {String} |
+ **/ |
+ 'browsePrintPreload': null, |
+ |
+ /** |
+ * This should be initialized by the test fixture and can be referenced |
+ * during the test run. |
+ * @type {Mock4JS.Mock} |
+ **/ |
+ 'mockHandler': null, |
+ |
+ /** |
+ * Override this method to perform initialization during preload (such as |
+ * creating mocks and registering handlers). |
+ * @type {Function} |
+ **/ |
+ 'PreLoad': function() {}, |
+ |
+ /** |
+ * Override this method to perform tasks before running your test. |
+ * @type {Function} |
+ **/ |
+ 'SetUp': function() {}, |
+ |
+ /** |
+ * Override this method to perform tasks after running your test. If you |
+ * create a mock class, you must call Mock4JS.verifyAllMocks() in this |
+ * phase. |
+ * @type {Function} |
+ **/ |
+ 'TearDown': function() { |
+ Mock4JS.verifyAllMocks(); |
+ } |
+ }; |
+ |
+ /** |
+ * This class is not exported and is available to hold the state of the |
+ * |currentTestCase| throughout preload and test run. |
+ * @param {String} name the name of the test case. |
+ * @param {Test} fixture the fixture object for this test case. |
+ * @param {Function} body the code to run for the test. |
+ * @constructor |
+ **/ |
+ function TestCase(name, fixture, body) { |
+ this.name = name; |
+ this.fixture = fixture; |
+ this.body = body; |
+ } |
+ |
+ TestCase.prototype = { |
+ /** |
+ * The name of this test case. |
+ * @type {String} |
+ **/ |
+ 'name': null, |
+ |
+ /** |
+ * The fixture of this test case. |
+ * @type {Test} |
+ **/ |
+ 'fixture': null, |
+ |
+ /** |
+ * The code to call when running this test case. |
+ * @type {Function} |
+ **/ |
+ 'body': null, |
+ |
+ /** |
+ * Called at preload time, proxies to the fixture. |
+ * @type {Function} |
+ **/ |
+ 'PreLoad': function(name) { |
+ if (this.fixture) |
+ this.fixture.PreLoad(); |
+ }, |
+ |
+ /** |
+ * Runs this test case. |
+ * @type {Function} |
+ **/ |
+ 'Run': function() { |
+ if (this.fixture) |
+ this.fixture.SetUp(); |
+ if (this.body) |
+ this.body.call(this.fixture); |
+ if (this.fixture) |
+ this.fixture.TearDown(); |
+ }, |
+ }; |
+ |
// Asserts. |
// Use the following assertions to verify a condition within a test. |
// If assertion fails, the C++ backend will be immediately notified. |
@@ -19,20 +156,32 @@ |
} |
} |
- var old_chrome = chrome; |
- var send_callbacks = {}; |
+ var oldChrome = chrome; |
+ var sendCallbacks = {}; |
function registerMessageCallback(name, object, callback) { |
- send_callbacks[name] = [object, callback]; |
+ sendCallbacks[name] = [object, callback]; |
} |
+ function registerMockMessageCallbacks(mockObject, mockClass) { |
+ var mockProxy = mockObject.proxy(); |
+ for (func in mockClass.prototype) { |
+ if (typeof(mockClass.prototype[func]) == 'function') { |
+ registerMessageCallback(func, |
+ mockProxy, |
+ mockProxy[func]); |
+ } |
+ } |
+ } |
+ |
+ |
function send(messageName) { |
- var callback = send_callbacks[messageName]; |
+ var callback = sendCallbacks[messageName]; |
var args = Array.prototype.slice.call(arguments, 1); |
if (callback != undefined) |
callback[1].apply(callback[0], args); |
else |
- old_chrome.send.apply(old_chrome, args); |
+ oldChrome.send.apply(oldChrome, args); |
} |
function assertTrue(test, message) { |
@@ -77,11 +226,12 @@ |
// Avoid eval() if at all possible, since it will not work on pages |
// that have enabled content-security-policy. |
currentTest = this[testFunction]; // global object -- not a method. |
- if (typeof currentTest === "undefined") { |
+ if (typeof currentTest === "undefined") |
currentTest = eval(testFunction); |
- } |
- console.log('Running test ' + currentTest.name); |
+ if (currentTest != RUN_TEST_F) |
+ console.log('Running test ' + currentTest.name); |
createExpect(currentTest).apply(null, testArguments); |
+ currentTest = null; |
if (errors.length) { |
return [false, errors.join('\n')]; |
@@ -90,21 +240,110 @@ |
return [true]; |
} |
- function preloadJavascriptLibraries(overload_chrome_send) { |
- if (overload_chrome_send) |
- chrome = { 'send': send }; |
+ function preloadJavascriptLibraries(testFixtureName, testName) { |
+ chrome = { |
+ '__proto__': oldChrome, |
+ 'send': send, |
+ }; |
+ var testFixture = new this[testFixtureName](); |
+ testFixture.name = testFixtureName; |
+ var testBody = this[testName]; |
+ currentTestCase = new TestCase(testName, testFixture, testBody); |
+ currentTestCase.PreLoad(); |
+ } |
+ |
+ /** |
+ * During generation phase, this outputs; do nothing at runtime. |
+ **/ |
+ function GEN() { |
+ } |
+ |
+ /** |
+ * At runtime, register the testFunction as a global object. |
+ * @param {String} testFixture the name of the test fixture class. |
+ * @param {String} testFunction the name of the test function. |
+ * @param {Function} the body to execute when running this test. |
+ **/ |
+ function TEST(testFixture, testFunction, testBody) { |
+ testBody.testFunction = testFunction; |
+ window[testFunction] = testBody; |
+ } |
+ |
+ /** |
+ * At runtime, register the testFunction as a global object. |
+ * @param {String} testFixture the name of the test fixture class. |
+ * @param {String} testFunction the name of the test function. |
+ * @param {Function} the body to execute when running this test. |
+ **/ |
+ function TEST_F(testFixture, testFunction, testBody) { |
+ testBody.testFunction = testFunction; |
+ testBody.testFixture = testFixture; |
+ window[testFunction] = testBody; |
+ } |
+ |
+ /** |
+ * Called by RunJavascriptTestF to invoke the named testFixture & |
+ * testFunction. |
+ * @param {String} testFixture the name of the test fixture class. |
+ * @param {String} testFunction the name of the test function. |
+ **/ |
+ function RUN_TEST_F(testFixture, testFunction) { |
+ assertTrue(!!currentTestCase, 'currentTestCase'); |
+ assertEquals(currentTestCase.name, testFunction); |
+ assertEquals(currentTestCase.fixture.name, testFixture); |
+ console.log('Running Test fixture ' + testFixture + '.' + testFunction); |
+ currentTestCase.Run(); |
+ } |
+ |
+ /** |
+ * CallFunctionAction is provided to allow mocks to have side effects. |
+ * @param {Function} func the function to call. |
+ * @param {Array} args any arguments to pass to func. |
+ * @constructor |
+ **/ |
+ function CallFunctionAction(func, args) { |
+ this._func = func; |
+ this._args = args; |
+ } |
+ |
+ CallFunctionAction.prototype = { |
+ invoke: function() { |
+ return this._func.apply(null, this._args); |
+ }, |
+ describe: function() { |
+ return 'calls the given function with arguments ' + this._args; |
+ } |
+ }; |
+ |
+ /** |
+ * Syntactic sugar for will() on a Mock4JS.Mock. |
+ * @param {Function} func the function to call when the method is invoked. |
+ * @param {*} ... arguments to pass when calling func. |
+ **/ |
+ function callFunction(func) { |
+ return new CallFunctionAction(func, |
+ Array.prototype.slice.call(arguments, 1)); |
} |
// Exports. |
+ testing.Test = Test; |
window.assertTrue = assertTrue; |
window.assertFalse = assertFalse; |
window.assertEquals = assertEquals; |
window.assertNotReached = assertNotReached; |
+ window.callFunction = callFunction; |
window.expectTrue = createExpect(assertTrue); |
window.expectFalse = createExpect(assertFalse); |
window.expectEquals = createExpect(assertEquals); |
window.expectNotReached = createExpect(assertNotReached); |
window.registerMessageCallback = registerMessageCallback; |
+ window.registerMockMessageCallbacks = registerMockMessageCallbacks; |
window.runTest = runTest; |
window.preloadJavascriptLibraries = preloadJavascriptLibraries; |
+ window.TEST = TEST; |
+ window.TEST_F = TEST_F; |
+ window.GEN = GEN; |
+ |
+ // Import the Mock4JS helpers. |
+ Mock4JS.addMockSupport(window); |
})(); |