OLD | NEW |
---|---|
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 **/ |
arv (Not doing code reviews)
2011/08/22 20:57:18
Close these JSDoc comments with */ instead of **/
Sheridan Rawlins
2011/08/23 01:06:15
Done.
| |
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 |
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} |
(...skipping 15 matching lines...) Expand all Loading... | |
33 // Provide global objects for generation case. | 33 // Provide global objects for generation case. |
34 if (this['window'] === undefined) | 34 if (this['window'] === undefined) |
35 this['window'] = this; | 35 this['window'] = this; |
36 if (this['chrome'] === undefined) { | 36 if (this['chrome'] === undefined) { |
37 this['chrome'] = { | 37 this['chrome'] = { |
38 send: function() {}, | 38 send: function() {}, |
39 }; | 39 }; |
40 } | 40 } |
41 if (this['console'] === undefined) { | 41 if (this['console'] === undefined) { |
42 this['console'] = { | 42 this['console'] = { |
43 log: print, | 43 log: print, |
arv (Not doing code reviews)
2011/08/22 20:57:18
what about error and info?
Sheridan Rawlins
2011/08/23 01:06:15
Only the window is needed, actually. I nuked thes
| |
44 }; | 44 }; |
45 } | 45 } |
46 | 46 |
47 /** | 47 /** |
48 * This class will be exported as testing.Test, and is provided to hold the | 48 * 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 | 49 * fixture's configuration and callback methods for the various phases of |
50 * invoking a test. It is called "Test" rather than TestFixture to roughly | 50 * invoking a test. It is called "Test" rather than TestFixture to roughly |
51 * mimic the gtest's class names. | 51 * mimic the gtest's class names. |
52 * @constructor | 52 * @constructor |
53 **/ | 53 **/ |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
92 | 92 |
93 /** | 93 /** |
94 * When set to a non-null string, auto-generate typedef before generating | 94 * When set to a non-null string, auto-generate typedef before generating |
95 * TEST*: {@code typedef typedefCppFixture testFixture}. | 95 * TEST*: {@code typedef typedefCppFixture testFixture}. |
96 * @type {string} | 96 * @type {string} |
97 **/ | 97 **/ |
98 typedefCppFixture: 'WebUIBrowserTest', | 98 typedefCppFixture: 'WebUIBrowserTest', |
99 | 99 |
100 /** | 100 /** |
101 * This should be initialized by the test fixture and can be referenced | 101 * This should be initialized by the test fixture and can be referenced |
102 * during the test run. | 102 * during the test run. It holds any mocked handler methods. |
103 * @type {Mock4JS.Mock} | 103 * @type {?Mock4JS.Mock} |
104 **/ | 104 **/ |
105 mockHandler: null, | 105 mockHandler: null, |
106 | 106 |
107 /** | 107 /** |
108 * This should be initialized by the test fixture and can be referenced | |
109 * during the test run. It holds any mocked global functions. | |
110 * @type {?Mock4JS.Mock} | |
111 **/ | |
112 mockGlobals: null, | |
113 | |
114 /** | |
115 * Value is passed through call to C++ RunJavascriptF to invoke this test. | |
116 * @type {boolean} | |
117 **/ | |
118 isAsync: false, | |
119 | |
120 /** | |
108 * Override this method to perform initialization during preload (such as | 121 * Override this method to perform initialization during preload (such as |
109 * creating mocks and registering handlers). | 122 * creating mocks and registering handlers). |
110 * @type {Function} | 123 * @type {Function} |
111 **/ | 124 **/ |
112 PreLoad: function() {}, | 125 PreLoad: function() {}, |
arv (Not doing code reviews)
2011/08/22 20:57:18
Can the names of these be fixed?
Sheridan Rawlins
2011/08/23 01:06:15
Done.
| |
113 | 126 |
114 /** | 127 /** |
115 * Override this method to perform tasks before running your test. | 128 * Override this method to perform tasks before running your test. |
116 * @type {Function} | 129 * @type {Function} |
117 **/ | 130 **/ |
118 SetUp: function() {}, | 131 SetUp: function() {}, |
119 | 132 |
120 /** | 133 /** |
121 * Override this method to perform tasks after running your test. If you | 134 * Override this method to perform tasks after running your test. If you |
122 * create a mock class, you must call Mock4JS.verifyAllMocks() in this | 135 * create a mock class, you must call Mock4JS.verifyAllMocks() in this |
123 * phase. | 136 * phase. |
124 * @type {Function} | 137 * @type {Function} |
125 **/ | 138 **/ |
126 TearDown: function() { | 139 TearDown: function() { |
127 Mock4JS.verifyAllMocks(); | 140 Mock4JS.verifyAllMocks(); |
128 } | 141 }, |
142 | |
143 /** | |
144 * Called to run the body from the perspective of this fixture. | |
145 * @type {Function} | |
146 */ | |
147 RunTest: function(testBody) { | |
148 testBody.call(this); | |
149 }, | |
150 | |
151 /** | |
152 * @param {boolean} alwaysDone When true, always call testDone(). | |
153 * @param {Function} completion The function to call to complete the test. | |
154 * @return {function(): void} Return a function, bound to this test fixture, | |
155 * which continues the test. | |
156 **/ | |
157 continueTest: function(alwaysDone, completion) { | |
158 var completionAction = new CallFunctionAction( | |
159 this, null, completion, null); | |
160 var runAll = new RunAllAction( | |
161 true, alwaysDone, [completionAction]); | |
162 return function() { | |
163 runAll.invoke(); | |
164 }; | |
165 }, | |
166 | |
167 /** | |
168 * Call this during SetUp to defer the call to RunTest() until later. The | |
169 * caller must call the returned function at some point to run the test. | |
170 * @type {Function} | |
171 * @return {function(): void} A function which will run the current body of | |
172 * the currentTestCase. | |
173 */ | |
174 deferRunTest: function() { | |
175 return currentTestCase.deferRunTest(); | |
176 }, | |
129 }; | 177 }; |
130 | 178 |
131 /** | 179 /** |
132 * This class is not exported and is available to hold the state of the | 180 * This class is not exported and is available to hold the state of the |
133 * |currentTestCase| throughout preload and test run. | 181 * |currentTestCase| throughout preload and test run. |
134 * @param {string} name The name of the test case. | 182 * @param {string} name The name of the test case. |
135 * @param {Test} fixture The fixture object for this test case. | 183 * @param {Test} fixture The fixture object for this test case. |
136 * @param {Function} body The code to run for the test. | 184 * @param {Function} body The code to run for the test. |
137 * @constructor | 185 * @constructor |
138 **/ | 186 **/ |
139 function TestCase(name, fixture, body) { | 187 function TestCase(name, fixture, body) { |
140 this.name = name; | 188 this.name = name; |
141 this.fixture = fixture; | 189 this.fixture = fixture; |
142 this.body = body; | 190 this.body = body; |
143 } | 191 } |
144 | 192 |
145 TestCase.prototype = { | 193 TestCase.prototype = { |
194 /** | |
195 * The name of this test. | |
196 * @type {string} | |
197 */ | |
146 name: null, | 198 name: null, |
199 | |
200 /** | |
201 * The test fixture to set |this| to when running the test |body|. | |
202 * @type {testing.Test} | |
203 */ | |
147 fixture: null, | 204 fixture: null, |
205 | |
206 /** | |
207 * The test body to execute in RunTest(). | |
208 * @type {Function} | |
209 **/ | |
148 body: null, | 210 body: null, |
149 | 211 |
150 /** | 212 /** |
213 * True when the test fixture will run the test later. | |
214 * @type {boolean} | |
215 * @private | |
216 */ | |
217 deferred_: false, | |
218 | |
219 /** | |
151 * Called at preload time, proxies to the fixture. | 220 * Called at preload time, proxies to the fixture. |
152 * @type {Function} | 221 * @type {Function} |
153 **/ | 222 **/ |
154 PreLoad: function(name) { | 223 PreLoad: function(name) { |
155 if (this.fixture) | 224 if (this.fixture) |
156 this.fixture.PreLoad(); | 225 this.fixture.PreLoad(); |
157 }, | 226 }, |
158 | 227 |
159 /** | 228 /** |
229 * Called before a test runs. | |
230 **/ | |
231 SetUp: function() { | |
232 if (this.fixture) | |
233 this.fixture.SetUp(); | |
234 }, | |
235 | |
236 /** | |
237 * Called before a test is torn down (by testDone()). | |
238 **/ | |
239 TearDown: function() { | |
240 if (this.fixture) | |
241 this.fixture.TearDown(); | |
242 }, | |
243 | |
244 /** | |
245 * Called to run this test's body. | |
246 **/ | |
247 RunTest: function() { | |
248 if (this.body && this.fixture) | |
249 this.fixture.RunTest(this.body); | |
250 }, | |
251 | |
252 /** | |
160 * Runs this test case with |this| set to the |fixture|. | 253 * Runs this test case with |this| set to the |fixture|. |
161 * | 254 * |
162 * Note: Tests created with TEST_F may depend upon |this| being set to an | 255 * 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 | 256 * instance of this.fixture. The current implementation of TEST creates a |
164 * dummy constructor, but tests created with TEST should not rely on |this| | 257 * dummy constructor, but tests created with TEST should not rely on |this| |
165 * being set. | 258 * being set. |
166 * @type {Function} | 259 * @type {Function} |
167 **/ | 260 **/ |
168 Run: function() { | 261 Run: function() { |
169 if (this.fixture) | 262 try { |
170 this.fixture.SetUp(); | 263 this.SetUp(); |
171 if (this.body) | 264 } catch(e) { |
172 this.body.call(this.fixture); | 265 console.error(e.stack); |
173 if (this.fixture) | 266 } |
174 this.fixture.TearDown(); | 267 |
268 if (!this.deferred_) | |
269 this.RunTest(); | |
270 | |
271 // TearDown called by testDone(). | |
175 }, | 272 }, |
273 | |
274 /** | |
275 * Cause this TestCase to be deferred (don't call RunTest()) until the | |
276 * returned function is called. | |
277 * @type {Function} | |
278 * @return {function(): void} A function thatwill run this TestCase when | |
279 * called. | |
280 */ | |
281 deferRunTest: function() { | |
282 this.deferred_ = true; | |
283 var completionAction = new CallFunctionAction( | |
284 this, null, this.RunTest, null); | |
285 var runAll = new RunAllAction( | |
286 true, true, [completionAction]); | |
287 return function() { | |
288 runAll.invoke(); | |
289 }; | |
290 }, | |
291 | |
176 }; | 292 }; |
177 | 293 |
178 /** | 294 /** |
179 * Registry of javascript-defined callbacks for {@code chrome.send}. | 295 * Registry of javascript-defined callbacks for {@code chrome.send}. |
180 * @type {Object} | 296 * @type {Object} |
181 **/ | 297 **/ |
182 var sendCallbacks = {}; | 298 var sendCallbacks = {}; |
183 | 299 |
184 /** | 300 /** |
185 * Registers the message, object and callback for {@code chrome.send} | 301 * Registers the message, object and callback for {@code chrome.send} |
186 * @param {string} name The name of the message to route to this |callback|. | 302 * @param {string} name The name of the message to route to this |callback|. |
187 * @param {Object} messageHAndler Pass as |this| when calling the |callback|. | 303 * @param {Object} messageHandler Pass as |this| when calling the |callback|. |
188 * @param {function(...)} callback Called by {@code chrome.send}. | 304 * @param {function(...)} callback Called by {@code chrome.send}. |
189 * @see sendCallbacks | 305 * @see sendCallbacks |
190 **/ | 306 **/ |
191 function registerMessageCallback(name, messageHandler, callback) { | 307 function registerMessageCallback(name, messageHandler, callback) { |
192 sendCallbacks[name] = [messageHandler, callback]; | 308 sendCallbacks[name] = [messageHandler, callback]; |
193 } | 309 } |
194 | 310 |
195 /** | 311 /** |
196 * Register all methods of {@code mockClass.prototype} with messages of the | 312 * 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 | 313 * same name as the method, using the proxy of the |mockObject| as the |
198 * |messageHandler| when registering. | 314 * |messageHandler| when registering. |
199 * @param {Mock4JS.Mock} mockObject The mock to register callbacks against. | 315 * @param {Mock4JS.Mock} mockObject The mock to register callbacks against. |
200 * @param {function(new:Object)} mockClAss Constructor for the mocked class. | 316 * @param {function(new:Object)} mockClAss Constructor for the mocked class. |
201 * @see registerMessageCallback | 317 * @see registerMessageCallback |
202 **/ | 318 **/ |
203 function registerMockMessageCallbacks(mockObject, mockClass) { | 319 function registerMockMessageCallbacks(mockObject, mockClass) { |
204 var mockProxy = mockObject.proxy(); | 320 var mockProxy = mockObject.proxy(); |
205 for (func in mockClass.prototype) { | 321 for (var func in mockClass.prototype) { |
206 if (typeof(mockClass.prototype[func]) == 'function') { | 322 if (typeof(mockClass.prototype[func]) == 'function') { |
207 registerMessageCallback(func, | 323 registerMessageCallback(func, mockProxy, mockProxy[func]); |
208 mockProxy, | |
209 mockProxy[func]); | |
210 } | 324 } |
211 } | 325 } |
212 } | 326 } |
327 | |
328 /** | |
329 * Holds the mapping of name -> global override information. | |
330 * @type {Object} | |
331 **/ | |
332 var globalOverrides = {}; | |
333 | |
334 /** | |
335 * Registers the global function name, object and callback. | |
336 * @param {string} name The name of the message to route to this |callback|. | |
337 * @param {Object} object Pass as |this| when calling the |callback|. | |
338 * @param {function(...)} callback Called by {@code chrome.send}. | |
339 **/ | |
340 function registerMockGlobal(name, object, callback) { | |
341 assertEquals(undefined, globalOverrides[name]); | |
342 globalOverrides[name] = { | |
343 object: object, | |
344 callback: callback, | |
345 }; | |
346 } | |
347 | |
348 /** | |
349 * Register all methods of {@code mockClass.prototype} as overrides to global | |
350 * functions of the same name as the method, using the proxy of the | |
351 * |mockObject| to handle the functions. | |
352 * @param {Mock4JS.Mock} mockObject The mock to register callbacks against. | |
353 * @param {function(new:Object)} mockClAss Constructor for the mocked class. | |
354 * @see registerMessageCallback | |
355 **/ | |
356 function registerMockGlobals(mockObject, mockClass) { | |
357 var mockProxy = mockObject.proxy(); | |
358 for (var func in mockClass.prototype) { | |
359 if (typeof(mockClass.prototype[func]) == 'function') { | |
arv (Not doing code reviews)
2011/08/22 20:57:18
typeof should not have parentheses
Sheridan Rawlins
2011/08/23 01:06:15
Done.
| |
360 registerMockGlobal(func, mockProxy, mockProxy[func]); | |
361 } | |
362 } | |
363 } | |
213 | 364 |
214 /** | 365 /** |
215 * Overrides {@code chrome.send} for routing messages to javascript | 366 * Overrides {@code chrome.send} for routing messages to javascript |
216 * functions. Also falls back to sending with the original chrome object. | 367 * functions. Also falls back to sending with the original chrome object. |
217 * @param {string} messageName The message to route. | 368 * @param {string} messageName The message to route. |
218 **/ | 369 **/ |
219 function send(messageName) { | 370 function send(messageName) { |
220 var callback = sendCallbacks[messageName]; | 371 var callback = sendCallbacks[messageName]; |
221 if (callback != undefined) | 372 if (callback != undefined) |
222 callback[1].apply(callback[0], Array.prototype.slice.call(arguments, 1)); | 373 callback[1].apply(callback[0], Array.prototype.slice.call(arguments, 1)); |
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
341 } | 492 } |
342 | 493 |
343 /** | 494 /** |
344 * Notifies the running browser test of the test results. Clears |errors|. | 495 * Notifies the running browser test of the test results. Clears |errors|. |
345 * @param {Array.<boolean, string>=} result When passed, this is used for the | 496 * @param {Array.<boolean, string>=} result When passed, this is used for the |
346 * testResult message. | 497 * testResult message. |
347 **/ | 498 **/ |
348 function testDone(result) { | 499 function testDone(result) { |
349 if (!testIsDone) { | 500 if (!testIsDone) { |
350 testIsDone = true; | 501 testIsDone = true; |
502 if (currentTestCase) { | |
503 currentTestCase.TearDown(); | |
504 currentTestCase = null; | |
505 } | |
351 chrome.send('testResult', result ? result : testResult()); | 506 chrome.send('testResult', result ? result : testResult()); |
352 errors.splice(0, errors.length); | 507 errors.splice(0, errors.length); |
353 } else { | 508 } else { |
354 console.warn('testIsDone already'); | 509 console.warn('testIsDone already'); |
355 } | 510 } |
356 } | 511 } |
357 | 512 |
358 /** | 513 /** |
359 * Returns [success, message] & clears |errors|. | 514 * Returns [success, message] & clears |errors|. |
360 * @return {Array.<boolean, string>} | 515 * @return {Array.<boolean, string>} |
(...skipping 248 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
609 * @param {string} testName The test name. | 764 * @param {string} testName The test name. |
610 * @see sendCallbacks | 765 * @see sendCallbacks |
611 **/ | 766 **/ |
612 function preloadJavascriptLibraries(testFixture, testName) { | 767 function preloadJavascriptLibraries(testFixture, testName) { |
613 window.addEventListener('DOMContentLoaded', function() { | 768 window.addEventListener('DOMContentLoaded', function() { |
614 var oldChrome = chrome; | 769 var oldChrome = chrome; |
615 chrome = { | 770 chrome = { |
616 __proto__: oldChrome, | 771 __proto__: oldChrome, |
617 send: send, | 772 send: send, |
618 }; | 773 }; |
774 | |
775 // Override globals at load time so they will be defined. | |
776 for (var func in globalOverrides) { | |
777 assertNotEquals(undefined, this[func]); | |
778 var globalOverride = globalOverrides[func]; | |
779 assertNotEquals(undefined, globalOverride); | |
780 assertEquals(undefined, globalOverride.original); | |
781 globalOverride.original = this[func]; | |
782 this[func] = globalOverride.callback.bind(globalOverride.object); | |
783 } | |
619 }); | 784 }); |
620 currentTestCase = createTestCase(testFixture, testName); | 785 currentTestCase = createTestCase(testFixture, testName); |
621 currentTestCase.PreLoad(); | 786 currentTestCase.PreLoad(); |
622 } | 787 } |
623 | 788 |
624 /** | 789 /** |
625 * During generation phase, this outputs; do nothing at runtime. | 790 * During generation phase, this outputs; do nothing at runtime. |
626 **/ | 791 **/ |
627 function GEN() {} | 792 function GEN() {} |
628 | 793 |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
669 * RunJavascriptTestF uses this as the |testFunction| when invoking | 834 * RunJavascriptTestF uses this as the |testFunction| when invoking |
670 * runTest. If |currentTestCase| is non-null at this point, verify that | 835 * runTest. If |currentTestCase| is non-null at this point, verify that |
671 * |testFixture| and |testName| agree with the preloaded values. Create | 836 * |testFixture| and |testName| agree with the preloaded values. Create |
672 * |currentTestCase|, if needed, run it, and clear the |currentTestCase|. | 837 * |currentTestCase|, if needed, run it, and clear the |currentTestCase|. |
673 * @param {string} testFixture The name of the test fixture class. | 838 * @param {string} testFixture The name of the test fixture class. |
674 * @param {string} testName The name of the test function. | 839 * @param {string} testName The name of the test function. |
675 * @see preloadJavascriptLibraries | 840 * @see preloadJavascriptLibraries |
676 * @see runTest | 841 * @see runTest |
677 **/ | 842 **/ |
678 function RUN_TEST_F(testFixture, testName) { | 843 function RUN_TEST_F(testFixture, testName) { |
679 try { | 844 if (!currentTestCase) |
680 if (!currentTestCase) | 845 currentTestCase = createTestCase(testFixture, testName); |
681 currentTestCase = createTestCase(testFixture, testName); | 846 assertEquals(currentTestCase.name, testName); |
682 assertEquals(currentTestCase.name, testName); | 847 assertEquals(currentTestCase.fixture.name, testFixture); |
683 assertEquals(currentTestCase.fixture.name, testFixture); | 848 console.log('Running TestCase ' + testFixture + '.' + testName); |
684 console.log('Running TestCase ' + testFixture + '.' + testName); | 849 currentTestCase.Run(); |
685 currentTestCase.Run(); | 850 } |
686 } finally { | 851 |
687 currentTestCase = null; | 852 /** |
688 } | 853 * Matcher which pushes the |actualArgument| of argumentMatches() onto |
689 } | 854 * |arguments|, then proxies the return result to the |realMatcher|. Because |
690 | 855 * |realMatcher| can be any type, this constructor overrides argumentMatches, |
691 /** | 856 * then forces |this| to be an instance of |realMatcher|. |
mmenke
2011/08/22 16:26:44
You're defining a class in terms of one of its met
Sheridan Rawlins
2011/08/23 01:06:15
I rewrote this with composition instead of hacky i
| |
692 * CallFunctionAction is provided to allow mocks to have side effects. | 857 * @param {Array} arguments The arguments to push |actualArgument| onto. |
693 * @param {Function} func The function to call. | 858 * @param {Object} realMatcher The real matcher check arguments with. |
694 * @param {Array} args Any arguments to pass to func. | 859 * @constructor |
695 * @constructor | 860 * @extends {realMatcher} |
arv (Not doing code reviews)
2011/08/22 20:57:18
This annotation is a bit strange
Sheridan Rawlins
2011/08/23 01:06:15
See new version.
On 2011/08/22 20:57:18, arv wrot
| |
696 **/ | 861 **/ |
697 function CallFunctionAction(func, args) { | 862 function SaveArgumentMatcher(arguments, realMatcher) { |
698 this._func = func; | 863 this.arguments_ = arguments; |
699 this._args = args; | 864 this.argumentMatches = this.argumentMatches; |
mmenke
2011/08/22 16:26:44
?
Sheridan Rawlins
2011/08/23 01:06:15
Yeah, this was weird - it could have been this.arg
| |
700 } | 865 this.__proto__ = realMatcher; |
arv (Not doing code reviews)
2011/08/22 20:57:18
This seems a bit hacky. How about?
var obj = Obje
Sheridan Rawlins
2011/08/23 01:06:15
See new version with composition instead of the ha
| |
701 | 866 } |
702 CallFunctionAction.prototype = { | 867 |
703 invoke: function() { | 868 SaveArgumentMatcher.prototype = { |
704 return this._func.apply(null, this._args); | 869 /** |
705 }, | 870 * Holds the arguments to push each |actualArgument| onto. |
706 describe: function() { | 871 * @type {Array} |
707 return 'calls the given function with arguments ' + this._args; | 872 * @private |
708 } | 873 **/ |
709 }; | 874 arguments_: null, |
710 | 875 |
711 /** | 876 /** |
712 * Syntactic sugar for will() on a Mock4JS.Mock. | 877 * Pushes |actualArgument| onto |arguments_| for later use. Clears |
713 * @param {Function} func the function to call when the method is invoked. | 878 * |arguments_| on non-match. |
714 * @param {...*} var_args arguments to pass when calling func. | 879 * @param {*} actualArgument The argument to match and save. |
715 **/ | 880 * @return {boolean} value of calling the |realMatcher|. |
716 function callFunction(func) { | 881 * @override |
717 return new CallFunctionAction(func, | 882 **/ |
718 Array.prototype.slice.call(arguments, 1)); | 883 argumentMatches: function(actualArgument) { |
719 } | 884 this.arguments_.push(actualArgument); |
885 var match = this.__proto__.argumentMatches(actualArgument); | |
886 if (!match) | |
887 this.arguments_.splice(0, this.arguments_.length); | |
888 | |
889 return match; | |
890 }, | |
891 }; | |
720 | 892 |
721 /** | 893 /** |
722 * Allow mock stubs() and expects() to know what arguments were passed to the | 894 * Allow mock stubs() and expects() to know what arguments were passed to the |
723 * |realMatcher|. | 895 * |realMatcher|. |
mmenke
2011/08/22 16:26:44
This isn't terribly illuminating for someone tryin
Sheridan Rawlins
2011/08/23 01:06:15
OK. Added more context to comments.
On 2011/08/2
| |
724 * @param {!Object} realMatcher The real matcher to perform matching with. | 896 * @param {!Object} realMatcher The real matcher to perform matching with. |
725 * @constructor | 897 * @constructor |
726 **/ | 898 **/ |
727 function SaveArgumentsMatcher(realMatcher) { | 899 function SaveMockArguments() { |
728 this.realMatcher_ = realMatcher; | 900 this.arguments = []; |
729 } | 901 } |
730 | 902 |
731 SaveArgumentsMatcher.prototype = { | 903 SaveMockArguments.prototype = { |
904 /** | |
905 * Wraps the |realMatcher| with an object which will push its argument onto | |
906 * |arguments| and call realMatcher. | |
907 * @param {Object} realMatcher A Mock4JS matcher object for this argument. | |
908 * @return {SaveArgumentMatcher} A new matcher which will push its argument | |
909 * onto |arguments|. | |
910 **/ | |
911 match: function(realMatcher) { | |
912 return new SaveArgumentMatcher(this.arguments, realMatcher); | |
913 }, | |
914 | |
732 /** | 915 /** |
733 * Remember the argument passed to this stub invocation. | 916 * Remember the argument passed to this stub invocation. |
734 * @type {*} | 917 * @type {Array} |
735 **/ | 918 **/ |
736 argument: undefined, | 919 arguments: null, |
737 | 920 }; |
738 /** | 921 |
739 * @type {Object} the object performing the real match. | 922 /** |
740 * @private | 923 * CallFunctionAction is provided to allow mocks to have side effects. |
741 */ | 924 * @param {Object} obj The object to set |this| to when calling |func_|. |
742 realMatcher_: null, | 925 * @param {?SaveMockArguments} savedArgs when non-null, saved arguments are |
743 | 926 * passed to |func|. |
744 /** | 927 * @param {Function} func The function to call. |
745 * Saves |actualArgument| for later use by the mock stub or expect. | 928 * @param {Array} args Any arguments to pass to func. |
746 * @param {*} actualArgument The argument to match and save. | 929 * @constructor |
747 * @return {boolean} value of calling the |realMatcher_|. | 930 **/ |
748 **/ | 931 function CallFunctionAction(obj, savedArgs, func, args) { |
749 argumentMatches: function(actualArgument) { | 932 this.obj_ = obj; |
750 this.argument = actualArgument; | 933 this.savedArgs_ = savedArgs; |
751 return this.realMatcher_.argumentMatches.call(this.realMatcher_, | 934 this.func_ = func; |
752 actualArgument); | 935 this.args_ = args; |
753 }, | 936 } |
754 | 937 |
755 /** | 938 CallFunctionAction.prototype = { |
756 * Generic description for this Matcher object. | 939 /** |
757 * @return {string} description of the matcher for this argument. | 940 * Set |this| to |obj_| when calling |func_|. |
941 * @type {?Object} | |
942 **/ | |
943 obj_: null, | |
944 | |
945 /** | |
946 * The SaveMockArguments to hold arguments when invoking |func_|. | |
947 * @type {?SaveMockArguments} | |
948 * @private | |
949 **/ | |
950 savedArgs_: null, | |
951 | |
952 /** | |
953 * The function to call when invoked. | |
954 * @type {!Function} | |
955 * @private | |
956 **/ | |
957 func_: null, | |
958 | |
959 /** | |
960 * Arguments to pass to |func_| when invoked. | |
961 * @type {!Array} | |
962 **/ | |
963 args_: null, | |
964 | |
965 /** | |
966 * Accessor for |func_|. | |
967 * @return {Function} The function to invoke. | |
968 **/ | |
969 get func() { | |
970 return this.func_; | |
971 }, | |
972 | |
973 /** | |
974 * Called by Mock4JS when using .will() to specify actions for stubs() or | |
975 * expects(). Clears |savedArgs_| so it can be reused. | |
976 * @return The results of calling |func_| with the concatenation of | |
977 * |savedArgs_| and |args_|. | |
978 **/ | |
979 invoke: function() { | |
980 var prependArgs = []; | |
981 if (this.savedArgs_) { | |
982 prependArgs = this.savedArgs_.arguments.splice( | |
983 0, this.savedArgs_.arguments.length); | |
984 } | |
985 return this.func.apply(this.obj_, prependArgs.concat(this.args_)); | |
986 }, | |
987 | |
988 /** | |
989 * Describe this action to Mock4JS. | |
990 * @return {string} A description of this action. | |
758 **/ | 991 **/ |
759 describe: function() { | 992 describe: function() { |
760 return 'SaveArguments(' + | 993 return 'calls the given function with saved arguments and ' + this.args_; |
761 this.realMatcher_.describe.call(this.realMatcher_) + ')'; | 994 } |
762 }, | 995 }; |
763 }; | 996 |
997 /** | |
998 * Syntactic sugar for will() on a Mock4JS.Mock. | |
mmenke
2011/08/22 16:26:44
nit: "for use with" make it clearer that this sho
Sheridan Rawlins
2011/08/23 01:06:15
Done.
| |
999 * @param {Function} func The function to call when the method is invoked. | |
1000 * @param {...*} var_args Arguments to pass when calling func. | |
1001 * @return {CallFunctionAction} Action for use in will. | |
1002 **/ | |
1003 function callFunction(func) { | |
1004 return new CallFunctionAction( | |
1005 null, null, func, Array.prototype.slice.call(arguments, 1)); | |
1006 } | |
1007 | |
1008 /** | |
1009 * Syntactic sugar for will() on a Mock4JS.Mock. | |
mmenke
2011/08/22 16:26:44
nit: "for use with"
Sheridan Rawlins
2011/08/23 01:06:15
Done.
| |
1010 * @param {SaveMockArguments} savedArgs Arguments saved with this object | |
1011 * are passed to |func|. | |
1012 * @param {Function} func The function to call when the method is invoked. | |
1013 * @param {...*} var_args Arguments to pass when calling func. | |
1014 * @return {CallFunctionAction} Action for use in will. | |
1015 **/ | |
1016 function callFunctionWithSavedArgs(savedArgs, func) { | |
1017 return new CallFunctionAction( | |
1018 null, savedArgs, func, Array.prototype.slice.call(arguments, 2)); | |
1019 } | |
1020 | |
1021 /** | |
1022 * CallGlobalAction is provided to help override global function with mocking | |
1023 * expectations and still call the global function. | |
mmenke
2011/08/22 16:26:44
nit: Say what it does, not just why it exists.
Sheridan Rawlins
2011/08/23 01:06:15
Done.
| |
1024 * @param {?SaveMockArguments} savedArgs when non-null, saved arguments are | |
1025 * passed to the global function |funcName|. | |
1026 * @param {Function} funcName The name of the global function to call. | |
1027 * @param {Array} args Any arguments to pass to func. | |
1028 * @constructor | |
1029 * @extends {CallFunctionAction} | |
1030 * @see globalOverrides | |
1031 **/ | |
1032 function CallGlobalAction(savedArgs, funcName, args) { | |
1033 CallFunctionAction.call(this, null, savedArgs, funcName, args); | |
1034 } | |
1035 | |
1036 CallGlobalAction.prototype = { | |
1037 __proto__: CallFunctionAction.prototype, | |
1038 | |
1039 /** | |
1040 * Fetch and return the original global function to call. | |
1041 * @return {Function} The global function to invoke. | |
1042 * @override | |
1043 **/ | |
1044 get func() { | |
1045 var func = globalOverrides[this.func_].original; | |
1046 assertNotEquals(undefined, func); | |
1047 return func; | |
1048 }, | |
1049 }; | |
1050 | |
1051 /** | |
1052 * Syntactic sugar for will() on a Mock4JS.Mock. | |
mmenke
2011/08/22 16:26:44
nit: For use with.
Sheridan Rawlins
2011/08/23 01:06:15
Done.
| |
1053 * @param {SaveMockArguments} savedArgs Arguments saved with this object | |
1054 * are passed to the global function |funcName|. | |
1055 * @param {Function} funcName The name of the global function to call when the | |
1056 * method is invoked. | |
mmenke
2011/08/22 16:26:44
nit: Name of a registered mock global function.
Sheridan Rawlins
2011/08/23 01:06:15
Done.
| |
1057 * @param {...*} var_args Arguments to pass when calling func. | |
1058 * @return {CallGlobalAction} Action for use in will. | |
1059 **/ | |
1060 function callGlobalWithSavedArgs(savedArgs, funcName) { | |
1061 return new CallGlobalAction( | |
1062 savedArgs, funcName, Array.prototype.slice.call(arguments, 2)); | |
1063 } | |
1064 | |
1065 /** | |
1066 * Runs all |actions|. | |
1067 * @param {boolean} isAsync When true, call testDone() on Errors. | |
1068 * @param {boolean} alwaysDone When true, always call testDone(). | |
1069 * @param {Array.<Object>} actions Actions to run. | |
1070 * @constructor | |
1071 **/ | |
1072 function RunAllAction(isAsync, alwaysDone, actions) { | |
1073 this.isAsync_ = isAsync; | |
1074 this.alwaysDone_ = alwaysDone; | |
1075 this.actions_ = actions; | |
1076 } | |
1077 | |
1078 RunAllAction.prototype = { | |
1079 /** | |
1080 * When true, call testDone() on Errors. | |
1081 * @type {boolean} | |
1082 * @private | |
1083 **/ | |
1084 isAsync_: false, | |
1085 | |
1086 /** | |
1087 * When true, always call testDone(). | |
1088 * @type {boolean} | |
1089 * @private | |
1090 **/ | |
1091 alwaysDone_: false, | |
1092 | |
1093 /** | |
1094 * Holds the actions to execute when invoked. | |
1095 * @type {Array} | |
1096 * @private | |
1097 **/ | |
1098 actions_: null, | |
1099 | |
1100 /** | |
1101 * Runs all |actions_|, returning the last one. | |
1102 **/ | |
1103 invoke: function() { | |
1104 try { | |
1105 var result; | |
1106 for(var i = 0; i < this.actions_.length; ++i) { | |
1107 result = this.actions_[i].invoke.apply( | |
1108 this.actions_[i], Array.prototype.slice.call(arguments)); | |
1109 } | |
1110 if (this.alwaysDone_) | |
1111 testDone(); | |
1112 | |
1113 return result; | |
1114 } catch (e) { | |
1115 if (!this.isAsync_) | |
1116 throw e; | |
1117 | |
1118 errors.push(e); | |
1119 testDone(); | |
mmenke
2011/08/22 16:26:44
You should also call testDone on expect failures,
Sheridan Rawlins
2011/08/23 01:06:15
I don't think so. There should be a distinction be
mmenke
2011/08/23 01:36:09
Then should probably add a way to tell if there's
Sheridan Rawlins
2011/08/23 05:52:18
Ok. I added a whenTestDone enum to describe when
mmenke
2011/08/23 15:26:29
Seems reasonable to me.
| |
1120 } | |
1121 }, | |
1122 | |
1123 /** | |
1124 * Describe this action to Mock4JS. | |
1125 * @return {string} A description of this action. | |
1126 **/ | |
1127 describe: function() { | |
1128 return 'Calls all actions: ' + this.actions_; | |
1129 }, | |
1130 }; | |
1131 | |
1132 /** | |
1133 * Syntactic sugar for will() on a Mock4JS.Mock. | |
1134 * @param {...Object} var_actions Actions to run. | |
1135 * @return {RunAllAction} Action for use in will. | |
1136 **/ | |
1137 function runAllActions() { | |
1138 return new RunAllAction(false, false, | |
1139 Array.prototype.slice.call(arguments)); | |
1140 } | |
1141 | |
1142 /** | |
1143 * Syntactic sugar for will() on a Mock4JS.Mock. | |
1144 * @param {boolean} alwaysDone When true, always call testDone() otherwise, | |
1145 * call it only when Errors are thrown (from asserts). | |
1146 * @return {RunAllAction} Action for use in will. | |
1147 **/ | |
1148 function runAllActionsAsync(alwaysDone) { | |
1149 return new RunAllAction(true, alwaysDone, | |
1150 Array.prototype.slice.call(arguments)); | |
1151 } | |
764 | 1152 |
765 // Exports. | 1153 // Exports. |
766 testing.Test = Test; | 1154 testing.Test = Test; |
767 window.testDone = testDone; | 1155 window.testDone = testDone; |
768 window.assertTrue = assertTrue; | 1156 window.assertTrue = assertTrue; |
769 window.assertFalse = assertFalse; | 1157 window.assertFalse = assertFalse; |
770 window.assertGE = assertGE; | 1158 window.assertGE = assertGE; |
771 window.assertGT = assertGT; | 1159 window.assertGT = assertGT; |
772 window.assertEquals = assertEquals; | 1160 window.assertEquals = assertEquals; |
773 window.assertLE = assertLE; | 1161 window.assertLE = assertLE; |
774 window.assertLT = assertLT; | 1162 window.assertLT = assertLT; |
775 window.assertNotEquals = assertNotEquals; | 1163 window.assertNotEquals = assertNotEquals; |
776 window.assertNotReached = assertNotReached; | 1164 window.assertNotReached = assertNotReached; |
777 window.callFunction = callFunction; | 1165 window.callFunction = callFunction; |
1166 window.callFunctionWithSavedArgs = callFunctionWithSavedArgs; | |
1167 window.callGlobalWithSavedArgs = callGlobalWithSavedArgs; | |
778 window.expectTrue = createExpect(assertTrue); | 1168 window.expectTrue = createExpect(assertTrue); |
779 window.expectFalse = createExpect(assertFalse); | 1169 window.expectFalse = createExpect(assertFalse); |
780 window.expectGE = createExpect(assertGE); | 1170 window.expectGE = createExpect(assertGE); |
781 window.expectGT = createExpect(assertGT); | 1171 window.expectGT = createExpect(assertGT); |
782 window.expectEquals = createExpect(assertEquals); | 1172 window.expectEquals = createExpect(assertEquals); |
783 window.expectLE = createExpect(assertLE); | 1173 window.expectLE = createExpect(assertLE); |
784 window.expectLT = createExpect(assertLT); | 1174 window.expectLT = createExpect(assertLT); |
785 window.expectNotEquals = createExpect(assertNotEquals); | 1175 window.expectNotEquals = createExpect(assertNotEquals); |
786 window.expectNotReached = createExpect(assertNotReached); | 1176 window.expectNotReached = createExpect(assertNotReached); |
787 window.preloadJavascriptLibraries = preloadJavascriptLibraries; | 1177 window.preloadJavascriptLibraries = preloadJavascriptLibraries; |
788 window.registerMessageCallback = registerMessageCallback; | 1178 window.registerMessageCallback = registerMessageCallback; |
1179 window.registerMockGlobals = registerMockGlobals; | |
789 window.registerMockMessageCallbacks = registerMockMessageCallbacks; | 1180 window.registerMockMessageCallbacks = registerMockMessageCallbacks; |
790 window.resetTestState = resetTestState; | 1181 window.resetTestState = resetTestState; |
1182 window.runAllActions = runAllActions; | |
1183 window.runAllActionsAsync = runAllActionsAsync; | |
791 window.runTest = runTest; | 1184 window.runTest = runTest; |
792 window.runTestFunction = runTestFunction; | 1185 window.runTestFunction = runTestFunction; |
793 window.SaveArgumentsMatcher = SaveArgumentsMatcher; | 1186 window.SaveMockArguments = SaveMockArguments; |
794 window.TEST = TEST; | 1187 window.TEST = TEST; |
795 window.TEST_F = TEST_F; | 1188 window.TEST_F = TEST_F; |
796 window.GEN = GEN; | 1189 window.GEN = GEN; |
797 | 1190 |
798 // Import the Mock4JS helpers. | 1191 // Import the Mock4JS helpers. |
799 Mock4JS.addMockSupport(window); | 1192 Mock4JS.addMockSupport(window); |
800 })(); | 1193 })(); |
OLD | NEW |