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

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

Powered by Google App Engine
This is Rietveld 408576698