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

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

Issue 7645007: WebUI Testing: async support - global mocking, deferred runs, continued run. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Test runAllActionsAsync with various combinations of arguments. Created 9 years, 4 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 /** 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 14 (function(window) {
15 /** 15 /**
16 * Hold the currentTestCase across between PreLoad and Run. 16 * Hold the currentTestCase across between preLoad and run.
17 * @type {TestCase} 17 * @type {TestCase}
18 **/ 18 */
19 var currentTestCase = null; 19 var currentTestCase = null;
20
21 /**
22 * @type {?string} The string representation of the currently running test
23 * function.
24 */
25 var currentTestFunction = null;
26
27 /**
28 * @type {?Array} The arguments of the currently running test.
29 */
30 var currentTestArguments = null;
31
32 (function() {
33 // Provide global objects for generation case.
34 if (this['window'] === undefined)
35 this['window'] = this;
36 if (this['chrome'] === undefined) {
37 this['chrome'] = {
38 send: function() {},
39 };
40 }
41 if (this['console'] === undefined) {
42 this['console'] = {
43 log: print,
44 };
45 }
46 20
47 /** 21 /**
22 * @type {?string} The string representation of the currently running test
23 * function.
24 */
25 var currentTestFunction = null;
26
27 /**
28 * @type {?Array} The arguments of the currently running test.
29 */
30 var currentTestArguments = null;
31
32 /**
48 * This class will be exported as testing.Test, and is provided to hold the 33 * This class will be exported as testing.Test, and is provided to hold the
49 * fixture's configuration and callback methods for the various phases of 34 * fixture's configuration and callback methods for the various phases of
50 * invoking a test. It is called "Test" rather than TestFixture to roughly 35 * invoking a test. It is called "Test" rather than TestFixture to roughly
51 * mimic the gtest's class names. 36 * mimic the gtest's class names.
52 * @constructor 37 * @constructor
53 **/ 38 */
54 function Test() {} 39 function Test() {}
55 40
56 Test.prototype = { 41 Test.prototype = {
57 /** 42 /**
58 * The name of the test. 43 * The name of the test.
59 **/ 44 */
60 name: null, 45 name: null,
61 46
62 /** 47 /**
63 * When set to a string value representing a url, generate BrowsePreload 48 * When set to a string value representing a url, generate BrowsePreload
64 * call, which will browse to the url and call fixture.PreLoad of the 49 * call, which will browse to the url and call fixture.preLoad of the
65 * currentTestCase. 50 * currentTestCase.
66 * @type {string} 51 * @type {string}
67 **/ 52 */
68 browsePreload: null, 53 browsePreload: null,
69 54
70 /** 55 /**
71 * When set to a string value representing an html page in the test 56 * When set to a string value representing an html page in the test
72 * directory, generate BrowsePrintPreload call, which will browse to a url 57 * directory, generate BrowsePrintPreload call, which will browse to a url
73 * representing the file, cause print, and call fixture.PreLoad of the 58 * representing the file, cause print, and call fixture.preLoad of the
74 * currentTestCase. 59 * currentTestCase.
75 * @type {string} 60 * @type {string}
76 **/ 61 */
77 browsePrintPreload: null, 62 browsePrintPreload: null,
78 63
79 /** 64 /**
80 * When set to a function, will be called in the context of the test 65 * When set to a function, will be called in the context of the test
81 * generation inside the function, and before any generated C++. 66 * generation inside the function, and before any generated C++.
82 * @type {function(string,string)} 67 * @type {function(string,string)}
83 **/ 68 */
84 testGenPreamble: null, 69 testGenPreamble: null,
85 70
86 /** 71 /**
87 * When set to a function, will be called in the context of the test 72 * When set to a function, will be called in the context of the test
88 * generation inside the function, and after any generated C++. 73 * generation inside the function, and after any generated C++.
89 * @type {function(string,string)} 74 * @type {function(string,string)}
90 **/ 75 */
91 testGenPostamble: null, 76 testGenPostamble: null,
92 77
93 /** 78 /**
94 * When set to a non-null string, auto-generate typedef before generating 79 * When set to a non-null string, auto-generate typedef before generating
95 * TEST*: {@code typedef typedefCppFixture testFixture}. 80 * TEST*: {@code typedef typedefCppFixture testFixture}.
96 * @type {string} 81 * @type {string}
97 **/ 82 */
98 typedefCppFixture: 'WebUIBrowserTest', 83 typedefCppFixture: 'WebUIBrowserTest',
99 84
100 /** 85 /**
101 * This should be initialized by the test fixture and can be referenced 86 * This should be initialized by the test fixture and can be referenced
102 * during the test run. 87 * during the test run. It holds any mocked handler methods.
103 * @type {Mock4JS.Mock} 88 * @type {?Mock4JS.Mock}
104 **/ 89 */
105 mockHandler: null, 90 mockHandler: null,
106 91
107 /** 92 /**
93 * This should be initialized by the test fixture and can be referenced
94 * during the test run. It holds any mocked global functions.
95 * @type {?Mock4JS.Mock}
96 */
97 mockGlobals: null,
98
99 /**
100 * Value is passed through call to C++ RunJavascriptF to invoke this test.
101 * @type {boolean}
102 */
103 isAsync: false,
104
105 /**
108 * Override this method to perform initialization during preload (such as 106 * Override this method to perform initialization during preload (such as
109 * creating mocks and registering handlers). 107 * creating mocks and registering handlers).
110 * @type {Function} 108 * @type {Function}
111 **/ 109 */
112 PreLoad: function() {}, 110 preLoad: function() {},
113 111
114 /** 112 /**
115 * Override this method to perform tasks before running your test. 113 * Override this method to perform tasks before running your test.
116 * @type {Function} 114 * @type {Function}
117 **/ 115 */
118 SetUp: function() {}, 116 setUp: function() {},
119 117
120 /** 118 /**
121 * Override this method to perform tasks after running your test. If you 119 * Override this method to perform tasks after running your test. If you
122 * create a mock class, you must call Mock4JS.verifyAllMocks() in this 120 * create a mock class, you must call Mock4JS.verifyAllMocks() in this
123 * phase. 121 * phase.
124 * @type {Function} 122 * @type {Function}
125 **/ 123 */
126 TearDown: function() { 124 tearDown: function() {
127 Mock4JS.verifyAllMocks(); 125 Mock4JS.verifyAllMocks();
128 } 126 },
127
128 /**
129 * Called to run the body from the perspective of this fixture.
130 * @type {Function}
131 */
132 runTest: function(testBody) {
133 testBody.call(this);
134 },
135
136 /**
137 * Create a closure function for continuing the test at a later time. May be
138 * used as a listener function.
139 * @param {WhenTestDone} whenTestDone Call testDone() at the appropriate
140 * time.
141 * @param {Function} completion The function to call to complete the test.
142 * @param {...*} var_args Arguments to pass when calling completionAction.
143 * @return {function(): void} Return a function, bound to this test fixture,
144 * which continues the test.
145 */
146 continueTest: function(whenTestDone, completion) {
147 var savedArgs = new SaveMockArguments();
148 var completionAction = new CallFunctionAction(
149 this, savedArgs, completion,
150 Array.prototype.slice.call(arguments, 2));
151 if (whenTestDone === WhenTestDone.DEFAULT)
152 whenTestDone = WhenTestDone.ASSERT;
153 var runAll = new RunAllAction(
154 true, whenTestDone, [completionAction]);
155 return function() {
156 savedArgs.arguments = Array.prototype.slice.call(arguments);
157 runAll.invoke();
158 };
159 },
160
161 /**
162 * Call this during setUp to defer the call to runTest() until later. The
163 * caller must call the returned function at some point to run the test.
164 * @type {Function}
165 * @param {WhenTestDone} whenTestDone Call testDone() at the appropriate
166 * time.
167 * @param {...*} var_args Arguments to pass when running the
168 * |currentTestCase|.
169 * @return {function(): void} A function which will run the current body of
170 * the currentTestCase.
171 */
172 deferRunTest: function(whenTestDone) {
173 if (whenTestDone === WhenTestDone.DEFAULT)
174 whenTestDone = WhenTestDone.ALWAYS;
175
176 return currentTestCase.deferRunTest.apply(
177 currentTestCase, [whenTestDone].concat(
178 Array.prototype.slice.call(arguments, 1)));
179 },
129 }; 180 };
130 181
131 /** 182 /**
132 * This class is not exported and is available to hold the state of the 183 * This class is not exported and is available to hold the state of the
133 * |currentTestCase| throughout preload and test run. 184 * |currentTestCase| throughout preload and test run.
134 * @param {string} name The name of the test case. 185 * @param {string} name The name of the test case.
135 * @param {Test} fixture The fixture object for this test case. 186 * @param {Test} fixture The fixture object for this test case.
136 * @param {Function} body The code to run for the test. 187 * @param {Function} body The code to run for the test.
137 * @constructor 188 * @constructor
138 **/ 189 */
139 function TestCase(name, fixture, body) { 190 function TestCase(name, fixture, body) {
140 this.name = name; 191 this.name = name;
141 this.fixture = fixture; 192 this.fixture = fixture;
142 this.body = body; 193 this.body = body;
143 } 194 }
144 195
145 TestCase.prototype = { 196 TestCase.prototype = {
197 /**
198 * The name of this test.
199 * @type {string}
200 */
146 name: null, 201 name: null,
202
203 /**
204 * The test fixture to set |this| to when running the test |body|.
205 * @type {testing.Test}
206 */
147 fixture: null, 207 fixture: null,
208
209 /**
210 * The test body to execute in runTest().
211 * @type {Function}
212 */
148 body: null, 213 body: null,
149 214
150 /** 215 /**
216 * True when the test fixture will run the test later.
217 * @type {boolean}
218 * @private
219 */
220 deferred_: false,
221
222 /**
151 * Called at preload time, proxies to the fixture. 223 * Called at preload time, proxies to the fixture.
152 * @type {Function} 224 * @type {Function}
153 **/ 225 */
154 PreLoad: function(name) { 226 preLoad: function(name) {
155 if (this.fixture) 227 if (this.fixture)
156 this.fixture.PreLoad(); 228 this.fixture.preLoad();
157 }, 229 },
158 230
159 /** 231 /**
232 * Called before a test runs.
233 */
234 setUp: function() {
235 if (this.fixture)
236 this.fixture.setUp();
237 },
238
239 /**
240 * Called before a test is torn down (by testDone()).
241 */
242 tearDown: function() {
243 if (this.fixture)
244 this.fixture.tearDown();
245 },
246
247 /**
248 * Called to run this test's body.
249 */
250 runTest: function() {
251 if (this.body && this.fixture)
252 this.fixture.runTest(this.body);
253 },
254
255 /**
160 * Runs this test case with |this| set to the |fixture|. 256 * Runs this test case with |this| set to the |fixture|.
161 * 257 *
162 * Note: Tests created with TEST_F may depend upon |this| being set to an 258 * Note: Tests created with TEST_F may depend upon |this| being set to an
163 * instance of this.fixture. The current implementation of TEST creates a 259 * instance of this.fixture. The current implementation of TEST creates a
164 * dummy constructor, but tests created with TEST should not rely on |this| 260 * dummy constructor, but tests created with TEST should not rely on |this|
165 * being set. 261 * being set.
166 * @type {Function} 262 * @type {Function}
167 **/ 263 */
168 Run: function() { 264 run: function() {
169 if (this.fixture) 265 try {
170 this.fixture.SetUp(); 266 this.setUp();
171 if (this.body) 267 } catch(e) {
172 this.body.call(this.fixture); 268 console.error(e.stack);
173 if (this.fixture) 269 }
174 this.fixture.TearDown(); 270
271 if (!this.deferred_)
272 this.runTest();
273
274 // tearDown called by testDone().
175 }, 275 },
276
277 /**
278 * Cause this TestCase to be deferred (don't call runTest()) until the
279 * returned function is called.
280 * @type {Function}
281 * @param {WhenTestDone} whenTestDone Call testDone() at the appropriate
282 * time.
283 * @param {...*} var_args Arguments to pass when running the
284 * |currentTestCase|.
285 * @return {function(): void} A function thatwill run this TestCase when
286 * called.
287 */
288 deferRunTest: function(whenTestDone) {
289 this.deferred_ = true;
290 var savedArgs = new SaveMockArguments();
291 var completionAction = new CallFunctionAction(
292 this, savedArgs, this.runTest,
293 Array.prototype.slice.call(arguments, 1));
294 var runAll = new RunAllAction(
295 true, whenTestDone, [completionAction]);
296 return function() {
297 savedArgs.arguments = Array.prototype.slice.call(arguments);
298 runAll.invoke();
299 };
300 },
301
176 }; 302 };
177 303
178 /** 304 /**
179 * Registry of javascript-defined callbacks for {@code chrome.send}. 305 * Registry of javascript-defined callbacks for {@code chrome.send}.
180 * @type {Object} 306 * @type {Object}
181 **/ 307 */
182 var sendCallbacks = {}; 308 var sendCallbacks = {};
183 309
184 /** 310 /**
185 * Registers the message, object and callback for {@code chrome.send} 311 * Registers the message, object and callback for {@code chrome.send}
186 * @param {string} name The name of the message to route to this |callback|. 312 * @param {string} name The name of the message to route to this |callback|.
187 * @param {Object} messageHAndler Pass as |this| when calling the |callback|. 313 * @param {Object} messageHandler Pass as |this| when calling the |callback|.
188 * @param {function(...)} callback Called by {@code chrome.send}. 314 * @param {function(...)} callback Called by {@code chrome.send}.
189 * @see sendCallbacks 315 * @see sendCallbacks
190 **/ 316 */
191 function registerMessageCallback(name, messageHandler, callback) { 317 function registerMessageCallback(name, messageHandler, callback) {
192 sendCallbacks[name] = [messageHandler, callback]; 318 sendCallbacks[name] = [messageHandler, callback];
193 } 319 }
194 320
195 /** 321 /**
196 * Register all methods of {@code mockClass.prototype} with messages of the 322 * Register all methods of {@code mockClass.prototype} with messages of the
197 * same name as the method, using the proxy of the |mockObject| as the 323 * same name as the method, using the proxy of the |mockObject| as the
198 * |messageHandler| when registering. 324 * |messageHandler| when registering.
199 * @param {Mock4JS.Mock} mockObject The mock to register callbacks against. 325 * @param {Mock4JS.Mock} mockObject The mock to register callbacks against.
200 * @param {function(new:Object)} mockClAss Constructor for the mocked class. 326 * @param {function(new:Object)} mockClAss Constructor for the mocked class.
201 * @see registerMessageCallback 327 * @see registerMessageCallback
202 **/ 328 */
203 function registerMockMessageCallbacks(mockObject, mockClass) { 329 function registerMockMessageCallbacks(mockObject, mockClass) {
204 var mockProxy = mockObject.proxy(); 330 var mockProxy = mockObject.proxy();
205 for (func in mockClass.prototype) { 331 for (var func in mockClass.prototype) {
206 if (typeof(mockClass.prototype[func]) == 'function') { 332 if (typeof mockClass.prototype[func] == 'function') {
207 registerMessageCallback(func, 333 registerMessageCallback(func, mockProxy, mockProxy[func]);
208 mockProxy,
209 mockProxy[func]);
210 } 334 }
211 } 335 }
212 } 336 }
337
338 /**
339 * Holds the mapping of name -> global override information.
340 * @type {Object}
341 */
342 var globalOverrides = {};
343
344 /**
345 * Registers the global function name, object and callback.
mmenke 2011/08/24 15:27:50 Important: Add a comment that this can only be ca
Sheridan Rawlins 2011/08/24 21:15:45 How 'bout this instead - I made it possible to moc
mmenke 2011/08/24 21:33:30 Sounds like a better idea to me.
346 * @param {string} name The name of the message to route to this |callback|.
347 * @param {Object} object Pass as |this| when calling the |callback|.
348 * @param {function(...)} callback Called by {@code chrome.send}.
349 */
350 function registerMockGlobal(name, object, callback) {
351 assertEquals(undefined, globalOverrides[name]);
352 globalOverrides[name] = {
353 object: object,
354 callback: callback,
355 };
356 }
357
358 /**
359 * Register all methods of {@code mockClass.prototype} as overrides to global
360 * functions of the same name as the method, using the proxy of the
361 * |mockObject| to handle the functions.
362 * @param {Mock4JS.Mock} mockObject The mock to register callbacks against.
363 * @param {function(new:Object)} mockClAss Constructor for the mocked class.
364 * @see registerMessageCallback
365 */
366 function registerMockGlobals(mockObject, mockClass) {
367 var mockProxy = mockObject.proxy();
368 for (var func in mockClass.prototype) {
369 if (typeof(mockClass.prototype[func]) == 'function') {
370 registerMockGlobal(func, mockProxy, mockProxy[func]);
371 }
372 }
373 }
213 374
214 /** 375 /**
215 * Overrides {@code chrome.send} for routing messages to javascript 376 * Overrides {@code chrome.send} for routing messages to javascript
216 * functions. Also falls back to sending with the original chrome object. 377 * functions. Also falls back to sending with the original chrome object.
217 * @param {string} messageName The message to route. 378 * @param {string} messageName The message to route.
218 **/ 379 */
219 function send(messageName) { 380 function send(messageName) {
220 var callback = sendCallbacks[messageName]; 381 var callback = sendCallbacks[messageName];
221 if (callback != undefined) 382 if (callback != undefined)
222 callback[1].apply(callback[0], Array.prototype.slice.call(arguments, 1)); 383 callback[1].apply(callback[0], arguments[1]);
223 else 384 else
224 this.__proto__.send.apply(this.__proto__, arguments); 385 this.__proto__.send.apply(this.__proto__, arguments);
225 } 386 }
226 387
227 /** 388 /**
228 * Provides a mechanism for assert* and expect* methods to fetch the signature 389 * Provides a mechanism for assert* and expect* methods to fetch the signature
229 * of their caller. Assert* methods should |registerCall| and expect* methods 390 * of their caller. Assert* methods should |registerCall| and expect* methods
230 * should set |isExpect| and |expectName| properties to indicate that the 391 * should set |isExpect| and |expectName| properties to indicate that the
231 * interesting caller is one more level up the stack. 392 * interesting caller is one more level up the stack.
232 **/ 393 */
233 function CallHelper() { 394 function CallHelper() {
234 this.__proto__ = CallHelper.prototype; 395 this.__proto__ = CallHelper.prototype;
235 } 396 }
236 397
237 CallHelper.prototype = { 398 CallHelper.prototype = {
238 /** 399 /**
239 * Holds the mapping of (callerCallerString, callerName) -> count of times 400 * Holds the mapping of (callerCallerString, callerName) -> count of times
240 * called. 401 * called.
241 * @type {Object.<string, Object.<string, number>>} 402 * @type {Object.<string, Object.<string, number>>}
242 **/ 403 */
243 counts_: {}, 404 counts_: {},
244 405
245 /** 406 /**
246 * This information about the caller is needed from most of the following 407 * This information about the caller is needed from most of the following
247 * routines. 408 * routines.
248 * @param {Function} caller the caller of the assert* routine. 409 * @param {Function} caller the caller of the assert* routine.
249 * @return {{callerName: string, callercallerString: string}} stackInfo 410 * @return {{callerName: string, callercallerString: string}} stackInfo
250 * @private 411 * @private
251 **/ 412 */
252 getCallerInfo_: function(caller) { 413 getCallerInfo_: function(caller) {
253 var callerName = caller.name; 414 var callerName = caller.name;
254 var callerCaller = caller.caller; 415 var callerCaller = caller.caller;
255 if (callerCaller['isExpect']) { 416 if (callerCaller['isExpect']) {
256 callerName = callerCaller.expectName; 417 callerName = callerCaller.expectName;
257 callerCaller = callerCaller.caller; 418 callerCaller = callerCaller.caller;
258 } 419 }
259 var callerCallerString = callerCaller.toString(); 420 var callerCallerString = callerCaller.toString();
260 return { 421 return {
261 callerName: callerName, 422 callerName: callerName,
262 callerCallerString: callerCallerString, 423 callerCallerString: callerCallerString,
263 }; 424 };
264 }, 425 },
265 426
266 /** 427 /**
267 * Register a call to an assertion class. 428 * Register a call to an assertion class.
268 **/ 429 */
269 registerCall: function() { 430 registerCall: function() {
270 var stackInfo = this.getCallerInfo_(arguments.callee.caller); 431 var stackInfo = this.getCallerInfo_(arguments.callee.caller);
271 if (!(stackInfo.callerCallerString in this.counts_)) 432 if (!(stackInfo.callerCallerString in this.counts_))
272 this.counts_[stackInfo.callerCallerString] = {}; 433 this.counts_[stackInfo.callerCallerString] = {};
273 if (!(stackInfo.callerName in this.counts_[stackInfo.callerCallerString])) 434 if (!(stackInfo.callerName in this.counts_[stackInfo.callerCallerString]))
274 this.counts_[stackInfo.callerCallerString][stackInfo.callerName] = 0; 435 this.counts_[stackInfo.callerCallerString][stackInfo.callerName] = 0;
275 ++this.counts_[stackInfo.callerCallerString][stackInfo.callerName]; 436 ++this.counts_[stackInfo.callerCallerString][stackInfo.callerName];
276 }, 437 },
277 438
278 /** 439 /**
279 * Get the call signature of this instance of the caller's call to this 440 * Get the call signature of this instance of the caller's call to this
280 * function. 441 * function.
281 * @param {Function} caller The caller of the assert* routine. 442 * @param {Function} caller The caller of the assert* routine.
282 * @return {String} Call signature. 443 * @return {String} Call signature.
283 * @private 444 * @private
284 **/ 445 */
285 getCall_: function(caller) { 446 getCall_: function(caller) {
286 var stackInfo = this.getCallerInfo_(caller); 447 var stackInfo = this.getCallerInfo_(caller);
287 var count = 448 var count =
288 this.counts_[stackInfo.callerCallerString][stackInfo.callerName]; 449 this.counts_[stackInfo.callerCallerString][stackInfo.callerName];
289 450
290 // Allow pattern to match multiple lines for text wrapping. 451 // Allow pattern to match multiple lines for text wrapping.
291 var callerRegExp = 452 var callerRegExp =
292 new RegExp(stackInfo.callerName + '\\((.|\\n)*?\\);', 'g'); 453 new RegExp(stackInfo.callerName + '\\((.|\\n)*?\\);', 'g');
293 454
294 // Find all matches allowing wrap around such as when a helper function 455 // Find all matches allowing wrap around such as when a helper function
295 // calls assert/expect calls and that helper function is called multiple 456 // calls assert/expect calls and that helper function is called multiple
296 // times. 457 // times.
297 var matches = stackInfo.callerCallerString.match(callerRegExp); 458 var matches = stackInfo.callerCallerString.match(callerRegExp);
298 var match = matches[(count - 1) % matches.length]; 459 var match = matches[(count - 1) % matches.length];
299 460
300 // Chop off the trailing ';'. 461 // Chop off the trailing ';'.
301 return match.substring(0, match.length-1); 462 return match.substring(0, match.length-1);
302 }, 463 },
303 464
304 /** 465 /**
305 * Returns the text of the call signature and any |message|. 466 * Returns the text of the call signature and any |message|.
306 * @param {string=} message Addtional message text from caller. 467 * @param {string=} message Addtional message text from caller.
307 **/ 468 */
308 getCallMessage: function(message) { 469 getCallMessage: function(message) {
309 var callMessage = this.getCall_(arguments.callee.caller); 470 var callMessage = this.getCall_(arguments.callee.caller);
310 if (message) 471 if (message)
311 callMessage += ': ' + message; 472 callMessage += ': ' + message;
312 return callMessage; 473 return callMessage;
313 }, 474 },
314 }; 475 };
315 476
316 /** 477 /**
317 * Help register calls for better error reporting. 478 * Help register calls for better error reporting.
318 * @type {CallHelper} 479 * @type {CallHelper}
319 **/ 480 */
320 var helper = new CallHelper(); 481 var helper = new CallHelper();
321 482
322 /** 483 /**
323 * true when testDone has been called. 484 * true when testDone has been called.
324 * @type {boolean} 485 * @type {boolean}
325 */ 486 */
326 var testIsDone = false; 487 var testIsDone = false;
327 488
328 /** 489 /**
329 * Holds the errors, if any, caught by expects so that the test case can 490 * Holds the errors, if any, caught by expects so that the test case can
330 * fail. Cleared when results are reported from runTest() or testDone(). 491 * fail. Cleared when results are reported from runTest() or testDone().
331 * @type {Array.<Error>} 492 * @type {Array.<Error>}
332 **/ 493 */
333 var errors = []; 494 var errors = [];
334 495
335 /** 496 /**
497 * URL to dummy WebUI page for testing framework.
498 * @type {string}
499 */
500 var DUMMY_URL = 'http://DummyURL';
501
502 /**
336 * Resets test state by clearing |errors| and |testIsDone| flags. 503 * Resets test state by clearing |errors| and |testIsDone| flags.
337 **/ 504 */
338 function resetTestState() { 505 function resetTestState() {
339 errors.splice(0, errors.length); 506 errors.splice(0, errors.length);
340 testIsDone = false; 507 testIsDone = false;
341 } 508 }
342 509
343 /** 510 /**
344 * Notifies the running browser test of the test results. Clears |errors|. 511 * Notifies the running browser test of the test results. Clears |errors|.
345 * @param {Array.<boolean, string>=} result When passed, this is used for the 512 * @param {Array.<boolean, string>=} result When passed, this is used for the
346 * testResult message. 513 * testResult message.
347 **/ 514 */
348 function testDone(result) { 515 function testDone(result) {
349 if (!testIsDone) { 516 if (!testIsDone) {
350 testIsDone = true; 517 testIsDone = true;
518 if (currentTestCase) {
519 currentTestCase.tearDown();
520 currentTestCase = null;
521 }
351 chrome.send('testResult', result ? result : testResult()); 522 chrome.send('testResult', result ? result : testResult());
352 errors.splice(0, errors.length); 523 errors.splice(0, errors.length);
353 } else { 524 } else {
354 console.warn('testIsDone already'); 525 console.warn('testIsDone already');
355 } 526 }
356 } 527 }
357 528
358 /** 529 /**
359 * Returns [success, message] & clears |errors|. 530 * Returns [success, message] & clears |errors|.
360 * @return {Array.<boolean, string>} 531 * @return {Array.<boolean, string>}
361 **/ 532 */
362 function testResult() { 533 function testResult() {
363 var result = [true, '']; 534 var result = [true, ''];
364 if (errors.length) { 535 if (errors.length) {
365 var message = ''; 536 var message = '';
366 for (var i = 0; i < errors.length; ++i) { 537 for (var i = 0; i < errors.length; ++i) {
367 message += 'Failed: ' + currentTestFunction + '(' + 538 message += 'Failed: ' + currentTestFunction + '(' +
368 currentTestArguments.map(JSON.stringify) + 539 currentTestArguments.map(JSON.stringify) +
369 ')\n' + errors[i].stack; 540 ')\n' + errors[i].stack;
370 } 541 }
371 result = [false, message]; 542 result = [false, message];
372 } 543 }
373 return result; 544 return result;
374 } 545 }
375 546
376 // Asserts. 547 // Asserts.
377 // Use the following assertions to verify a condition within a test. 548 // Use the following assertions to verify a condition within a test.
378 // If assertion fails, throw an Error with information pertinent to the test. 549 // If assertion fails, throw an Error with information pertinent to the test.
379 550
380 /** 551 /**
381 * When |test| !== true, aborts the current test. 552 * When |test| !== true, aborts the current test.
382 * @param {boolean} test The predicate to check against |expected|. 553 * @param {boolean} test The predicate to check against |expected|.
383 * @param {string=} message The message to include in the Error thrown. 554 * @param {string=} message The message to include in the Error thrown.
384 * @throws {Error} upon failure. 555 * @throws {Error} upon failure.
385 **/ 556 */
386 function assertTrue(test, message) { 557 function assertTrue(test, message) {
387 helper.registerCall(); 558 helper.registerCall();
388 if (test !== true) 559 if (test !== true)
389 throw new Error( 560 throw new Error(
390 'Test Error ' + helper.getCallMessage(message) + ': ' + test); 561 'Test Error ' + helper.getCallMessage(message) + ': ' + test);
391 } 562 }
392 563
393 /** 564 /**
394 * When |test| !== false, aborts the current test. 565 * When |test| !== false, aborts the current test.
395 * @param {boolean} test The predicate to check against |expected|. 566 * @param {boolean} test The predicate to check against |expected|.
396 * @param {string=} message The message to include in the Error thrown. 567 * @param {string=} message The message to include in the Error thrown.
397 * @throws {Error} upon failure. 568 * @throws {Error} upon failure.
398 **/ 569 */
399 function assertFalse(test, message) { 570 function assertFalse(test, message) {
400 helper.registerCall(); 571 helper.registerCall();
401 if (test !== false) 572 if (test !== false)
402 throw new Error( 573 throw new Error(
403 'Test Error ' + helper.getCallMessage(message) + ': ' + test); 574 'Test Error ' + helper.getCallMessage(message) + ': ' + test);
404 } 575 }
405 576
406 /** 577 /**
407 * When |val1| < |val2|, aborts the current test. 578 * When |val1| < |val2|, aborts the current test.
408 * @param {number} val1 The number expected to be >= |val2|. 579 * @param {number} val1 The number expected to be >= |val2|.
409 * @param {number} val2 The number expected to be < |val1|. 580 * @param {number} val2 The number expected to be < |val1|.
410 * @param {string=} message The message to include in the Error thrown. 581 * @param {string=} message The message to include in the Error thrown.
411 **/ 582 */
412 function assertGE(val1, val2, message) { 583 function assertGE(val1, val2, message) {
413 helper.registerCall(); 584 helper.registerCall();
414 if (val1 < val2) { 585 if (val1 < val2) {
415 throw new Error( 586 throw new Error(
416 'Test Error ' + helper.getCallMessage(message) + val1 + '<' + val2); 587 'Test Error ' + helper.getCallMessage(message) + val1 + '<' + val2);
417 } 588 }
418 } 589 }
419 590
420 /** 591 /**
421 * When |val1| <= |val2|, aborts the current test. 592 * When |val1| <= |val2|, aborts the current test.
422 * @param {number} val1 The number expected to be > |val2|. 593 * @param {number} val1 The number expected to be > |val2|.
423 * @param {number} val2 The number expected to be <= |val1|. 594 * @param {number} val2 The number expected to be <= |val1|.
424 * @param {string=} message The message to include in the Error thrown. 595 * @param {string=} message The message to include in the Error thrown.
425 **/ 596 */
426 function assertGT(val1, val2, message) { 597 function assertGT(val1, val2, message) {
427 helper.registerCall(); 598 helper.registerCall();
428 if (val1 <= val2) { 599 if (val1 <= val2) {
429 throw new Error( 600 throw new Error(
430 'Test Error ' + helper.getCallMessage(message) + val1 + '<=' + val2); 601 'Test Error ' + helper.getCallMessage(message) + val1 + '<=' + val2);
431 } 602 }
432 } 603 }
433 604
434 /** 605 /**
435 * When |expected| !== |actual|, aborts the current test. 606 * When |expected| !== |actual|, aborts the current test.
436 * @param {*} expected The expected value of |actual|. 607 * @param {*} expected The expected value of |actual|.
437 * @param {*} actual The predicate to check against |expected|. 608 * @param {*} actual The predicate to check against |expected|.
438 * @param {string=} message The message to include in the Error thrown. 609 * @param {string=} message The message to include in the Error thrown.
439 * @throws {Error} upon failure. 610 * @throws {Error} upon failure.
440 **/ 611 */
441 function assertEquals(expected, actual, message) { 612 function assertEquals(expected, actual, message) {
442 helper.registerCall(); 613 helper.registerCall();
443 if (expected != actual) { 614 if (expected != actual) {
444 throw new Error( 615 throw new Error(
445 'Test Error ' + helper.getCallMessage(message) + 616 'Test Error ' + helper.getCallMessage(message) +
446 '\nActual: ' + actual + '\nExpected: ' + expected); 617 '\nActual: ' + actual + '\nExpected: ' + expected);
447 } 618 }
448 if (typeof expected != typeof actual) { 619 if (typeof expected != typeof actual) {
449 throw new Error( 620 throw new Error(
450 'Test Error (type mismatch) ' + helper.getCallMessage(message) + 621 'Test Error (type mismatch) ' + helper.getCallMessage(message) +
451 '\nActual Type: ' + typeof actual + 622 '\nActual Type: ' + typeof actual +
452 '\nExpected Type:' + typeof expected); 623 '\nExpected Type:' + typeof expected);
453 } 624 }
454 } 625 }
455 626
456 /** 627 /**
457 * When |val1| > |val2|, aborts the current test. 628 * When |val1| > |val2|, aborts the current test.
458 * @param {number} val1 The number expected to be <= |val2|. 629 * @param {number} val1 The number expected to be <= |val2|.
459 * @param {number} val2 The number expected to be > |val1|. 630 * @param {number} val2 The number expected to be > |val1|.
460 * @param {string=} message The message to include in the Error thrown. 631 * @param {string=} message The message to include in the Error thrown.
461 **/ 632 */
462 function assertLE(val1, val2, message) { 633 function assertLE(val1, val2, message) {
463 helper.registerCall(); 634 helper.registerCall();
464 if (val1 > val2) { 635 if (val1 > val2) {
465 throw new Error( 636 throw new Error(
466 'Test Error ' + helper.getCallMessage(message) + val1 + '>' + val2); 637 'Test Error ' + helper.getCallMessage(message) + val1 + '>' + val2);
467 } 638 }
468 } 639 }
469 640
470 /** 641 /**
471 * When |val1| >= |val2|, aborts the current test. 642 * When |val1| >= |val2|, aborts the current test.
472 * @param {number} val1 The number expected to be < |val2|. 643 * @param {number} val1 The number expected to be < |val2|.
473 * @param {number} val2 The number expected to be >= |val1|. 644 * @param {number} val2 The number expected to be >= |val1|.
474 * @param {string=} message The message to include in the Error thrown. 645 * @param {string=} message The message to include in the Error thrown.
475 **/ 646 */
476 function assertLT(val1, val2, message) { 647 function assertLT(val1, val2, message) {
477 helper.registerCall(); 648 helper.registerCall();
478 if (val1 >= val2) { 649 if (val1 >= val2) {
479 throw new Error( 650 throw new Error(
480 'Test Error ' + helper.getCallMessage(message) + val1 + '>=' + val2); 651 'Test Error ' + helper.getCallMessage(message) + val1 + '>=' + val2);
481 } 652 }
482 } 653 }
483 654
484 /** 655 /**
485 * When |notExpected| === |actual|, aborts the current test. 656 * When |notExpected| === |actual|, aborts the current test.
486 * @param {*} notExpected The expected value of |actual|. 657 * @param {*} notExpected The expected value of |actual|.
487 * @param {*} actual The predicate to check against |notExpected|. 658 * @param {*} actual The predicate to check against |notExpected|.
488 * @param {string=} message The message to include in the Error thrown. 659 * @param {string=} message The message to include in the Error thrown.
489 * @throws {Error} upon failure. 660 * @throws {Error} upon failure.
490 **/ 661 */
491 function assertNotEquals(notExpected, actual, message) { 662 function assertNotEquals(notExpected, actual, message) {
492 helper.registerCall(); 663 helper.registerCall();
493 if (notExpected === actual) { 664 if (notExpected === actual) {
494 throw new Error( 665 throw new Error(
495 'Test Error ' + helper.getCallMessage(message) + 666 'Test Error ' + helper.getCallMessage(message) +
496 '\nActual: ' + actual + '\nnotExpected: ' + notExpected); 667 '\nActual: ' + actual + '\nnotExpected: ' + notExpected);
497 } 668 }
498 } 669 }
499 670
500 /** 671 /**
501 * Always aborts the current test. 672 * Always aborts the current test.
502 * @param {string=} message The message to include in the Error thrown. 673 * @param {string=} message The message to include in the Error thrown.
503 * @throws {Error} always. 674 * @throws {Error} always.
504 **/ 675 */
505 function assertNotReached(message) { 676 function assertNotReached(message) {
506 helper.registerCall(); 677 helper.registerCall();
507 throw new Error(helper.getCallMessage(message)); 678 throw new Error(helper.getCallMessage(message));
508 } 679 }
509 680
510 /** 681 /**
511 * Creates a function based upon a function that thows an exception on 682 * Creates a function based upon a function that thows an exception on
512 * failure. The new function stuffs any errors into the |errors| array for 683 * failure. The new function stuffs any errors into the |errors| array for
513 * checking by runTest. This allows tests to continue running other checks, 684 * checking by runTest. This allows tests to continue running other checks,
514 * while failing the overall test if any errors occurrred. 685 * while failing the overall test if any errors occurrred.
515 * @param {Function} assertFunc The function which may throw an Error. 686 * @param {Function} assertFunc The function which may throw an Error.
516 * @return {Function} A function that applies its arguments to |assertFunc|. 687 * @return {Function} A function that applies its arguments to |assertFunc|.
517 * @see errors 688 * @see errors
518 * @see runTest 689 * @see runTest
519 **/ 690 */
520 function createExpect(assertFunc) { 691 function createExpect(assertFunc) {
521 var expectFunc = function() { 692 var expectFunc = function() {
522 try { 693 try {
523 assertFunc.apply(null, arguments); 694 assertFunc.apply(null, arguments);
524 } catch (e) { 695 } catch (e) {
525 errors.push(e); 696 errors.push(e);
526 } 697 }
527 }; 698 };
528 expectFunc.isExpect = true; 699 expectFunc.isExpect = true;
529 expectFunc.expectName = assertFunc.name.replace(/^assert/, 'expect'); 700 expectFunc.expectName = assertFunc.name.replace(/^assert/, 'expect');
530 return expectFunc; 701 return expectFunc;
531 } 702 }
532 703
533 /** 704 /**
534 * This is the starting point for tests run by WebUIBrowserTest. If an error 705 * This is the starting point for tests run by WebUIBrowserTest. If an error
535 * occurs, it reports a failure and a message created by joining individual 706 * occurs, it reports a failure and a message created by joining individual
536 * error messages. This supports sync tests and async tests by calling 707 * error messages. This supports sync tests and async tests by calling
537 * testDone() when |isAsync| is not true, relying on async tests to call 708 * testDone() when |isAsync| is not true, relying on async tests to call
538 * testDone() when they complete. 709 * testDone() when they complete.
539 * @param {boolean} isAsync When false, call testDone() with the test result. 710 * @param {boolean} isAsync When false, call testDone() with the test result.
540 * @param {string} testFunction The function name to call. 711 * @param {string} testFunction The function name to call.
541 * @param {Array} testArguments The arguments to call |testFunction| with. 712 * @param {Array} testArguments The arguments to call |testFunction| with.
542 * @return {boolean} true always to signal successful execution (but not 713 * @return {boolean} true always to signal successful execution (but not
543 * necessarily successful results) of this test. 714 * necessarily successful results) of this test.
544 * @see errors 715 * @see errors
545 * @see runTestFunction 716 * @see runTestFunction
546 **/ 717 */
547 function runTest(isAsync, testFunction, testArguments) { 718 function runTest(isAsync, testFunction, testArguments) {
548 // Avoid eval() if at all possible, since it will not work on pages 719 // Avoid eval() if at all possible, since it will not work on pages
549 // that have enabled content-security-policy. 720 // that have enabled content-security-policy.
550 var testBody = this[testFunction]; // global object -- not a method. 721 var testBody = this[testFunction]; // global object -- not a method.
551 var testName = testFunction; 722 var testName = testFunction;
552 if (typeof testBody === "undefined") { 723 if (typeof testBody === "undefined") {
553 testBody = eval(testFunction); 724 testBody = eval(testFunction);
554 testName = testBody.toString(); 725 testName = testBody.toString();
555 } 726 }
556 if (testBody != RUN_TEST_F) { 727 if (testBody != RUN_TEST_F) {
(...skipping 10 matching lines...) Expand all
567 * expect to catch Errors. If |errors| is non-empty, it reports a failure and 738 * expect to catch Errors. If |errors| is non-empty, it reports a failure and
568 * a message by joining |errors|. Consumers can use this to use assert/expect 739 * a message by joining |errors|. Consumers can use this to use assert/expect
569 * functions asynchronously, but are then responsible for reporting errors to 740 * functions asynchronously, but are then responsible for reporting errors to
570 * the browser themselves through testDone(). 741 * the browser themselves through testDone().
571 * @param {string} testFunction The function name to report on failure. 742 * @param {string} testFunction The function name to report on failure.
572 * @param {Function} testBody The function to call. 743 * @param {Function} testBody The function to call.
573 * @param {Array} testArguments The arguments to call |testBody| with. 744 * @param {Array} testArguments The arguments to call |testBody| with.
574 * @return {Array.<boolean, string>} [test-succeeded, message-if-failed] 745 * @return {Array.<boolean, string>} [test-succeeded, message-if-failed]
575 * @see createExpect 746 * @see createExpect
576 * @see testDone 747 * @see testDone
577 **/ 748 */
578 function runTestFunction(testFunction, testBody, testArguments) { 749 function runTestFunction(testFunction, testBody, testArguments) {
579 currentTestFunction = testFunction; 750 currentTestFunction = testFunction;
580 currentTestArguments = testArguments; 751 currentTestArguments = testArguments;
581 createExpect(testBody).apply(null, testArguments); 752 createExpect(testBody).apply(null, testArguments);
582 return testResult(); 753 return testResult();
583 } 754 }
584 755
585 /** 756 /**
586 * Creates a new test case for the given |testFixture| and |testName|. Assumes 757 * Creates a new test case for the given |testFixture| and |testName|. Assumes
587 * |testFixture| describes a globally available subclass of type Test. 758 * |testFixture| describes a globally available subclass of type Test.
588 * @param {string} testFixture The fixture for this test case. 759 * @param {string} testFixture The fixture for this test case.
589 * @param {string} testName The name for this test case. 760 * @param {string} testName The name for this test case.
590 * @return {TestCase} A newly created TestCase. 761 * @return {TestCase} A newly created TestCase.
591 **/ 762 */
592 function createTestCase(testFixture, testName) { 763 function createTestCase(testFixture, testName) {
593 var fixtureConstructor = this[testFixture]; 764 var fixtureConstructor = this[testFixture];
594 var testBody = fixtureConstructor.testCaseBodies[testName]; 765 var testBody = fixtureConstructor.testCaseBodies[testName];
595 var fixture = new fixtureConstructor(); 766 var fixture = new fixtureConstructor();
596 fixture.name = testFixture; 767 fixture.name = testFixture;
597 return new TestCase(testName, fixture, testBody); 768 return new TestCase(testName, fixture, testBody);
598 } 769 }
599 770
600 /** 771 /**
601 * Used by WebUIBrowserTest to preload the javascript libraries at the 772 * Used by WebUIBrowserTest to preload the javascript libraries at the
602 * appropriate time for javascript injection into the current page. This 773 * appropriate time for javascript injection into the current page. This
603 * creates a test case and calls its PreLoad for any early initialization such 774 * creates a test case and calls its preLoad for any early initialization such
604 * as registering handlers before the page's javascript runs it's OnLoad 775 * as registering handlers before the page's javascript runs it's OnLoad
605 * method. This is called before the page is loaded, so the |chrome| object is 776 * method. This is called before the page is loaded, so the |chrome| object is
606 * not yet bound and this DOMContentLoaded listener will be called first to 777 * not yet bound and this DOMContentLoaded listener will be called first to
607 * override |chrome| in order to route messages registered in |sendCallbacks|. 778 * override |chrome| in order to route messages registered in |sendCallbacks|.
608 * @param {string} testFixture The test fixture name. 779 * @param {string} testFixture The test fixture name.
609 * @param {string} testName The test name. 780 * @param {string} testName The test name.
610 * @see sendCallbacks 781 * @see sendCallbacks
611 **/ 782 */
612 function preloadJavascriptLibraries(testFixture, testName) { 783 function preloadJavascriptLibraries(testFixture, testName) {
613 window.addEventListener('DOMContentLoaded', function() { 784 window.addEventListener('DOMContentLoaded', function() {
614 var oldChrome = chrome; 785 var oldChrome = chrome;
615 chrome = { 786 chrome = {
616 __proto__: oldChrome, 787 __proto__: oldChrome,
617 send: send, 788 send: send,
618 }; 789 };
790
791 // Override globals at load time so they will be defined.
792 for (var func in globalOverrides) {
793 assertNotEquals(undefined, this[func]);
794 var globalOverride = globalOverrides[func];
795 assertNotEquals(undefined, globalOverride);
796 assertEquals(undefined, globalOverride.original);
797 globalOverride.original = this[func];
798 this[func] = globalOverride.callback.bind(globalOverride.object);
799 }
619 }); 800 });
620 currentTestCase = createTestCase(testFixture, testName); 801 currentTestCase = createTestCase(testFixture, testName);
621 currentTestCase.PreLoad(); 802 currentTestCase.preLoad();
622 } 803 }
623 804
624 /** 805 /**
625 * During generation phase, this outputs; do nothing at runtime. 806 * During generation phase, this outputs; do nothing at runtime.
626 **/ 807 */
627 function GEN() {} 808 function GEN() {}
628 809
629 /** 810 /**
630 * At runtime, register the testName with a test fixture. Since this method 811 * At runtime, register the testName with a test fixture. Since this method
631 * doesn't have a test fixture, create a dummy fixture to hold its |name| 812 * doesn't have a test fixture, create a dummy fixture to hold its |name|
632 * and |testCaseBodies|. 813 * and |testCaseBodies|.
633 * @param {string} testCaseName The name of the test case. 814 * @param {string} testCaseName The name of the test case.
634 * @param {string} testName The name of the test function. 815 * @param {string} testName The name of the test function.
635 * @param {Function} testBody The body to execute when running this test. 816 * @param {Function} testBody The body to execute when running this test.
636 **/ 817 */
637 function TEST(testCaseName, testName, testBody) { 818 function TEST(testCaseName, testName, testBody) {
638 var fixtureConstructor = this[testCaseName]; 819 var fixtureConstructor = this[testCaseName];
639 if (fixtureConstructor === undefined) { 820 if (fixtureConstructor === undefined) {
640 fixtureConstructor = function() {}; 821 fixtureConstructor = function() {};
641 this[testCaseName] = fixtureConstructor; 822 this[testCaseName] = fixtureConstructor;
642 fixtureConstructor.prototype = { 823 fixtureConstructor.prototype = {
643 __proto__: Test.prototype, 824 __proto__: Test.prototype,
644 name: testCaseName, 825 name: testCaseName,
645 }; 826 };
646 fixtureConstructor.testCaseBodies = {}; 827 fixtureConstructor.testCaseBodies = {};
647 } 828 }
648 fixtureConstructor.testCaseBodies[testName] = testBody; 829 fixtureConstructor.testCaseBodies[testName] = testBody;
649 } 830 }
650 831
651 /** 832 /**
652 * At runtime, register the testName with its fixture. Stuff the |name| into 833 * At runtime, register the testName with its fixture. Stuff the |name| into
653 * the |testFixture|'s prototype, if needed, and the |testCaseBodies| into its 834 * the |testFixture|'s prototype, if needed, and the |testCaseBodies| into its
654 * constructor. 835 * constructor.
655 * @param {string} testFixture The name of the test fixture class. 836 * @param {string} testFixture The name of the test fixture class.
656 * @param {string} testName The name of the test function. 837 * @param {string} testName The name of the test function.
657 * @param {Function} testBody The body to execute when running this test. 838 * @param {Function} testBody The body to execute when running this test.
658 **/ 839 */
659 function TEST_F(testFixture, testName, testBody) { 840 function TEST_F(testFixture, testName, testBody) {
660 var fixtureConstructor = this[testFixture]; 841 var fixtureConstructor = this[testFixture];
661 if (!fixtureConstructor.prototype.name) 842 if (!fixtureConstructor.prototype.name)
662 fixtureConstructor.prototype.name = testFixture; 843 fixtureConstructor.prototype.name = testFixture;
663 if (fixtureConstructor['testCaseBodies'] === undefined) 844 if (fixtureConstructor['testCaseBodies'] === undefined)
664 fixtureConstructor.testCaseBodies = {}; 845 fixtureConstructor.testCaseBodies = {};
665 fixtureConstructor.testCaseBodies[testName] = testBody; 846 fixtureConstructor.testCaseBodies[testName] = testBody;
666 } 847 }
667 848
668 /** 849 /**
669 * RunJavascriptTestF uses this as the |testFunction| when invoking 850 * RunJavascriptTestF uses this as the |testFunction| when invoking
670 * runTest. If |currentTestCase| is non-null at this point, verify that 851 * runTest. If |currentTestCase| is non-null at this point, verify that
671 * |testFixture| and |testName| agree with the preloaded values. Create 852 * |testFixture| and |testName| agree with the preloaded values. Create
672 * |currentTestCase|, if needed, run it, and clear the |currentTestCase|. 853 * |currentTestCase|, if needed, run it, and clear the |currentTestCase|.
673 * @param {string} testFixture The name of the test fixture class. 854 * @param {string} testFixture The name of the test fixture class.
674 * @param {string} testName The name of the test function. 855 * @param {string} testName The name of the test function.
675 * @see preloadJavascriptLibraries 856 * @see preloadJavascriptLibraries
676 * @see runTest 857 * @see runTest
677 **/ 858 */
678 function RUN_TEST_F(testFixture, testName) { 859 function RUN_TEST_F(testFixture, testName) {
679 try { 860 if (!currentTestCase)
680 if (!currentTestCase) 861 currentTestCase = createTestCase(testFixture, testName);
681 currentTestCase = createTestCase(testFixture, testName); 862 assertEquals(currentTestCase.name, testName);
682 assertEquals(currentTestCase.name, testName); 863 assertEquals(currentTestCase.fixture.name, testFixture);
683 assertEquals(currentTestCase.fixture.name, testFixture); 864 console.log('Running TestCase ' + testFixture + '.' + testName);
684 console.log('Running TestCase ' + testFixture + '.' + testName); 865 currentTestCase.run();
685 currentTestCase.Run(); 866 }
686 } finally { 867
687 currentTestCase = null; 868 /**
869 * This Mock4JS matcher object pushes each |actualArgument| parameter to
870 * match() calls onto |args|.
871 * @param {Array} args The array to push |actualArgument| onto.
872 * @param {Object} realMatcher The real matcher check arguments with.
873 * @constructor
874 * @extends {realMatcher}
875 */
876 function SaveMockArgumentMatcher(args, realMatcher) {
877 this.arguments_ = args;
878 this.realMatcher_ = realMatcher;
879 }
880
881 SaveMockArgumentMatcher.prototype = {
882 /**
883 * Holds the arguments to push each |actualArgument| onto.
884 * @type {Array}
885 * @private
886 */
887 arguments_: null,
888
889 /**
890 * The real Mock4JS matcher object to check arguments with.
891 * @type {Object}
892 */
893 realMatcher_: null,
894
895 /**
896 * Pushes |actualArgument| onto |arguments_| and call |realMatcher_|. Clears
897 * |arguments_| on non-match.
898 * @param {*} actualArgument The argument to match and save.
899 * @return {boolean} Result of calling the |realMatcher|.
900 */
901 argumentMatches: function(actualArgument) {
902 this.arguments_.push(actualArgument);
903 var match = this.realMatcher_.argumentMatches(actualArgument);
904 if (!match)
905 this.arguments_.splice(0, this.arguments_.length);
906
907 return match;
908 },
909
910 /**
911 * Proxy to |realMatcher_| for description.
912 * @return {string} Description of this Mock4JS matcher.
913 */
914 describe: function() {
915 return this.realMatcher_.describe();
916 },
917 };
918
919 /**
920 * Actions invoked by Mock4JS's "will()" syntax do not receive arguments from
921 * the mocked method. This class works with SaveMockArgumentMatcher to save
922 * arguments so that the invoked Action can pass arguments through to the
923 * invoked function.
924 * @param {!Object} realMatcher The real matcher to perform matching with.
925 * @constructor
926 */
927 function SaveMockArguments() {
928 this.arguments = [];
929 }
930
931 SaveMockArguments.prototype = {
932 /**
933 * Wraps the |realMatcher| with an object which will push its argument onto
934 * |arguments| and call realMatcher.
935 * @param {Object} realMatcher A Mock4JS matcher object for this argument.
936 * @return {SaveMockArgumentMatcher} A new matcher which will push its
937 * argument onto |arguments|.
938 */
939 match: function(realMatcher) {
940 return new SaveMockArgumentMatcher(this.arguments, realMatcher);
941 },
942
943 /**
944 * Remember the argument passed to this stub invocation.
945 * @type {Array}
946 */
947 arguments: null,
948 };
949
950 /**
951 * CallFunctionAction is provided to allow mocks to have side effects.
952 * @param {Object} obj The object to set |this| to when calling |func_|.
953 * @param {?SaveMockArguments} savedArgs when non-null, saved arguments are
954 * passed to |func|.
955 * @param {Function} func The function to call.
956 * @param {Array=} args Any arguments to pass to func.
957 * @constructor
958 */
959 function CallFunctionAction(obj, savedArgs, func, args) {
960 this.obj_ = obj;
961 this.savedArgs_ = savedArgs;
962 this.func_ = func;
963 this.args_ = args ? args : [];
964 }
965
966 CallFunctionAction.prototype = {
967 /**
968 * Set |this| to |obj_| when calling |func_|.
969 * @type {?Object}
970 */
971 obj_: null,
972
973 /**
974 * The SaveMockArguments to hold arguments when invoking |func_|.
975 * @type {?SaveMockArguments}
976 * @private
977 */
978 savedArgs_: null,
979
980 /**
981 * The function to call when invoked.
982 * @type {!Function}
983 * @private
984 */
985 func_: null,
986
987 /**
988 * Arguments to pass to |func_| when invoked.
989 * @type {!Array}
990 */
991 args_: null,
992
993 /**
994 * Accessor for |func_|.
995 * @return {Function} The function to invoke.
996 */
997 get func() {
998 return this.func_;
999 },
1000
1001 /**
1002 * Called by Mock4JS when using .will() to specify actions for stubs() or
1003 * expects(). Clears |savedArgs_| so it can be reused.
1004 * @return The results of calling |func_| with the concatenation of
1005 * |savedArgs_| and |args_|.
1006 */
1007 invoke: function() {
1008 var prependArgs = [];
1009 if (this.savedArgs_) {
1010 prependArgs = this.savedArgs_.arguments.splice(
1011 0, this.savedArgs_.arguments.length);
1012 }
1013 return this.func.apply(this.obj_, prependArgs.concat(this.args_));
1014 },
1015
1016 /**
1017 * Describe this action to Mock4JS.
1018 * @return {string} A description of this action.
1019 */
1020 describe: function() {
1021 return 'calls the given function with saved arguments and ' + this.args_;
688 } 1022 }
689 } 1023 };
690 1024
691 /** 1025 /**
692 * CallFunctionAction is provided to allow mocks to have side effects. 1026 * Syntactic sugar for use with will() on a Mock4JS.Mock.
693 * @param {Function} func The function to call. 1027 * @param {Function} func The function to call when the method is invoked.
1028 * @param {...*} var_args Arguments to pass when calling func.
1029 * @return {CallFunctionAction} Action for use in will.
1030 */
1031 function callFunction(func) {
1032 return new CallFunctionAction(
1033 null, null, func, Array.prototype.slice.call(arguments, 1));
1034 }
1035
1036 /**
1037 * Syntactic sugar for use with will() on a Mock4JS.Mock.
1038 * @param {SaveMockArguments} savedArgs Arguments saved with this object
1039 * are passed to |func|.
1040 * @param {Function} func The function to call when the method is invoked.
1041 * @param {...*} var_args Arguments to pass when calling func.
1042 * @return {CallFunctionAction} Action for use in will.
1043 */
1044 function callFunctionWithSavedArgs(savedArgs, func) {
1045 return new CallFunctionAction(
1046 null, savedArgs, func, Array.prototype.slice.call(arguments, 2));
1047 }
1048
1049 /**
1050 * CallGlobalAction as a subclass of CallFunctionAction looks up the original
1051 * global object in |globalOverrides| using |funcName| as the key. This allows
1052 * tests, which need to wait until a global function to be called in order to
1053 * start the test to run the original function. When used with runAllActions
1054 * or runAllActionsAsync, Mock4JS expectations may call start or continue the
1055 * test after calling the original function.
1056 * @param {?SaveMockArguments} savedArgs when non-null, saved arguments are
1057 * passed to the global function |funcName|.
1058 * @param {string} funcName The name of the global function to call.
694 * @param {Array} args Any arguments to pass to func. 1059 * @param {Array} args Any arguments to pass to func.
695 * @constructor 1060 * @constructor
696 **/ 1061 * @extends {CallFunctionAction}
697 function CallFunctionAction(func, args) { 1062 * @see globalOverrides
698 this._func = func; 1063 */
699 this._args = args; 1064 function CallGlobalAction(savedArgs, funcName, args) {
700 } 1065 CallFunctionAction.call(this, null, savedArgs, funcName, args);
701 1066 }
702 CallFunctionAction.prototype = { 1067
1068 CallGlobalAction.prototype = {
1069 __proto__: CallFunctionAction.prototype,
1070
1071 /**
1072 * Fetch and return the original global function to call.
1073 * @return {Function} The global function to invoke.
1074 * @override
1075 */
1076 get func() {
1077 var func = globalOverrides[this.func_].original;
1078 assertNotEquals(undefined, func);
1079 return func;
1080 },
1081 };
1082
1083 /**
1084 * Syntactic sugar for use with will() on a Mock4JS.Mock.
1085 * @param {SaveMockArguments} savedArgs Arguments saved with this object
1086 * are passed to the global function |funcName|.
1087 * @param {string} funcName The name of a registered mock global function to
1088 * call when the method is invoked.
1089 * @param {...*} var_args Arguments to pass when calling func.
1090 * @return {CallGlobalAction} Action for use in Mock4JS will().
1091 */
1092 function callGlobalWithSavedArgs(savedArgs, funcName) {
mmenke 2011/08/24 15:27:50 Might be nice to have a way to have this record, a
Sheridan Rawlins 2011/08/24 21:15:45 You can do this with runAllActionsAsync. See exam
1093 return new CallGlobalAction(
1094 savedArgs, funcName, Array.prototype.slice.call(arguments, 2));
1095 }
1096
1097 /**
1098 * When to call testDone().
1099 * @enum {number}
1100 */
1101 var WhenTestDone = {
1102 /**
1103 * Default for the method called.
1104 */
1105 DEFAULT: -1,
1106
1107 /**
1108 * Never call testDone().
1109 */
1110 NEVER: 0,
1111
1112 /**
1113 * Call testDone() on assert failure.
1114 */
1115 ASSERT: 1,
1116
1117 /**
1118 * Call testDone() if there are any assert or expect failures.
1119 */
1120 EXPECT: 2,
1121
1122 /**
1123 * Always call testDone().
1124 */
1125 ALWAYS: 3,
1126 };
1127
1128 /**
1129 * Runs all |actions|.
1130 * @param {boolean} isAsync When true, call testDone() on Errors.
1131 * @param {WhenTestDone} whenTestDone Call testDone() at the appropriate
1132 * time.
1133 * @param {Array.<Object>} actions Actions to run.
1134 * @constructor
1135 */
1136 function RunAllAction(isAsync, whenTestDone, actions) {
1137 this.isAsync_ = isAsync;
1138 this.whenTestDone_ = whenTestDone;
1139 this.actions_ = actions;
1140 }
1141
1142 RunAllAction.prototype = {
1143 /**
1144 * When true, call testDone() on Errors.
1145 * @type {boolean}
1146 * @private
1147 */
1148 isAsync_: false,
1149
1150 /**
1151 * Call testDone() at appropriate time.
1152 * @type {WhenTestDone}
1153 * @private
1154 * @see WhenTestDone
1155 */
1156 whenTestDone_: WhenTestDone.ASSERT,
1157
1158 /**
1159 * Holds the actions to execute when invoked.
1160 * @type {Array}
1161 * @private
1162 */
1163 actions_: null,
1164
1165 /**
1166 * Runs all |actions_|, returning the last one. When running in sync mode,
1167 * throws any exceptions to be caught by runTest() or
1168 * runTestFunction(). Call testDone() according to |whenTestDone_| setting.
1169 */
703 invoke: function() { 1170 invoke: function() {
704 return this._func.apply(null, this._args); 1171 try {
705 }, 1172 var result;
1173 for(var i = 0; i < this.actions_.length; ++i)
1174 result = this.actions_[i].invoke();
1175
1176 if ((this.whenTestDone_ == WhenTestDone.EXPECT && errors.length) ||
1177 this.whenTestDone_ == WhenTestDone.ALWAYS)
1178 testDone();
1179
1180 return result;
1181 } catch (e) {
1182 if (!(e instanceof Error))
1183 e = new Error(e.toString());
1184
1185 if (!this.isAsync_)
1186 throw e;
1187
1188 errors.push(e);
1189 if (this.whenTestDone_ == WhenTestDone.ASSERT ||
1190 this.whenTestDone_ == WhenTestDone.ALWAYS) {
mmenke 2011/08/24 15:27:50 Important: Should also abort on WhenTestDone.EXPE
Sheridan Rawlins 2011/08/24 21:15:45 Ok. How 'bout != NEVER. Done. On 2011/08/24 15:
1191 testDone();
1192 }
1193 }
1194 },
1195
1196 /**
1197 * Describe this action to Mock4JS.
1198 * @return {string} A description of this action.
1199 */
706 describe: function() { 1200 describe: function() {
707 return 'calls the given function with arguments ' + this._args; 1201 return 'Calls all actions: ' + this.actions_;
708 } 1202 },
709 }; 1203 };
710 1204
711 /** 1205 /**
712 * Syntactic sugar for will() on a Mock4JS.Mock. 1206 * Syntactic sugar for use with will() on a Mock4JS.Mock.
713 * @param {Function} func the function to call when the method is invoked. 1207 * @param {...Object} var_actions Actions to run.
714 * @param {...*} var_args arguments to pass when calling func. 1208 * @return {RunAllAction} Action for use in will.
715 **/ 1209 */
716 function callFunction(func) { 1210 function runAllActions() {
717 return new CallFunctionAction(func, 1211 return new RunAllAction(false, WhenTestDone.NEVER,
718 Array.prototype.slice.call(arguments, 1)); 1212 Array.prototype.slice.call(arguments));
719 } 1213 }
720 1214
721 /** 1215 /**
722 * Allow mock stubs() and expects() to know what arguments were passed to the 1216 * Syntactic sugar for use with will() on a Mock4JS.Mock.
723 * |realMatcher|. 1217 * @param {WhenTestDone} whenTestDone Call testDone() at the appropriate
724 * @param {!Object} realMatcher The real matcher to perform matching with. 1218 * time.
725 * @constructor 1219 * @param {...Object} var_actions Actions to run.
726 **/ 1220 * @return {RunAllAction} Action for use in will.
727 function SaveArgumentsMatcher(realMatcher) { 1221 */
728 this.realMatcher_ = realMatcher; 1222 function runAllActionsAsync(whenTestDone) {
729 } 1223 return new RunAllAction(true, whenTestDone,
730 1224 Array.prototype.slice.call(arguments, 1));
731 SaveArgumentsMatcher.prototype = { 1225 }
732 /**
733 * Remember the argument passed to this stub invocation.
734 * @type {*}
735 **/
736 argument: undefined,
737
738 /**
739 * @type {Object} the object performing the real match.
740 * @private
741 */
742 realMatcher_: null,
743
744 /**
745 * Saves |actualArgument| for later use by the mock stub or expect.
746 * @param {*} actualArgument The argument to match and save.
747 * @return {boolean} value of calling the |realMatcher_|.
748 **/
749 argumentMatches: function(actualArgument) {
750 this.argument = actualArgument;
751 return this.realMatcher_.argumentMatches.call(this.realMatcher_,
752 actualArgument);
753 },
754
755 /**
756 * Generic description for this Matcher object.
757 * @return {string} description of the matcher for this argument.
758 **/
759 describe: function() {
760 return 'SaveArguments(' +
761 this.realMatcher_.describe.call(this.realMatcher_) + ')';
762 },
763 };
764 1226
765 // Exports. 1227 // Exports.
766 testing.Test = Test; 1228 testing.Test = Test;
767 window.testDone = testDone; 1229 window.testDone = testDone;
768 window.assertTrue = assertTrue; 1230 window.assertTrue = assertTrue;
769 window.assertFalse = assertFalse; 1231 window.assertFalse = assertFalse;
770 window.assertGE = assertGE; 1232 window.assertGE = assertGE;
771 window.assertGT = assertGT; 1233 window.assertGT = assertGT;
772 window.assertEquals = assertEquals; 1234 window.assertEquals = assertEquals;
773 window.assertLE = assertLE; 1235 window.assertLE = assertLE;
774 window.assertLT = assertLT; 1236 window.assertLT = assertLT;
775 window.assertNotEquals = assertNotEquals; 1237 window.assertNotEquals = assertNotEquals;
776 window.assertNotReached = assertNotReached; 1238 window.assertNotReached = assertNotReached;
777 window.callFunction = callFunction; 1239 window.callFunction = callFunction;
1240 window.callFunctionWithSavedArgs = callFunctionWithSavedArgs;
1241 window.callGlobalWithSavedArgs = callGlobalWithSavedArgs;
778 window.expectTrue = createExpect(assertTrue); 1242 window.expectTrue = createExpect(assertTrue);
779 window.expectFalse = createExpect(assertFalse); 1243 window.expectFalse = createExpect(assertFalse);
780 window.expectGE = createExpect(assertGE); 1244 window.expectGE = createExpect(assertGE);
781 window.expectGT = createExpect(assertGT); 1245 window.expectGT = createExpect(assertGT);
782 window.expectEquals = createExpect(assertEquals); 1246 window.expectEquals = createExpect(assertEquals);
783 window.expectLE = createExpect(assertLE); 1247 window.expectLE = createExpect(assertLE);
784 window.expectLT = createExpect(assertLT); 1248 window.expectLT = createExpect(assertLT);
785 window.expectNotEquals = createExpect(assertNotEquals); 1249 window.expectNotEquals = createExpect(assertNotEquals);
786 window.expectNotReached = createExpect(assertNotReached); 1250 window.expectNotReached = createExpect(assertNotReached);
787 window.preloadJavascriptLibraries = preloadJavascriptLibraries; 1251 window.preloadJavascriptLibraries = preloadJavascriptLibraries;
788 window.registerMessageCallback = registerMessageCallback; 1252 window.registerMessageCallback = registerMessageCallback;
1253 window.registerMockGlobals = registerMockGlobals;
789 window.registerMockMessageCallbacks = registerMockMessageCallbacks; 1254 window.registerMockMessageCallbacks = registerMockMessageCallbacks;
790 window.resetTestState = resetTestState; 1255 window.resetTestState = resetTestState;
1256 window.runAllActions = runAllActions;
1257 window.runAllActionsAsync = runAllActionsAsync;
791 window.runTest = runTest; 1258 window.runTest = runTest;
792 window.runTestFunction = runTestFunction; 1259 window.runTestFunction = runTestFunction;
793 window.SaveArgumentsMatcher = SaveArgumentsMatcher; 1260 window.SaveMockArguments = SaveMockArguments;
1261 window.DUMMY_URL = DUMMY_URL;
794 window.TEST = TEST; 1262 window.TEST = TEST;
795 window.TEST_F = TEST_F; 1263 window.TEST_F = TEST_F;
796 window.GEN = GEN; 1264 window.GEN = GEN;
1265 window.WhenTestDone = WhenTestDone;
797 1266
798 // Import the Mock4JS helpers. 1267 // Import the Mock4JS helpers.
799 Mock4JS.addMockSupport(window); 1268 Mock4JS.addMockSupport(window);
800 })(); 1269 })(('window' in this) ? window : this);
OLDNEW
« chrome/test/data/webui/async_gen.js ('K') | « chrome/test/data/webui/print_preview.js ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698