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

Side by Side Diff: chrome/third_party/mock4js/mock4js.js

Issue 7237030: Added options browser_tests using the generator and js handler framework. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: TestNavigationController in ui_test_utils, renamed LoadStart->JsInjectionReady, reordered methods. Created 9 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 /**
2 * Mock4JS 0.2
3 * http://mock4js.sourceforge.net/
4 */
5
6 Mock4JS = {
7 _mocksToVerify: [],
8 _convertToConstraint: function(constraintOrValue) {
9 if(constraintOrValue.argumentMatches) {
10 return constraintOrValue; // it's already an ArgumentMat cher
11 } else {
12 return new MatchExactly(constraintOrValue); // defau lt to eq(...)
13 }
14 },
15 addMockSupport: function(object) {
16 // mock creation
17 object.mock = function(mockedType) {
18 if(!mockedType) {
19 throw new Mock4JSException("Cannot create mock: type to mock cannot be found or is null");
20 }
21 var newMock = new Mock(mockedType);
22 Mock4JS._mocksToVerify.push(newMock);
23 return newMock;
24 }
25
26 // syntactic sugar for expects()
27 object.once = function() {
28 return new CallCounter(1);
29 }
30 object.never = function() {
31 return new CallCounter(0);
32 }
33 object.exactly = function(expectedCallCount) {
34 return new CallCounter(expectedCallCount);
35 }
36 object.atLeastOnce = function() {
37 return new InvokeAtLeastOnce();
38 }
39
40 // syntactic sugar for argument expectations
41 object.ANYTHING = new MatchAnything();
42 object.NOT_NULL = new MatchAnythingBut(new MatchExactly(null));
43 object.NOT_UNDEFINED = new MatchAnythingBut(new MatchExactly(und efined));
44 object.eq = function(expectedValue) {
45 return new MatchExactly(expectedValue);
46 }
47 object.not = function(valueNotExpected) {
48 var argConstraint = Mock4JS._convertToConstraint(valueNo tExpected);
49 return new MatchAnythingBut(argConstraint);
50 }
51 object.and = function() {
52 var constraints = [];
53 for(var i=0; i<arguments.length; i++) {
54 constraints[i] = Mock4JS._convertToConstraint(ar guments[i]);
55 }
56 return new MatchAllOf(constraints);
57 }
58 object.or = function() {
59 var constraints = [];
60 for(var i=0; i<arguments.length; i++) {
61 constraints[i] = Mock4JS._convertToConstraint(ar guments[i]);
62 }
63 return new MatchAnyOf(constraints);
64 }
65 object.stringContains = function(substring) {
66 return new MatchStringContaining(substring);
67 }
68
69 // syntactic sugar for will()
70 object.returnValue = function(value) {
71 return new ReturnValueAction(value);
72 }
73 object.throwException = function(exception) {
74 return new ThrowExceptionAction(exception);
75 }
76 },
77 clearMocksToVerify: function() {
78 Mock4JS._mocksToVerify = [];
79 },
80 verifyAllMocks: function() {
81 for(var i=0; i<Mock4JS._mocksToVerify.length; i++) {
82 Mock4JS._mocksToVerify[i].verify();
83 }
84 }
85 }
86
87 Mock4JSUtil = {
88 hasFunction: function(obj, methodName) {
89 return typeof obj == 'object' && typeof obj[methodName] == 'func tion';
90 },
91 join: function(list) {
92 var result = "";
93 for(var i=0; i<list.length; i++) {
94 var item = list[i];
95 if(Mock4JSUtil.hasFunction(item, "describe")) {
96 result += item.describe();
97 }
98 else if(typeof list[i] == 'string') {
99 result += "\""+list[i]+"\"";
100 } else {
101 result += list[i];
102 }
103
104 if(i<list.length-1) result += ", ";
105 }
106 return result;
107 }
108 }
109
110 Mock4JSException = function(message) {
111 this.message = message;
112 }
113
114 Mock4JSException.prototype = {
115 toString: function() {
116 return this.message;
117 }
118 }
119
120 /**
121 * Assert function that makes use of the constraint methods
122 */
123 assertThat = function(expected, argumentMatcher) {
124 if(!argumentMatcher.argumentMatches(expected)) {
125 fail("Expected '"+expected+"' to be "+argumentMatcher.describe() );
126 }
127 }
128
129 /**
130 * CallCounter
131 */
132 function CallCounter(expectedCount) {
133 this._expectedCallCount = expectedCount;
134 this._actualCallCount = 0;
135 }
136
137 CallCounter.prototype = {
138 addActualCall: function() {
139 this._actualCallCount++;
140 if(this._actualCallCount > this._expectedCallCount) {
141 throw new Mock4JSException("unexpected invocation");
142 }
143 },
144
145 verify: function() {
146 if(this._actualCallCount < this._expectedCallCount) {
147 throw new Mock4JSException("expected method was not invo ked the expected number of times");
148 }
149 },
150
151 describe: function() {
152 if(this._expectedCallCount == 0) {
153 return "not expected";
154 } else if(this._expectedCallCount == 1) {
155 var msg = "expected once";
156 if(this._actualCallCount >= 1) {
157 msg += " and has been invoked";
158 }
159 return msg;
160 } else {
161 var msg = "expected "+this._expectedCallCount+" times";
162 if(this._actualCallCount > 0) {
163 msg += ", invoked "+this._actualCallCount + " ti mes";
164 }
165 return msg;
166 }
167 }
168 }
169
170 function InvokeAtLeastOnce() {
171 this._hasBeenInvoked = false;
172 }
173
174 InvokeAtLeastOnce.prototype = {
175 addActualCall: function() {
176 this._hasBeenInvoked = true;
177 },
178
179 verify: function() {
180 if(this._hasBeenInvoked === false) {
181 throw new Mock4JSException(describe());
182 }
183 },
184
185 describe: function() {
186 var desc = "expected at least once";
187 if(this._hasBeenInvoked) desc+=" and has been invoked";
188 return desc;
189 }
190 }
191
192 /**
193 * ArgumentMatchers
194 */
195
196 function MatchExactly(expectedValue) {
197 this._expectedValue = expectedValue;
198 }
199
200 MatchExactly.prototype = {
201 argumentMatches: function(actualArgument) {
202 if(this._expectedValue instanceof Array) {
203 if(!(actualArgument instanceof Array)) return false;
204 if(this._expectedValue.length != actualArgument.length) return false;
205 for(var i=0; i<this._expectedValue.length; i++) {
206 if(this._expectedValue[i] != actualArgument[i]) return false;
207 }
208 return true;
209 } else {
210 return this._expectedValue == actualArgument;
211 }
212 },
213 describe: function() {
214 if(typeof this._expectedValue == "string") {
215 return "eq(\""+this._expectedValue+"\")";
216 } else {
217 return "eq("+this._expectedValue+")";
218 }
219 }
220 }
221
222 function MatchAnything() {
223 }
224
225 MatchAnything.prototype = {
226 argumentMatches: function(actualArgument) {
227 return true;
228 },
229 describe: function() {
230 return "ANYTHING";
231 }
232 }
233
234 function MatchAnythingBut(matcherToNotMatch) {
235 this._matcherToNotMatch = matcherToNotMatch;
236 }
237
238 MatchAnythingBut.prototype = {
239 argumentMatches: function(actualArgument) {
240 return !this._matcherToNotMatch.argumentMatches(actualArgument);
241 },
242 describe: function() {
243 return "not("+this._matcherToNotMatch.describe()+")";
244 }
245 }
246
247 function MatchAllOf(constraints) {
248 this._constraints = constraints;
249 }
250
251
252 MatchAllOf.prototype = {
253 argumentMatches: function(actualArgument) {
254 for(var i=0; i<this._constraints.length; i++) {
255 var constraint = this._constraints[i];
256 if(!constraint.argumentMatches(actualArgument)) return f alse;
257 }
258 return true;
259 },
260 describe: function() {
261 return "and("+Mock4JSUtil.join(this._constraints)+")";
262 }
263 }
264
265 function MatchAnyOf(constraints) {
266 this._constraints = constraints;
267 }
268
269 MatchAnyOf.prototype = {
270 argumentMatches: function(actualArgument) {
271 for(var i=0; i<this._constraints.length; i++) {
272 var constraint = this._constraints[i];
273 if(constraint.argumentMatches(actualArgument)) return tr ue;
274 }
275 return false;
276 },
277 describe: function() {
278 return "or("+Mock4JSUtil.join(this._constraints)+")";
279 }
280 }
281
282
283 function MatchStringContaining(stringToLookFor) {
284 this._stringToLookFor = stringToLookFor;
285 }
286
287 MatchStringContaining.prototype = {
288 argumentMatches: function(actualArgument) {
289 if(typeof actualArgument != 'string') throw new Mock4JSException ("stringContains() must be given a string, actually got a "+(typeof actualArgume nt));
290 return (actualArgument.indexOf(this._stringToLookFor) != -1);
291 },
292 describe: function() {
293 return "a string containing \""+this._stringToLookFor+"\"";
294 }
295 }
296
297
298 /**
299 * StubInvocation
300 */
301 function StubInvocation(expectedMethodName, expectedArgs, actionSequence) {
302 this._expectedMethodName = expectedMethodName;
303 this._expectedArgs = expectedArgs;
304 this._actionSequence = actionSequence;
305 }
306
307 StubInvocation.prototype = {
308 matches: function(invokedMethodName, invokedMethodArgs) {
309 if (invokedMethodName != this._expectedMethodName) {
310 return false;
311 }
312
313 if (invokedMethodArgs.length != this._expectedArgs.length) {
314 return false;
315 }
316
317 for(var i=0; i<invokedMethodArgs.length; i++) {
318 var expectedArg = this._expectedArgs[i];
319 var invokedArg = invokedMethodArgs[i];
320 if(!expectedArg.argumentMatches(invokedArg)) {
321 return false;
322 }
323 }
324
325 return true;
326 },
327
328 invoked: function() {
329 try {
330 return this._actionSequence.invokeNextAction();
331 } catch(e) {
332 if(e instanceof Mock4JSException) {
333 throw new Mock4JSException(this.describeInvocati onNameAndArgs()+" - "+e.message);
334 } else {
335 throw e;
336 }
337 }
338 },
339
340 will: function() {
341 this._actionSequence.addAll.apply(this._actionSequence, argument s);
342 },
343
344 describeInvocationNameAndArgs: function() {
345 return this._expectedMethodName+"("+Mock4JSUtil.join(this._expec tedArgs)+")";
346 },
347
348 describe: function() {
349 return "stub: "+this.describeInvocationNameAndArgs();
350 },
351
352 verify: function() {
353 }
354 }
355
356 /**
357 * ExpectedInvocation
358 */
359 function ExpectedInvocation(expectedMethodName, expectedArgs, expectedCallCounte r) {
360 this._stubInvocation = new StubInvocation(expectedMethodName, expectedAr gs, new ActionSequence());
361 this._expectedCallCounter = expectedCallCounter;
362 }
363
364 ExpectedInvocation.prototype = {
365 matches: function(invokedMethodName, invokedMethodArgs) {
366 try {
367 return this._stubInvocation.matches(invokedMethodName, i nvokedMethodArgs);
368 } catch(e) {
369 throw new Mock4JSException("method "+this._stubInvocatio n.describeInvocationNameAndArgs()+": "+e.message);
370 }
371 },
372
373 invoked: function() {
374 try {
375 this._expectedCallCounter.addActualCall();
376 } catch(e) {
377 throw new Mock4JSException(e.message+": "+this._stubInvo cation.describeInvocationNameAndArgs());
378 }
379 return this._stubInvocation.invoked();
380 },
381
382 will: function() {
383 this._stubInvocation.will.apply(this._stubInvocation, arguments) ;
384 },
385
386 describe: function() {
387 return this._expectedCallCounter.describe()+": "+this._stubInvoc ation.describeInvocationNameAndArgs();
388 },
389
390 verify: function() {
391 try {
392 this._expectedCallCounter.verify();
393 } catch(e) {
394 throw new Mock4JSException(e.message+": "+this._stubInvo cation.describeInvocationNameAndArgs());
395 }
396 }
397 }
398
399 /**
400 * MethodActions
401 */
402 function ReturnValueAction(valueToReturn) {
403 this._valueToReturn = valueToReturn;
404 }
405
406 ReturnValueAction.prototype = {
407 invoke: function() {
408 return this._valueToReturn;
409 },
410 describe: function() {
411 return "returns "+this._valueToReturn;
412 }
413 }
414
415 function ThrowExceptionAction(exceptionToThrow) {
416 this._exceptionToThrow = exceptionToThrow;
417 }
418
419 ThrowExceptionAction.prototype = {
420 invoke: function() {
421 throw this._exceptionToThrow;
422 },
423 describe: function() {
424 return "throws "+this._exceptionToThrow;
425 }
426 }
427
428 function ActionSequence() {
429 this._ACTIONS_NOT_SETUP = "_ACTIONS_NOT_SETUP";
430 this._actionSequence = this._ACTIONS_NOT_SETUP;
431 this._indexOfNextAction = 0;
432 }
433
434 ActionSequence.prototype = {
435 invokeNextAction: function() {
436 if(this._actionSequence === this._ACTIONS_NOT_SETUP) {
437 return;
438 } else {
439 if(this._indexOfNextAction >= this._actionSequence.lengt h) {
440 throw new Mock4JSException("no more values to re turn");
441 } else {
442 var action = this._actionSequence[this._indexOfN extAction];
443 this._indexOfNextAction++;
444 return action.invoke();
445 }
446 }
447 },
448
449 addAll: function() {
450 this._actionSequence = [];
451 for(var i=0; i<arguments.length; i++) {
452 if(typeof arguments[i] != 'object' && arguments[i].invok e === undefined) {
453 throw new Error("cannot add a method action that does not have an invoke() method");
454 }
455 this._actionSequence.push(arguments[i]);
456 }
457 }
458 }
459
460 function StubActionSequence() {
461 this._ACTIONS_NOT_SETUP = "_ACTIONS_NOT_SETUP";
462 this._actionSequence = this._ACTIONS_NOT_SETUP;
463 this._indexOfNextAction = 0;
464 }
465
466 StubActionSequence.prototype = {
467 invokeNextAction: function() {
468 if(this._actionSequence === this._ACTIONS_NOT_SETUP) {
469 return;
470 } else if(this._actionSequence.length == 1) {
471 // if there is only one method action, keep doing that o n every invocation
472 return this._actionSequence[0].invoke();
473 } else {
474 if(this._indexOfNextAction >= this._actionSequence.lengt h) {
475 throw new Mock4JSException("no more values to re turn");
476 } else {
477 var action = this._actionSequence[this._indexOfN extAction];
478 this._indexOfNextAction++;
479 return action.invoke();
480 }
481 }
482 },
483
484 addAll: function() {
485 this._actionSequence = [];
486 for(var i=0; i<arguments.length; i++) {
487 if(typeof arguments[i] != 'object' && arguments[i].invok e === undefined) {
488 throw new Error("cannot add a method action that does not have an invoke() method");
489 }
490 this._actionSequence.push(arguments[i]);
491 }
492 }
493 }
494
495
496 /**
497 * Mock
498 */
499 function Mock(mockedType) {
500 if(mockedType === undefined || mockedType.prototype === undefined) {
501 throw new Mock4JSException("Unable to create Mock: must create M ock using a class not prototype, eg. 'new Mock(TypeToMock)' or using the conveni ence method 'mock(TypeToMock)'");
502 }
503 this._mockedType = mockedType.prototype;
504 this._expectedCallCount;
505 this._isRecordingExpectations = false;
506 this._expectedInvocations = [];
507
508 // setup proxy
509 var IntermediateClass = new Function();
510 IntermediateClass.prototype = mockedType.prototype;
511 var ChildClass = new Function();
512 ChildClass.prototype = new IntermediateClass();
513 this._proxy = new ChildClass();
514 this._proxy.mock = this;
515
516 for(property in mockedType.prototype) {
517 if(this._isPublicMethod(mockedType.prototype, property)) {
518 var publicMethodName = property;
519 this._proxy[publicMethodName] = this._createMockedMethod (publicMethodName);
520 this[publicMethodName] = this._createExpectationRecordin gMethod(publicMethodName);
521 }
522 }
523 }
524
525 Mock.prototype = {
526
527 proxy: function() {
528 return this._proxy;
529 },
530
531 expects: function(expectedCallCount) {
532 this._expectedCallCount = expectedCallCount;
533 this._isRecordingExpectations = true;
534 this._isRecordingStubs = false;
535 return this;
536 },
537
538 stubs: function() {
539 this._isRecordingExpectations = false;
540 this._isRecordingStubs = true;
541 return this;
542 },
543
544 verify: function() {
545 for(var i=0; i<this._expectedInvocations.length; i++) {
546 var expectedInvocation = this._expectedInvocations[i];
547 try {
548 expectedInvocation.verify();
549 } catch(e) {
550 var failMsg = e.message+this._describeMockSetup( );
551 throw new Mock4JSException(failMsg);
552 }
553 }
554 },
555
556 _isPublicMethod: function(mockedType, property) {
557 try {
558 var isMethod = typeof(mockedType[property]) == 'function ';
559 var isPublic = property.charAt(0) != "_";
560 return isMethod && isPublic;
561 } catch(e) {
562 return false;
563 }
564 },
565
566 _createExpectationRecordingMethod: function(methodName) {
567 return function() {
568 // ensure all arguments are instances of ArgumentMatcher
569 var expectedArgs = [];
570 for(var i=0; i<arguments.length; i++) {
571 if(arguments[i] !== null && arguments[i] !== und efined && arguments[i].argumentMatches) {
572 expectedArgs[i] = arguments[i];
573 } else {
574 expectedArgs[i] = new MatchExactly(argum ents[i]);
575 }
576 }
577
578 // create stub or expected invocation
579 var expectedInvocation;
580 if(this._isRecordingExpectations) {
581 expectedInvocation = new ExpectedInvocation(meth odName, expectedArgs, this._expectedCallCount);
582 } else {
583 expectedInvocation = new StubInvocation(methodNa me, expectedArgs, new StubActionSequence());
584 }
585
586 this._expectedInvocations.push(expectedInvocation);
587
588 this._isRecordingExpectations = false;
589 this._isRecordingStubs = false;
590 return expectedInvocation;
591 }
592 },
593
594 _createMockedMethod: function(methodName) {
595 return function() {
596 // go through expectation list backwards to ensure later expectations override earlier ones
597 for(var i=this.mock._expectedInvocations.length-1; i>=0; i--) {
598 var expectedInvocation = this.mock._expectedInvo cations[i];
599 if(expectedInvocation.matches(methodName, argume nts)) {
600 try {
601 return expectedInvocation.invoke d();
602 } catch(e) {
603 if(e instanceof Mock4JSException ) {
604 throw new Mock4JSExcepti on(e.message+this.mock._describeMockSetup());
605 } else {
606 // the user setup the mo ck to throw a specific error, so don't modify the message
607 throw e;
608 }
609 }
610 }
611 }
612 var failMsg = "unexpected invocation: "+methodName+"("+M ock4JSUtil.join(arguments)+")"+this.mock._describeMockSetup();
613 throw new Mock4JSException(failMsg);
614 };
615 },
616
617 _describeMockSetup: function() {
618 var msg = "\nAllowed:";
619 for(var i=0; i<this._expectedInvocations.length; i++) {
620 var expectedInvocation = this._expectedInvocations[i];
621 msg += "\n" + expectedInvocation.describe();
622 }
623 return msg;
624 }
625 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698