Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(703)

Side by Side Diff: chrome/test/data/webui/test_api.js

Issue 7237030: Added options browser_tests using the generator and js handler framework. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: TestNavigationController in ui_test_utils, renamed LoadStart->JsInjectionReady, reordered methods. Created 9 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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 // Library providing basic test framework functionality. 5 /**
6 * @fileoverview Library providing basic test framework functionality.
7 **/
8
9 /**
10 * Namespace for |Test|.
11 * @type {Object}
12 **/
13 var testing = {};
14
15 /**
16 * Hold the currentTestCase across between PreLoad and Run.
17 * @type {TestCase}
18 **/
19 var currentTestCase = null;
6 20
7 (function() { 21 (function() {
22 // Provide global objects for generation case.
23 if (this['window'] === undefined)
24 this['window'] = this;
25 if (this['chrome'] === undefined) {
26 this['chrome'] = {
27 send: function() {},
28 };
29 }
30 if (this['console'] === undefined) {
31 this['console'] = {
32 log: print,
33 };
34 }
35
36 /**
37 * This class will be exported as testing.Test, and is provided to hold the
38 * fixture's configuration and callback methods for the various phases of
39 * invoking a test. It is called "Test" rather than TestFixture to roughly
40 * mimic the gtest's class names.
41 * @constructor
42 **/
43 function Test() {}
44
45 Test.prototype = {
46 /**
47 * The name of the test.
48 **/
49 name: null,
50
51 /**
52 * When set to a string value representing a url, generate BrowsePreload
53 * call, which will browse to the url and call fixture.PreLoad of the
54 * currentTestCase.
55 * @type {String}
56 **/
57 browsePreload: null,
58
59 /**
60 * When set to a string value representing an html page in the test
61 * directory, generate BrowsePrintPreload call, which will browse to a url
62 * representing the file, cause print, and call fixture.PreLoad of the
63 * currentTestCase.
64 * @type {String}
65 **/
66 browsePrintPreload: null,
67
68 /**
69 * When set to a function, will be called in the context of the test
70 * generation inside the function, and before any generated C++.
71 * @type {function(string,string)}
72 **/
73 testGenPreamble: null,
74
75 /**
76 * When set to a function, will be called in the context of the test
77 * generation inside the function, and before any generated C++.
78 * @type {function(string,string)}
79 **/
80 testGenPostamble: null,
81
82 /**
83 * When set to a non-null String, auto-generate typedef before generating
84 * TEST*: {@code typedef typedefCppFixture testFixture}.
85 * @type {String}
86 **/
87 typedefCppFixture: 'WebUIBrowserTest',
88
89 /**
90 * This should be initialized by the test fixture and can be referenced
91 * during the test run.
92 * @type {Mock4JS.Mock}
93 **/
94 mockHandler: null,
95
96 /**
97 * Override this method to perform initialization during preload (such as
98 * creating mocks and registering handlers).
99 * @type {Function}
100 **/
101 PreLoad: function() {},
102
103 /**
104 * Override this method to perform tasks before running your test.
105 * @type {Function}
106 **/
107 SetUp: function() {},
108
109 /**
110 * Override this method to perform tasks after running your test. If you
111 * create a mock class, you must call Mock4JS.verifyAllMocks() in this
112 * phase.
113 * @type {Function}
114 **/
115 TearDown: function() {
116 Mock4JS.verifyAllMocks();
117 }
118 };
119
120 /**
121 * This class is not exported and is available to hold the state of the
122 * |currentTestCase| throughout preload and test run.
123 * @param {String} name The name of the test case.
124 * @param {Test} fixture The fixture object for this test case.
125 * @param {Function} body The code to run for the test.
126 * @constructor
127 **/
128 function TestCase(name, fixture, body) {
129 this.name = name;
130 this.fixture = fixture;
131 this.body = body;
132 }
133
134 TestCase.prototype = {
135 name: null,
136 fixture: null,
137 body: null,
138
139 /**
140 * Called at preload time, proxies to the fixture.
141 * @type {Function}
142 **/
143 PreLoad: function(name) {
144 if (this.fixture)
145 this.fixture.PreLoad();
146 },
147
148 /**
149 * Runs this test case.
150 * @type {Function}
151 **/
152 Run: function() {
153 if (this.fixture)
154 this.fixture.SetUp();
155 if (this.body)
156 this.body.call(this.fixture);
157 if (this.fixture)
158 this.fixture.TearDown();
159 },
160 };
161
162 /**
163 * Registry of javascript-defined callbacks for {@code chrome.send}.
164 * @type {Object}
165 **/
166 var sendCallbacks = {};
167
168 /**
169 * Registers the message, object and callback for {@code chrome.send}
170 * @param {String} name The name of the message to route to this |callback|.
171 * @param {Object} messageHAndler Pass as |this| when calling the |callback|.
172 * @param {function(...)} callback Called by {@code chrome.send}.
173 * @see sendCallbacks
174 **/
175 function registerMessageCallback(name, messageHandler, callback) {
176 sendCallbacks[name] = [messageHandler, callback];
177 }
178
179 /**
180 * Register all methods of {@code mockClass.prototype} with messages of the
181 * same name as the method, using the proxy of the |mockObject| as the
182 * |messageHandler| when registering.
183 * @param {Mock4JS.Mock} mockObject The mock to register callbacks against.
184 * @param {function(new:Object)} mockClAss Constructor for the mocked class.
185 * @see registerMessageCallback
186 **/
187 function registerMockMessageCallbacks(mockObject, mockClass) {
188 var mockProxy = mockObject.proxy();
189 for (func in mockClass.prototype) {
190 if (typeof(mockClass.prototype[func]) == 'function') {
191 registerMessageCallback(func,
192 mockProxy,
193 mockProxy[func]);
194 }
195 }
196 }
197
198 /**
199 * Holds the old chrome object when overriding for preload and registry of
200 * handlers.
201 * @type {Object}
202 **/
203 var oldChrome = chrome;
204
205 /**
206 * Overrides {@code chrome.send} for routing messages to javascript
207 * functions. Also fallsback to sending with the |oldChrome| object.
208 * @param {String} messageName The message to route.
209 * @see oldChrome
210 **/
211 function send(messageName) {
212 var callback = sendCallbacks[messageName];
213 var args = Array.prototype.slice.call(arguments, 1);
214 if (callback != undefined)
215 callback[1].apply(callback[0], args);
216 else
217 oldChrome.send.apply(oldChrome, args);
218 }
219
8 // Asserts. 220 // Asserts.
9 // Use the following assertions to verify a condition within a test. 221 // Use the following assertions to verify a condition within a test.
10 // If assertion fails, the C++ backend will be immediately notified. 222 // If assertion fails, the C++ backend will be immediately notified.
11 // If assertion passes, no notification will be sent to the C++ backend. 223 // If assertion passes, no notification will be sent to the C++ backend.
224
225 /**
226 * When |test| !== |expected|, aborts the current test.
227 * @param {Boolean} test The predicate to check against |expected|.
228 * @param {Boolean} expected The expected value of |test|.
229 * @param {String=} message The message to include in the Error thrown.
230 * @throws {Error} upon failure.
231 **/
12 function assertBool(test, expected, message) { 232 function assertBool(test, expected, message) {
13 if (test !== expected) { 233 if (test !== expected) {
14 if (message) 234 if (message)
15 message = test + '\n' + message; 235 message = test + '\n' + message;
16 else 236 else
17 message = test; 237 message = test;
18 throw new Error(message); 238 throw new Error(message);
19 } 239 }
20 } 240 }
21 241
22 var old_chrome = chrome; 242 /**
23 var send_callbacks = {}; 243 * When |test| !== true, aborts the current test.
24 244 * @param {Boolean} test The predicate to check against |expected|.
25 function registerMessageCallback(name, object, callback) { 245 * @param {String=} message The message to include in the Error thrown.
26 send_callbacks[name] = [object, callback]; 246 * @throws {Error} upon failure.
27 } 247 **/
28
29 function send(messageName) {
30 var callback = send_callbacks[messageName];
31 var args = Array.prototype.slice.call(arguments, 1);
32 if (callback != undefined)
33 callback[1].apply(callback[0], args);
34 else
35 old_chrome.send.apply(old_chrome, args);
36 }
37
38 function assertTrue(test, message) { 248 function assertTrue(test, message) {
39 assertBool(test, true, message); 249 assertBool(test, true, message);
40 } 250 }
41 251
252 /**
253 * When |test| !== false, aborts the current test.
254 * @param {Boolean} test The predicate to check against |expected|.
255 * @param {String=} message The message to include in the Error thrown.
256 * @throws {Error} upon failure.
257 **/
42 function assertFalse(test, message) { 258 function assertFalse(test, message) {
43 assertBool(test, false, message); 259 assertBool(test, false, message);
44 } 260 }
45 261
262 /**
263 * When |expected| !== |actual|, aborts the current test.
264 * @param {*} expected The predicate to check against |expected|.
265 * @param {*} actual The expected value of |test|.
266 * @param {String=} message The message to include in the Error thrown.
267 * @throws {Error} upon failure.
268 **/
46 function assertEquals(expected, actual, message) { 269 function assertEquals(expected, actual, message) {
47 if (expected != actual) { 270 if (expected != actual) {
48 throw new Error('Test Error. Actual: ' + actual + '\nExpected: ' + 271 throw new Error('Test Error. Actual: ' + actual + '\nExpected: ' +
49 expected + '\n' + message); 272 expected + '\n' + message);
50 } 273 }
51 if (typeof expected != typeof actual) { 274 if (typeof expected != typeof actual) {
52 throw new Error('Test Error' + 275 throw new Error('Test Error' +
53 ' (type mismatch)\nActual Type: ' + typeof actual + 276 ' (type mismatch)\nActual Type: ' + typeof actual +
54 '\nExpected Type:' + typeof expected + '\n' + message); 277 '\nExpected Type:' + typeof expected + '\n' + message);
55 } 278 }
56 } 279 }
57 280
281 /**
282 * Always aborts the current test.
283 * @param {String=} message The message to include in the Error thrown.
284 * @throws {Error} always.
285 **/
58 function assertNotReached(message) { 286 function assertNotReached(message) {
59 throw new Error(message); 287 throw new Error(message);
60 } 288 }
61 289
290 /**
291 * Holds the errors, if any, caught by expects so that the test case can fail.
292 * @type {Array.<Error>}
293 **/
62 var errors = []; 294 var errors = [];
63 295
296 /**
297 * Creates a function based upon a function that thows an exception on
298 * failure. The new function stuffs any errors into the |errors| array for
299 * checking by runTest. This allows tests to continue running other checks,
300 * while failing the overal test if any errors occurrred.
301 * @param {Function} assertFunc The function which may throw an Error.
302 * @return {Function} A function that applies its arguments to |assertFunc|.
303 * @see errors
304 * @see runTest
305 **/
64 function createExpect(assertFunc) { 306 function createExpect(assertFunc) {
65 return function() { 307 return function() {
66 try { 308 try {
67 assertFunc.apply(null, arguments); 309 assertFunc.apply(null, arguments);
68 } catch (e) { 310 } catch (e) {
69 console.log('Failed: ' + currentTest.name + '\n' + e.stack);
70 errors.push(e); 311 errors.push(e);
71 } 312 }
72 }; 313 };
73 } 314 }
74 315
316 /**
317 * This is the starting point for tests run by WebUIBrowserTest. It clears
318 * |errors|, runs the test surrounded by an expect to catch Errors. If
319 * |errors| is non-empty, it reports a failure and a message by joining
320 * |errors|.
321 * @param {String} testFunction The function name to call.
322 * @param {Array} testArguments The arguments to call |testFunction| with.
323 * @return {Array.<Boolean, String>} [test-succeeded, message-if-failed]
324 * @see errors
325 * @see createExpect
326 **/
75 function runTest(testFunction, testArguments) { 327 function runTest(testFunction, testArguments) {
76 errors = []; 328 errors = [];
77 // Avoid eval() if at all possible, since it will not work on pages 329 // Avoid eval() if at all possible, since it will not work on pages
78 // that have enabled content-security-policy. 330 // that have enabled content-security-policy.
79 currentTest = this[testFunction]; // global object -- not a method. 331 var testBody = this[testFunction]; // global object -- not a method.
80 if (typeof currentTest === "undefined") { 332 if (typeof testBody === "undefined")
81 currentTest = eval(testFunction); 333 testBody = eval(testFunction);
82 } 334 if (testBody != RUN_TEST_F)
83 console.log('Running test ' + currentTest.name); 335 console.log('Running test ' + testBody.name);
84 createExpect(currentTest).apply(null, testArguments); 336 createExpect(testBody).apply(null, testArguments);
85 337
86 if (errors.length) { 338 if (errors.length) {
339 for (var i = 0; i < errors.length; ++i) {
340 console.log('Failed: ' + testFunction + '(' +
341 testArguments.toString() + ')\n' + errors[i].stack);
342 }
87 return [false, errors.join('\n')]; 343 return [false, errors.join('\n')];
88 } 344 } else {
89 345 return [true];
90 return [true]; 346 }
91 } 347 }
92 348
93 function preloadJavascriptLibraries(overload_chrome_send) { 349 /**
94 if (overload_chrome_send) 350 * Creates a new test case for the given |testFixture| and |testName|. Assumes
95 chrome = { 'send': send }; 351 * |testFixture| describes a globally available subclass of type Test.
352 * @param {String} testFixture The fixture for this test case.
353 * @param {String} testName The name for this test case.
354 * @return {TestCase} A newly created TestCase.
355 **/
356 function createTestCase(testFixture, testName) {
357 var fixtureConstructor = this[testFixture];
358 var testBody = fixtureConstructor.testCaseBodies[testName];
359 var fixture = new fixtureConstructor();
360 fixture.name = testFixture;
361 return new TestCase(testName, fixture, testBody);
362 }
363
364 /**
365 * Used by WebUIBrowserTest to preload the javascript libraries at the
366 * appropriate time for javascript injection into the current page. This
367 * creates a test case and calls its PreLoad for any early initialization such
368 * as registering handlers before the page's javascript runs it's OnLoad
369 * method.
370 * @param {String} testFixture The test fixture name.
371 * @param {String} testName The test name.
372 **/
373 function preloadJavascriptLibraries(testFixture, testName) {
374 chrome = {
375 __proto__: oldChrome,
376 send: send,
377 };
378 currentTestCase = createTestCase(testFixture, testName);
379 currentTestCase.PreLoad();
380 }
381
382 /**
383 * During generation phase, this outputs; do nothing at runtime.
384 **/
385 function GEN() {}
386
387 /**
388 * At runtime, register the testName with a test fixture. Since this method
389 * doesn't have a test fixture, we create a dummy fixture to hold its |name|
390 * and |testCaseBodies|.
391 * @param {String} testCaseName The name of the test case.
392 * @param {String} testName The name of the test function.
393 * @param {Function} testBody The body to execute when running this test.
394 **/
395 function TEST(testCaseName, testName, testBody) {
396 if (this[testCaseName] === undefined) {
397 var fixtureConstructor = new function() {};
398 this[testCaseName] = fixtureConstructor;
399 fixtureConstructor.prototype.name = testCaseName;
400 fixtureConstructor.testCaseBodies = {};
401 }
402 fixtureConstructor.testCaseBodies[testName] = testBody;
403 }
404
405 /**
406 * At runtime, register the testName with its fixture. Stuff the |name| into
407 * the |testFixture|'s prototype, if needed, and the |testCaseBodies| into its
408 * constructor.
409 * @param {String} testFixture The name of the test fixture class.
410 * @param {String} testName The name of the test function.
411 * @param {Function} testBody The body to execute when running this test.
412 **/
413 function TEST_F(testFixture, testName, testBody) {
414 var fixtureConstructor = this[testFixture];
415 if (!fixtureConstructor.prototype.name)
416 fixtureConstructor.prototype.name = testFixture;
417 if (fixtureConstructor['testCaseBodies'] === undefined)
418 fixtureConstructor.testCaseBodies = {};
419 fixtureConstructor.testCaseBodies[testName] = testBody;
420 }
421
422 /**
423 * RunJavascriptTestF uses this as the |testFunction| when invoking
424 * runTest. If |currentTestCase| is non-null at this point, verify that
425 * |testFixture| and |testName| agree with the preloaded values. Create
426 * |currentTestCase|, if needed, run it, and clear the |currentTestCase|.
427 * @param {String} testFixture The name of the test fixture class.
428 * @param {String} testName The name of the test function.
429 * @see preloadJavascriptLibraries
430 * @see runTest
431 **/
432 function RUN_TEST_F(testFixture, testName) {
433 if (!currentTestCase)
434 currentTestCase = createTestCase(testFixture, testName);
435 assertEquals(currentTestCase.name, testName);
436 assertEquals(currentTestCase.fixture.name, testFixture);
437 console.log('Running TestCase ' + testFixture + '.' + testName);
438 currentTestCase.Run();
439 currentTestCase = null;
440 }
441
442 /**
443 * CallFunctionAction is provided to allow mocks to have side effects.
444 * @param {Function} func The function to call.
445 * @param {Array} args Any arguments to pass to func.
446 * @constructor
447 **/
448 function CallFunctionAction(func, args) {
449 this._func = func;
450 this._args = args;
451 }
452
453 CallFunctionAction.prototype = {
454 invoke: function() {
455 return this._func.apply(null, this._args);
456 },
457 describe: function() {
458 return 'calls the given function with arguments ' + this._args;
459 }
460 };
461
462 /**
463 * Syntactic sugar for will() on a Mock4JS.Mock.
464 * @param {Function} func the function to call when the method is invoked.
465 * @param {...*} var_args arguments to pass when calling func.
466 **/
467 function callFunction(func) {
468 return new CallFunctionAction(func,
469 Array.prototype.slice.call(arguments, 1));
96 } 470 }
97 471
98 // Exports. 472 // Exports.
473 testing.Test = Test;
99 window.assertTrue = assertTrue; 474 window.assertTrue = assertTrue;
100 window.assertFalse = assertFalse; 475 window.assertFalse = assertFalse;
101 window.assertEquals = assertEquals; 476 window.assertEquals = assertEquals;
102 window.assertNotReached = assertNotReached; 477 window.assertNotReached = assertNotReached;
478 window.callFunction = callFunction;
103 window.expectTrue = createExpect(assertTrue); 479 window.expectTrue = createExpect(assertTrue);
104 window.expectFalse = createExpect(assertFalse); 480 window.expectFalse = createExpect(assertFalse);
105 window.expectEquals = createExpect(assertEquals); 481 window.expectEquals = createExpect(assertEquals);
106 window.expectNotReached = createExpect(assertNotReached); 482 window.expectNotReached = createExpect(assertNotReached);
107 window.registerMessageCallback = registerMessageCallback; 483 window.registerMessageCallback = registerMessageCallback;
484 window.registerMockMessageCallbacks = registerMockMessageCallbacks;
108 window.runTest = runTest; 485 window.runTest = runTest;
109 window.preloadJavascriptLibraries = preloadJavascriptLibraries; 486 window.preloadJavascriptLibraries = preloadJavascriptLibraries;
487 window.TEST = TEST;
488 window.TEST_F = TEST_F;
489 window.GEN = GEN;
490
491 // Import the Mock4JS helpers.
492 Mock4JS.addMockSupport(window);
110 })(); 493 })();
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698