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

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