jasmine-ajax 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (56) hide show
  1. data/.gitignore +2 -0
  2. data/.pairs +6 -0
  3. data/Gemfile +4 -0
  4. data/Gemfile.lock +35 -0
  5. data/MIT.LICENSE +20 -0
  6. data/README.markdown +168 -0
  7. data/Rakefile +3 -0
  8. data/examples/jquery/Rakefile +2 -0
  9. data/examples/jquery/public/css/master.css +59 -0
  10. data/examples/jquery/public/css/reset.css +47 -0
  11. data/examples/jquery/public/images/fail-whale.png +0 -0
  12. data/examples/jquery/public/index.html +60 -0
  13. data/examples/jquery/public/javascripts/Tweet.js +6 -0
  14. data/examples/jquery/public/javascripts/TwitSearch.js +32 -0
  15. data/examples/jquery/public/javascripts/TwitterApi.js +31 -0
  16. data/examples/jquery/spec/SpecRunner.html +32 -0
  17. data/examples/jquery/spec/javascripts/TweetSpec.js +24 -0
  18. data/examples/jquery/spec/javascripts/TwitterApiSpec.js +88 -0
  19. data/examples/jquery/spec/javascripts/helpers/test_responses/search.js +16 -0
  20. data/examples/jquery/spec/javascripts/helpers/tweets.js +3 -0
  21. data/examples/jquery/spec/javascripts/jasmine-0.11.1/jasmine-html.js +182 -0
  22. data/examples/jquery/spec/javascripts/jasmine-0.11.1/jasmine.css +166 -0
  23. data/examples/jquery/spec/javascripts/jasmine-0.11.1/jasmine.js +2343 -0
  24. data/examples/jquery/spec/javascripts/support/jasmine.yml +78 -0
  25. data/examples/jquery/spec/javascripts/support/jasmine_runner.rb +21 -0
  26. data/examples/prototype/Rakefile +2 -0
  27. data/examples/prototype/public/css/master.css +59 -0
  28. data/examples/prototype/public/css/reset.css +47 -0
  29. data/examples/prototype/public/images/fail-whale.png +0 -0
  30. data/examples/prototype/public/index.html +45 -0
  31. data/examples/prototype/public/javascripts/Tweet.js +6 -0
  32. data/examples/prototype/public/javascripts/TwitSearch.js +32 -0
  33. data/examples/prototype/public/javascripts/TwitterApi.js +24 -0
  34. data/examples/prototype/spec/SpecRunner.html +32 -0
  35. data/examples/prototype/spec/javascripts/TweetSpec.js +24 -0
  36. data/examples/prototype/spec/javascripts/TwitterApiSpec.js +89 -0
  37. data/examples/prototype/spec/javascripts/helpers/test_responses/search.js +16 -0
  38. data/examples/prototype/spec/javascripts/helpers/tweets.js +3 -0
  39. data/examples/prototype/spec/javascripts/jasmine-0.11.1/jasmine-html.js +182 -0
  40. data/examples/prototype/spec/javascripts/jasmine-0.11.1/jasmine.css +166 -0
  41. data/examples/prototype/spec/javascripts/jasmine-0.11.1/jasmine.js +2343 -0
  42. data/examples/prototype/spec/javascripts/support/jasmine.yml +78 -0
  43. data/examples/prototype/spec/javascripts/support/jasmine_runner.rb +21 -0
  44. data/frameworks/jquery.js +8176 -0
  45. data/frameworks/prototype.js +4874 -0
  46. data/lib/assets/javascripts/mock-ajax.js +207 -0
  47. data/lib/spec-helper.js +0 -0
  48. data/lib/version.rb +5 -0
  49. data/spec/javascripts/fake-xml-http-request-spec.js +45 -0
  50. data/spec/javascripts/helpers/spec-helper.js +5 -0
  51. data/spec/javascripts/mock-ajax-jquery-spec.js +374 -0
  52. data/spec/javascripts/mock-ajax-prototypejs-spec.js +287 -0
  53. data/spec/javascripts/mock-ajax-spec.js +193 -0
  54. data/spec/javascripts/support/jasmine.yml +81 -0
  55. data/spec/javascripts/support/jasmine_runner.rb +21 -0
  56. metadata +108 -0
@@ -0,0 +1,2343 @@
1
+ /**
2
+ * Top level namespace for Jasmine, a lightweight JavaScript BDD/spec/testing framework.
3
+ *
4
+ * @namespace
5
+ */
6
+ var jasmine = {};
7
+
8
+ /**
9
+ * @private
10
+ */
11
+ jasmine.unimplementedMethod_ = function() {
12
+ throw new Error("unimplemented method");
13
+ };
14
+
15
+ /**
16
+ * Use <code>jasmine.undefined</code> instead of <code>undefined</code>, since <code>undefined</code> is just
17
+ * a plain old variable and may be redefined by somebody else.
18
+ *
19
+ * @private
20
+ */
21
+ jasmine.undefined = jasmine.___undefined___;
22
+
23
+ /**
24
+ * Default interval for event loop yields. Small values here may result in slow test running. Zero means no updates until all tests have completed.
25
+ *
26
+ */
27
+ jasmine.DEFAULT_UPDATE_INTERVAL = 250;
28
+
29
+ jasmine.getGlobal = function() {
30
+ function getGlobal() {
31
+ return this;
32
+ }
33
+
34
+ return getGlobal();
35
+ };
36
+
37
+ /**
38
+ * Allows for bound functions to be compared. Internal use only.
39
+ *
40
+ * @ignore
41
+ * @private
42
+ * @param base {Object} bound 'this' for the function
43
+ * @param name {Function} function to find
44
+ */
45
+ jasmine.bindOriginal_ = function(base, name) {
46
+ var original = base[name];
47
+ if (original.apply) {
48
+ return function() {
49
+ return original.apply(base, arguments);
50
+ };
51
+ } else {
52
+ // IE support
53
+ return jasmine.getGlobal()[name];
54
+ }
55
+ };
56
+
57
+ jasmine.setTimeout = jasmine.bindOriginal_(jasmine.getGlobal(), 'setTimeout');
58
+ jasmine.clearTimeout = jasmine.bindOriginal_(jasmine.getGlobal(), 'clearTimeout');
59
+ jasmine.setInterval = jasmine.bindOriginal_(jasmine.getGlobal(), 'setInterval');
60
+ jasmine.clearInterval = jasmine.bindOriginal_(jasmine.getGlobal(), 'clearInterval');
61
+
62
+ jasmine.MessageResult = function(values) {
63
+ this.type = 'log';
64
+ this.values = values;
65
+ this.trace = new Error(); // todo: test better
66
+ };
67
+
68
+ jasmine.MessageResult.prototype.toString = function() {
69
+ var text = "";
70
+ for(var i = 0; i < this.values.length; i++) {
71
+ if (i > 0) text += " ";
72
+ if (jasmine.isString_(this.values[i])) {
73
+ text += this.values[i];
74
+ } else {
75
+ text += jasmine.pp(this.values[i]);
76
+ }
77
+ }
78
+ return text;
79
+ };
80
+
81
+ jasmine.ExpectationResult = function(params) {
82
+ this.type = 'expect';
83
+ this.matcherName = params.matcherName;
84
+ this.passed_ = params.passed;
85
+ this.expected = params.expected;
86
+ this.actual = params.actual;
87
+
88
+ this.message = this.passed_ ? 'Passed.' : params.message;
89
+ this.trace = this.passed_ ? '' : new Error(this.message);
90
+ };
91
+
92
+ jasmine.ExpectationResult.prototype.toString = function () {
93
+ return this.message;
94
+ };
95
+
96
+ jasmine.ExpectationResult.prototype.passed = function () {
97
+ return this.passed_;
98
+ };
99
+
100
+ /**
101
+ * Getter for the Jasmine environment. Ensures one gets created
102
+ */
103
+ jasmine.getEnv = function() {
104
+ return jasmine.currentEnv_ = jasmine.currentEnv_ || new jasmine.Env();
105
+ };
106
+
107
+ /**
108
+ * @ignore
109
+ * @private
110
+ * @param value
111
+ * @returns {Boolean}
112
+ */
113
+ jasmine.isArray_ = function(value) {
114
+ return jasmine.isA_("Array", value);
115
+ };
116
+
117
+ /**
118
+ * @ignore
119
+ * @private
120
+ * @param value
121
+ * @returns {Boolean}
122
+ */
123
+ jasmine.isString_ = function(value) {
124
+ return jasmine.isA_("String", value);
125
+ };
126
+
127
+ /**
128
+ * @ignore
129
+ * @private
130
+ * @param value
131
+ * @returns {Boolean}
132
+ */
133
+ jasmine.isNumber_ = function(value) {
134
+ return jasmine.isA_("Number", value);
135
+ };
136
+
137
+ /**
138
+ * @ignore
139
+ * @private
140
+ * @param {String} typeName
141
+ * @param value
142
+ * @returns {Boolean}
143
+ */
144
+ jasmine.isA_ = function(typeName, value) {
145
+ return Object.prototype.toString.apply(value) === '[object ' + typeName + ']';
146
+ };
147
+
148
+ /**
149
+ * Pretty printer for expecations. Takes any object and turns it into a human-readable string.
150
+ *
151
+ * @param value {Object} an object to be outputted
152
+ * @returns {String}
153
+ */
154
+ jasmine.pp = function(value) {
155
+ var stringPrettyPrinter = new jasmine.StringPrettyPrinter();
156
+ stringPrettyPrinter.format(value);
157
+ return stringPrettyPrinter.string;
158
+ };
159
+
160
+ /**
161
+ * Returns true if the object is a DOM Node.
162
+ *
163
+ * @param {Object} obj object to check
164
+ * @returns {Boolean}
165
+ */
166
+ jasmine.isDomNode = function(obj) {
167
+ return obj['nodeType'] > 0;
168
+ };
169
+
170
+ /**
171
+ * Returns a matchable 'generic' object of the class type. For use in expecations of type when values don't matter.
172
+ *
173
+ * @example
174
+ * // don't care about which function is passed in, as long as it's a function
175
+ * expect(mySpy).toHaveBeenCalledWith(jasmine.any(Function));
176
+ *
177
+ * @param {Class} clazz
178
+ * @returns matchable object of the type clazz
179
+ */
180
+ jasmine.any = function(clazz) {
181
+ return new jasmine.Matchers.Any(clazz);
182
+ };
183
+
184
+ /**
185
+ * Jasmine Spies are test doubles that can act as stubs, spies, fakes or when used in an expecation, mocks.
186
+ *
187
+ * Spies should be created in test setup, before expectations. They can then be checked, using the standard Jasmine
188
+ * expectation syntax. Spies can be checked if they were called or not and what the calling params were.
189
+ *
190
+ * A Spy has the following fields: wasCalled, callCount, mostRecentCall, and argsForCall (see docs).
191
+ *
192
+ * Spies are torn down at the end of every spec.
193
+ *
194
+ * Note: Do <b>not</b> call new jasmine.Spy() directly - a spy must be created using spyOn, jasmine.createSpy or jasmine.createSpyObj.
195
+ *
196
+ * @example
197
+ * // a stub
198
+ * var myStub = jasmine.createSpy('myStub'); // can be used anywhere
199
+ *
200
+ * // spy example
201
+ * var foo = {
202
+ * not: function(bool) { return !bool; }
203
+ * }
204
+ *
205
+ * // actual foo.not will not be called, execution stops
206
+ * spyOn(foo, 'not');
207
+
208
+ // foo.not spied upon, execution will continue to implementation
209
+ * spyOn(foo, 'not').andCallThrough();
210
+ *
211
+ * // fake example
212
+ * var foo = {
213
+ * not: function(bool) { return !bool; }
214
+ * }
215
+ *
216
+ * // foo.not(val) will return val
217
+ * spyOn(foo, 'not').andCallFake(function(value) {return value;});
218
+ *
219
+ * // mock example
220
+ * foo.not(7 == 7);
221
+ * expect(foo.not).toHaveBeenCalled();
222
+ * expect(foo.not).toHaveBeenCalledWith(true);
223
+ *
224
+ * @constructor
225
+ * @see spyOn, jasmine.createSpy, jasmine.createSpyObj
226
+ * @param {String} name
227
+ */
228
+ jasmine.Spy = function(name) {
229
+ /**
230
+ * The name of the spy, if provided.
231
+ */
232
+ this.identity = name || 'unknown';
233
+ /**
234
+ * Is this Object a spy?
235
+ */
236
+ this.isSpy = true;
237
+ /**
238
+ * The actual function this spy stubs.
239
+ */
240
+ this.plan = function() {
241
+ };
242
+ /**
243
+ * Tracking of the most recent call to the spy.
244
+ * @example
245
+ * var mySpy = jasmine.createSpy('foo');
246
+ * mySpy(1, 2);
247
+ * mySpy.mostRecentCall.args = [1, 2];
248
+ */
249
+ this.mostRecentCall = {};
250
+
251
+ /**
252
+ * Holds arguments for each call to the spy, indexed by call count
253
+ * @example
254
+ * var mySpy = jasmine.createSpy('foo');
255
+ * mySpy(1, 2);
256
+ * mySpy(7, 8);
257
+ * mySpy.mostRecentCall.args = [7, 8];
258
+ * mySpy.argsForCall[0] = [1, 2];
259
+ * mySpy.argsForCall[1] = [7, 8];
260
+ */
261
+ this.argsForCall = [];
262
+ this.calls = [];
263
+ };
264
+
265
+ /**
266
+ * Tells a spy to call through to the actual implemenatation.
267
+ *
268
+ * @example
269
+ * var foo = {
270
+ * bar: function() { // do some stuff }
271
+ * }
272
+ *
273
+ * // defining a spy on an existing property: foo.bar
274
+ * spyOn(foo, 'bar').andCallThrough();
275
+ */
276
+ jasmine.Spy.prototype.andCallThrough = function() {
277
+ this.plan = this.originalValue;
278
+ return this;
279
+ };
280
+
281
+ /**
282
+ * For setting the return value of a spy.
283
+ *
284
+ * @example
285
+ * // defining a spy from scratch: foo() returns 'baz'
286
+ * var foo = jasmine.createSpy('spy on foo').andReturn('baz');
287
+ *
288
+ * // defining a spy on an existing property: foo.bar() returns 'baz'
289
+ * spyOn(foo, 'bar').andReturn('baz');
290
+ *
291
+ * @param {Object} value
292
+ */
293
+ jasmine.Spy.prototype.andReturn = function(value) {
294
+ this.plan = function() {
295
+ return value;
296
+ };
297
+ return this;
298
+ };
299
+
300
+ /**
301
+ * For throwing an exception when a spy is called.
302
+ *
303
+ * @example
304
+ * // defining a spy from scratch: foo() throws an exception w/ message 'ouch'
305
+ * var foo = jasmine.createSpy('spy on foo').andThrow('baz');
306
+ *
307
+ * // defining a spy on an existing property: foo.bar() throws an exception w/ message 'ouch'
308
+ * spyOn(foo, 'bar').andThrow('baz');
309
+ *
310
+ * @param {String} exceptionMsg
311
+ */
312
+ jasmine.Spy.prototype.andThrow = function(exceptionMsg) {
313
+ this.plan = function() {
314
+ throw exceptionMsg;
315
+ };
316
+ return this;
317
+ };
318
+
319
+ /**
320
+ * Calls an alternate implementation when a spy is called.
321
+ *
322
+ * @example
323
+ * var baz = function() {
324
+ * // do some stuff, return something
325
+ * }
326
+ * // defining a spy from scratch: foo() calls the function baz
327
+ * var foo = jasmine.createSpy('spy on foo').andCall(baz);
328
+ *
329
+ * // defining a spy on an existing property: foo.bar() calls an anonymnous function
330
+ * spyOn(foo, 'bar').andCall(function() { return 'baz';} );
331
+ *
332
+ * @param {Function} fakeFunc
333
+ */
334
+ jasmine.Spy.prototype.andCallFake = function(fakeFunc) {
335
+ this.plan = fakeFunc;
336
+ return this;
337
+ };
338
+
339
+ /**
340
+ * Resets all of a spy's the tracking variables so that it can be used again.
341
+ *
342
+ * @example
343
+ * spyOn(foo, 'bar');
344
+ *
345
+ * foo.bar();
346
+ *
347
+ * expect(foo.bar.callCount).toEqual(1);
348
+ *
349
+ * foo.bar.reset();
350
+ *
351
+ * expect(foo.bar.callCount).toEqual(0);
352
+ */
353
+ jasmine.Spy.prototype.reset = function() {
354
+ this.wasCalled = false;
355
+ this.callCount = 0;
356
+ this.argsForCall = [];
357
+ this.calls = [];
358
+ this.mostRecentCall = {};
359
+ };
360
+
361
+ jasmine.createSpy = function(name) {
362
+
363
+ var spyObj = function() {
364
+ spyObj.wasCalled = true;
365
+ spyObj.callCount++;
366
+ var args = jasmine.util.argsToArray(arguments);
367
+ spyObj.mostRecentCall.object = this;
368
+ spyObj.mostRecentCall.args = args;
369
+ spyObj.argsForCall.push(args);
370
+ spyObj.calls.push({object: this, args: args});
371
+ return spyObj.plan.apply(this, arguments);
372
+ };
373
+
374
+ var spy = new jasmine.Spy(name);
375
+
376
+ for (var prop in spy) {
377
+ spyObj[prop] = spy[prop];
378
+ }
379
+
380
+ spyObj.reset();
381
+
382
+ return spyObj;
383
+ };
384
+
385
+ /**
386
+ * Determines whether an object is a spy.
387
+ *
388
+ * @param {jasmine.Spy|Object} putativeSpy
389
+ * @returns {Boolean}
390
+ */
391
+ jasmine.isSpy = function(putativeSpy) {
392
+ return putativeSpy && putativeSpy.isSpy;
393
+ };
394
+
395
+ /**
396
+ * Creates a more complicated spy: an Object that has every property a function that is a spy. Used for stubbing something
397
+ * large in one call.
398
+ *
399
+ * @param {String} baseName name of spy class
400
+ * @param {Array} methodNames array of names of methods to make spies
401
+ */
402
+ jasmine.createSpyObj = function(baseName, methodNames) {
403
+ if (!jasmine.isArray_(methodNames) || methodNames.length == 0) {
404
+ throw new Error('createSpyObj requires a non-empty array of method names to create spies for');
405
+ }
406
+ var obj = {};
407
+ for (var i = 0; i < methodNames.length; i++) {
408
+ obj[methodNames[i]] = jasmine.createSpy(baseName + '.' + methodNames[i]);
409
+ }
410
+ return obj;
411
+ };
412
+
413
+ /**
414
+ * All parameters are pretty-printed and concatenated together, then written to the current spec's output.
415
+ *
416
+ * Be careful not to leave calls to <code>jasmine.log</code> in production code.
417
+ */
418
+ jasmine.log = function() {
419
+ var spec = jasmine.getEnv().currentSpec;
420
+ spec.log.apply(spec, arguments);
421
+ };
422
+
423
+ /**
424
+ * Function that installs a spy on an existing object's method name. Used within a Spec to create a spy.
425
+ *
426
+ * @example
427
+ * // spy example
428
+ * var foo = {
429
+ * not: function(bool) { return !bool; }
430
+ * }
431
+ * spyOn(foo, 'not'); // actual foo.not will not be called, execution stops
432
+ *
433
+ * @see jasmine.createSpy
434
+ * @param obj
435
+ * @param methodName
436
+ * @returns a Jasmine spy that can be chained with all spy methods
437
+ */
438
+ var spyOn = function(obj, methodName) {
439
+ return jasmine.getEnv().currentSpec.spyOn(obj, methodName);
440
+ };
441
+
442
+ /**
443
+ * Creates a Jasmine spec that will be added to the current suite.
444
+ *
445
+ * // TODO: pending tests
446
+ *
447
+ * @example
448
+ * it('should be true', function() {
449
+ * expect(true).toEqual(true);
450
+ * });
451
+ *
452
+ * @param {String} desc description of this specification
453
+ * @param {Function} func defines the preconditions and expectations of the spec
454
+ */
455
+ var it = function(desc, func) {
456
+ return jasmine.getEnv().it(desc, func);
457
+ };
458
+
459
+ /**
460
+ * Creates a <em>disabled</em> Jasmine spec.
461
+ *
462
+ * A convenience method that allows existing specs to be disabled temporarily during development.
463
+ *
464
+ * @param {String} desc description of this specification
465
+ * @param {Function} func defines the preconditions and expectations of the spec
466
+ */
467
+ var xit = function(desc, func) {
468
+ return jasmine.getEnv().xit(desc, func);
469
+ };
470
+
471
+ /**
472
+ * Starts a chain for a Jasmine expectation.
473
+ *
474
+ * It is passed an Object that is the actual value and should chain to one of the many
475
+ * jasmine.Matchers functions.
476
+ *
477
+ * @param {Object} actual Actual value to test against and expected value
478
+ */
479
+ var expect = function(actual) {
480
+ return jasmine.getEnv().currentSpec.expect(actual);
481
+ };
482
+
483
+ /**
484
+ * Defines part of a jasmine spec. Used in cominbination with waits or waitsFor in asynchrnous specs.
485
+ *
486
+ * @param {Function} func Function that defines part of a jasmine spec.
487
+ */
488
+ var runs = function(func) {
489
+ jasmine.getEnv().currentSpec.runs(func);
490
+ };
491
+
492
+ /**
493
+ * Waits for a timeout before moving to the next runs()-defined block.
494
+ * @param {Number} timeout
495
+ */
496
+ var waits = function(timeout) {
497
+ jasmine.getEnv().currentSpec.waits(timeout);
498
+ };
499
+
500
+ /**
501
+ * Waits for the latchFunction to return true before proceeding to the next runs()-defined block.
502
+ *
503
+ * @param {Number} timeout
504
+ * @param {Function} latchFunction
505
+ * @param {String} message
506
+ */
507
+ var waitsFor = function(timeout, latchFunction, message) {
508
+ jasmine.getEnv().currentSpec.waitsFor(timeout, latchFunction, message);
509
+ };
510
+
511
+ /**
512
+ * A function that is called before each spec in a suite.
513
+ *
514
+ * Used for spec setup, including validating assumptions.
515
+ *
516
+ * @param {Function} beforeEachFunction
517
+ */
518
+ var beforeEach = function(beforeEachFunction) {
519
+ jasmine.getEnv().beforeEach(beforeEachFunction);
520
+ };
521
+
522
+ /**
523
+ * A function that is called after each spec in a suite.
524
+ *
525
+ * Used for restoring any state that is hijacked during spec execution.
526
+ *
527
+ * @param {Function} afterEachFunction
528
+ */
529
+ var afterEach = function(afterEachFunction) {
530
+ jasmine.getEnv().afterEach(afterEachFunction);
531
+ };
532
+
533
+ /**
534
+ * Defines a suite of specifications.
535
+ *
536
+ * Stores the description and all defined specs in the Jasmine environment as one suite of specs. Variables declared
537
+ * are accessible by calls to beforeEach, it, and afterEach. Describe blocks can be nested, allowing for specialization
538
+ * of setup in some tests.
539
+ *
540
+ * @example
541
+ * // TODO: a simple suite
542
+ *
543
+ * // TODO: a simple suite with a nested describe block
544
+ *
545
+ * @param {String} description A string, usually the class under test.
546
+ * @param {Function} specDefinitions function that defines several specs.
547
+ */
548
+ var describe = function(description, specDefinitions) {
549
+ return jasmine.getEnv().describe(description, specDefinitions);
550
+ };
551
+
552
+ /**
553
+ * Disables a suite of specifications. Used to disable some suites in a file, or files, temporarily during development.
554
+ *
555
+ * @param {String} description A string, usually the class under test.
556
+ * @param {Function} specDefinitions function that defines several specs.
557
+ */
558
+ var xdescribe = function(description, specDefinitions) {
559
+ return jasmine.getEnv().xdescribe(description, specDefinitions);
560
+ };
561
+
562
+
563
+ // Provide the XMLHttpRequest class for IE 5.x-6.x:
564
+ jasmine.XmlHttpRequest = (typeof XMLHttpRequest == "undefined") ? function() {
565
+ try {
566
+ return new ActiveXObject("Msxml2.XMLHTTP.6.0");
567
+ } catch(e) {
568
+ }
569
+ try {
570
+ return new ActiveXObject("Msxml2.XMLHTTP.3.0");
571
+ } catch(e) {
572
+ }
573
+ try {
574
+ return new ActiveXObject("Msxml2.XMLHTTP");
575
+ } catch(e) {
576
+ }
577
+ try {
578
+ return new ActiveXObject("Microsoft.XMLHTTP");
579
+ } catch(e) {
580
+ }
581
+ throw new Error("This browser does not support XMLHttpRequest.");
582
+ } : XMLHttpRequest;
583
+ /**
584
+ * @namespace
585
+ */
586
+ jasmine.util = {};
587
+
588
+ /**
589
+ * Declare that a child class inherit it's prototype from the parent class.
590
+ *
591
+ * @private
592
+ * @param {Function} childClass
593
+ * @param {Function} parentClass
594
+ */
595
+ jasmine.util.inherit = function(childClass, parentClass) {
596
+ /**
597
+ * @private
598
+ */
599
+ var subclass = function() {
600
+ };
601
+ subclass.prototype = parentClass.prototype;
602
+ childClass.prototype = new subclass;
603
+ };
604
+
605
+ jasmine.util.formatException = function(e) {
606
+ var lineNumber;
607
+ if (e.line) {
608
+ lineNumber = e.line;
609
+ }
610
+ else if (e.lineNumber) {
611
+ lineNumber = e.lineNumber;
612
+ }
613
+
614
+ var file;
615
+
616
+ if (e.sourceURL) {
617
+ file = e.sourceURL;
618
+ }
619
+ else if (e.fileName) {
620
+ file = e.fileName;
621
+ }
622
+
623
+ var message = (e.name && e.message) ? (e.name + ': ' + e.message) : e.toString();
624
+
625
+ if (file && lineNumber) {
626
+ message += ' in ' + file + ' (line ' + lineNumber + ')';
627
+ }
628
+
629
+ return message;
630
+ };
631
+
632
+ jasmine.util.htmlEscape = function(str) {
633
+ if (!str) return str;
634
+ return str.replace(/&/g, '&amp;')
635
+ .replace(/</g, '&lt;')
636
+ .replace(/>/g, '&gt;');
637
+ };
638
+
639
+ jasmine.util.argsToArray = function(args) {
640
+ var arrayOfArgs = [];
641
+ for (var i = 0; i < args.length; i++) arrayOfArgs.push(args[i]);
642
+ return arrayOfArgs;
643
+ };
644
+
645
+ jasmine.util.extend = function(destination, source) {
646
+ for (var property in source) destination[property] = source[property];
647
+ return destination;
648
+ };
649
+
650
+ /**
651
+ * Environment for Jasmine
652
+ *
653
+ * @constructor
654
+ */
655
+ jasmine.Env = function() {
656
+ this.currentSpec = null;
657
+ this.currentSuite = null;
658
+ this.currentRunner_ = new jasmine.Runner(this);
659
+
660
+ this.reporter = new jasmine.MultiReporter();
661
+
662
+ this.updateInterval = jasmine.DEFAULT_UPDATE_INTERVAL;
663
+ this.lastUpdate = 0;
664
+ this.specFilter = function() {
665
+ return true;
666
+ };
667
+
668
+ this.nextSpecId_ = 0;
669
+ this.nextSuiteId_ = 0;
670
+ this.equalityTesters_ = [];
671
+
672
+ // wrap matchers
673
+ this.matchersClass = function() {
674
+ jasmine.Matchers.apply(this, arguments);
675
+ };
676
+ jasmine.util.inherit(this.matchersClass, jasmine.Matchers);
677
+
678
+ jasmine.Matchers.wrapInto_(jasmine.Matchers.prototype, this.matchersClass);
679
+ };
680
+
681
+
682
+ jasmine.Env.prototype.setTimeout = jasmine.setTimeout;
683
+ jasmine.Env.prototype.clearTimeout = jasmine.clearTimeout;
684
+ jasmine.Env.prototype.setInterval = jasmine.setInterval;
685
+ jasmine.Env.prototype.clearInterval = jasmine.clearInterval;
686
+
687
+ /**
688
+ * @returns an object containing jasmine version build info, if set.
689
+ */
690
+ jasmine.Env.prototype.version = function () {
691
+ if (jasmine.version_) {
692
+ return jasmine.version_;
693
+ } else {
694
+ throw new Error('Version not set');
695
+ }
696
+ };
697
+
698
+ /**
699
+ * @returns string containing jasmine version build info, if set.
700
+ */
701
+ jasmine.Env.prototype.versionString = function() {
702
+ if (jasmine.version_) {
703
+ var version = this.version();
704
+ return version.major + "." + version.minor + "." + version.build + " revision " + version.revision;
705
+ } else {
706
+ return "version unknown";
707
+ }
708
+ };
709
+
710
+ /**
711
+ * @returns a sequential integer starting at 0
712
+ */
713
+ jasmine.Env.prototype.nextSpecId = function () {
714
+ return this.nextSpecId_++;
715
+ };
716
+
717
+ /**
718
+ * @returns a sequential integer starting at 0
719
+ */
720
+ jasmine.Env.prototype.nextSuiteId = function () {
721
+ return this.nextSuiteId_++;
722
+ };
723
+
724
+ /**
725
+ * Register a reporter to receive status updates from Jasmine.
726
+ * @param {jasmine.Reporter} reporter An object which will receive status updates.
727
+ */
728
+ jasmine.Env.prototype.addReporter = function(reporter) {
729
+ this.reporter.addReporter(reporter);
730
+ };
731
+
732
+ jasmine.Env.prototype.execute = function() {
733
+ this.currentRunner_.execute();
734
+ };
735
+
736
+ jasmine.Env.prototype.describe = function(description, specDefinitions) {
737
+ var suite = new jasmine.Suite(this, description, specDefinitions, this.currentSuite);
738
+
739
+ var parentSuite = this.currentSuite;
740
+ if (parentSuite) {
741
+ parentSuite.add(suite);
742
+ } else {
743
+ this.currentRunner_.add(suite);
744
+ }
745
+
746
+ this.currentSuite = suite;
747
+
748
+ var declarationError = null;
749
+ try {
750
+ specDefinitions.call(suite);
751
+ } catch(e) {
752
+ declarationError = e;
753
+ }
754
+
755
+ this.currentSuite = parentSuite;
756
+
757
+ if (declarationError) {
758
+ this.it("encountered a declaration exception", function() {
759
+ throw declarationError;
760
+ });
761
+ }
762
+
763
+ return suite;
764
+ };
765
+
766
+ jasmine.Env.prototype.beforeEach = function(beforeEachFunction) {
767
+ if (this.currentSuite) {
768
+ this.currentSuite.beforeEach(beforeEachFunction);
769
+ } else {
770
+ this.currentRunner_.beforeEach(beforeEachFunction);
771
+ }
772
+ };
773
+
774
+ jasmine.Env.prototype.currentRunner = function () {
775
+ return this.currentRunner_;
776
+ };
777
+
778
+ jasmine.Env.prototype.afterEach = function(afterEachFunction) {
779
+ if (this.currentSuite) {
780
+ this.currentSuite.afterEach(afterEachFunction);
781
+ } else {
782
+ this.currentRunner_.afterEach(afterEachFunction);
783
+ }
784
+
785
+ };
786
+
787
+ jasmine.Env.prototype.xdescribe = function(desc, specDefinitions) {
788
+ return {
789
+ execute: function() {
790
+ }
791
+ };
792
+ };
793
+
794
+ jasmine.Env.prototype.it = function(description, func) {
795
+ var spec = new jasmine.Spec(this, this.currentSuite, description);
796
+ this.currentSuite.add(spec);
797
+ this.currentSpec = spec;
798
+
799
+ if (func) {
800
+ spec.runs(func);
801
+ }
802
+
803
+ return spec;
804
+ };
805
+
806
+ jasmine.Env.prototype.xit = function(desc, func) {
807
+ return {
808
+ id: this.nextSpecId(),
809
+ runs: function() {
810
+ }
811
+ };
812
+ };
813
+
814
+ jasmine.Env.prototype.compareObjects_ = function(a, b, mismatchKeys, mismatchValues) {
815
+ if (a.__Jasmine_been_here_before__ === b && b.__Jasmine_been_here_before__ === a) {
816
+ return true;
817
+ }
818
+
819
+ a.__Jasmine_been_here_before__ = b;
820
+ b.__Jasmine_been_here_before__ = a;
821
+
822
+ var hasKey = function(obj, keyName) {
823
+ return obj != null && obj[keyName] !== jasmine.undefined;
824
+ };
825
+
826
+ for (var property in b) {
827
+ if (!hasKey(a, property) && hasKey(b, property)) {
828
+ mismatchKeys.push("expected has key '" + property + "', but missing from actual.");
829
+ }
830
+ }
831
+ for (property in a) {
832
+ if (!hasKey(b, property) && hasKey(a, property)) {
833
+ mismatchKeys.push("expected missing key '" + property + "', but present in actual.");
834
+ }
835
+ }
836
+ for (property in b) {
837
+ if (property == '__Jasmine_been_here_before__') continue;
838
+ if (!this.equals_(a[property], b[property], mismatchKeys, mismatchValues)) {
839
+ mismatchValues.push("'" + property + "' was '" + (b[property] ? jasmine.util.htmlEscape(b[property].toString()) : b[property]) + "' in expected, but was '" + (a[property] ? jasmine.util.htmlEscape(a[property].toString()) : a[property]) + "' in actual.");
840
+ }
841
+ }
842
+
843
+ if (jasmine.isArray_(a) && jasmine.isArray_(b) && a.length != b.length) {
844
+ mismatchValues.push("arrays were not the same length");
845
+ }
846
+
847
+ delete a.__Jasmine_been_here_before__;
848
+ delete b.__Jasmine_been_here_before__;
849
+ return (mismatchKeys.length == 0 && mismatchValues.length == 0);
850
+ };
851
+
852
+ jasmine.Env.prototype.equals_ = function(a, b, mismatchKeys, mismatchValues) {
853
+ mismatchKeys = mismatchKeys || [];
854
+ mismatchValues = mismatchValues || [];
855
+
856
+ for (var i = 0; i < this.equalityTesters_.length; i++) {
857
+ var equalityTester = this.equalityTesters_[i];
858
+ var result = equalityTester(a, b, this, mismatchKeys, mismatchValues);
859
+ if (result !== jasmine.undefined) return result;
860
+ }
861
+
862
+ if (a === b) return true;
863
+
864
+ if (a === jasmine.undefined || a === null || b === jasmine.undefined || b === null) {
865
+ return (a == jasmine.undefined && b == jasmine.undefined);
866
+ }
867
+
868
+ if (jasmine.isDomNode(a) && jasmine.isDomNode(b)) {
869
+ return a === b;
870
+ }
871
+
872
+ if (a instanceof Date && b instanceof Date) {
873
+ return a.getTime() == b.getTime();
874
+ }
875
+
876
+ if (a instanceof jasmine.Matchers.Any) {
877
+ return a.matches(b);
878
+ }
879
+
880
+ if (b instanceof jasmine.Matchers.Any) {
881
+ return b.matches(a);
882
+ }
883
+
884
+ if (jasmine.isString_(a) && jasmine.isString_(b)) {
885
+ return (a == b);
886
+ }
887
+
888
+ if (jasmine.isNumber_(a) && jasmine.isNumber_(b)) {
889
+ return (a == b);
890
+ }
891
+
892
+ if (typeof a === "object" && typeof b === "object") {
893
+ return this.compareObjects_(a, b, mismatchKeys, mismatchValues);
894
+ }
895
+
896
+ //Straight check
897
+ return (a === b);
898
+ };
899
+
900
+ jasmine.Env.prototype.contains_ = function(haystack, needle) {
901
+ if (jasmine.isArray_(haystack)) {
902
+ for (var i = 0; i < haystack.length; i++) {
903
+ if (this.equals_(haystack[i], needle)) return true;
904
+ }
905
+ return false;
906
+ }
907
+ return haystack.indexOf(needle) >= 0;
908
+ };
909
+
910
+ jasmine.Env.prototype.addEqualityTester = function(equalityTester) {
911
+ this.equalityTesters_.push(equalityTester);
912
+ };
913
+ /** No-op base class for Jasmine reporters.
914
+ *
915
+ * @constructor
916
+ */
917
+ jasmine.Reporter = function() {
918
+ };
919
+
920
+ //noinspection JSUnusedLocalSymbols
921
+ jasmine.Reporter.prototype.reportRunnerStarting = function(runner) {
922
+ };
923
+
924
+ //noinspection JSUnusedLocalSymbols
925
+ jasmine.Reporter.prototype.reportRunnerResults = function(runner) {
926
+ };
927
+
928
+ //noinspection JSUnusedLocalSymbols
929
+ jasmine.Reporter.prototype.reportSuiteResults = function(suite) {
930
+ };
931
+
932
+ //noinspection JSUnusedLocalSymbols
933
+ jasmine.Reporter.prototype.reportSpecStarting = function(spec) {
934
+ };
935
+
936
+ //noinspection JSUnusedLocalSymbols
937
+ jasmine.Reporter.prototype.reportSpecResults = function(spec) {
938
+ };
939
+
940
+ //noinspection JSUnusedLocalSymbols
941
+ jasmine.Reporter.prototype.log = function(str) {
942
+ };
943
+
944
+ /**
945
+ * Blocks are functions with executable code that make up a spec.
946
+ *
947
+ * @constructor
948
+ * @param {jasmine.Env} env
949
+ * @param {Function} func
950
+ * @param {jasmine.Spec} spec
951
+ */
952
+ jasmine.Block = function(env, func, spec) {
953
+ this.env = env;
954
+ this.func = func;
955
+ this.spec = spec;
956
+ };
957
+
958
+ jasmine.Block.prototype.execute = function(onComplete) {
959
+ try {
960
+ this.func.apply(this.spec);
961
+ } catch (e) {
962
+ this.spec.fail(e);
963
+ }
964
+ onComplete();
965
+ };
966
+ /** JavaScript API reporter.
967
+ *
968
+ * @constructor
969
+ */
970
+ jasmine.JsApiReporter = function() {
971
+ this.started = false;
972
+ this.finished = false;
973
+ this.suites_ = [];
974
+ this.results_ = {};
975
+ };
976
+
977
+ jasmine.JsApiReporter.prototype.reportRunnerStarting = function(runner) {
978
+ this.started = true;
979
+ var suites = runner.topLevelSuites();
980
+ for (var i = 0; i < suites.length; i++) {
981
+ var suite = suites[i];
982
+ this.suites_.push(this.summarize_(suite));
983
+ }
984
+ };
985
+
986
+ jasmine.JsApiReporter.prototype.suites = function() {
987
+ return this.suites_;
988
+ };
989
+
990
+ jasmine.JsApiReporter.prototype.summarize_ = function(suiteOrSpec) {
991
+ var isSuite = suiteOrSpec instanceof jasmine.Suite;
992
+ var summary = {
993
+ id: suiteOrSpec.id,
994
+ name: suiteOrSpec.description,
995
+ type: isSuite ? 'suite' : 'spec',
996
+ children: []
997
+ };
998
+
999
+ if (isSuite) {
1000
+ var children = suiteOrSpec.children();
1001
+ for (var i = 0; i < children.length; i++) {
1002
+ summary.children.push(this.summarize_(children[i]));
1003
+ }
1004
+ }
1005
+ return summary;
1006
+ };
1007
+
1008
+ jasmine.JsApiReporter.prototype.results = function() {
1009
+ return this.results_;
1010
+ };
1011
+
1012
+ jasmine.JsApiReporter.prototype.resultsForSpec = function(specId) {
1013
+ return this.results_[specId];
1014
+ };
1015
+
1016
+ //noinspection JSUnusedLocalSymbols
1017
+ jasmine.JsApiReporter.prototype.reportRunnerResults = function(runner) {
1018
+ this.finished = true;
1019
+ };
1020
+
1021
+ //noinspection JSUnusedLocalSymbols
1022
+ jasmine.JsApiReporter.prototype.reportSuiteResults = function(suite) {
1023
+ };
1024
+
1025
+ //noinspection JSUnusedLocalSymbols
1026
+ jasmine.JsApiReporter.prototype.reportSpecResults = function(spec) {
1027
+ this.results_[spec.id] = {
1028
+ messages: spec.results().getItems(),
1029
+ result: spec.results().failedCount > 0 ? "failed" : "passed"
1030
+ };
1031
+ };
1032
+
1033
+ //noinspection JSUnusedLocalSymbols
1034
+ jasmine.JsApiReporter.prototype.log = function(str) {
1035
+ };
1036
+
1037
+ jasmine.JsApiReporter.prototype.resultsForSpecs = function(specIds){
1038
+ var results = {};
1039
+ for (var i = 0; i < specIds.length; i++) {
1040
+ var specId = specIds[i];
1041
+ results[specId] = this.summarizeResult_(this.results_[specId]);
1042
+ }
1043
+ return results;
1044
+ };
1045
+
1046
+ jasmine.JsApiReporter.prototype.summarizeResult_ = function(result){
1047
+ var summaryMessages = [];
1048
+ var messagesLength = result.messages.length;
1049
+ for (var messageIndex = 0; messageIndex < messagesLength; messageIndex++) {
1050
+ var resultMessage = result.messages[messageIndex];
1051
+ summaryMessages.push({
1052
+ text: resultMessage.type == 'log' ? resultMessage.toString() : jasmine.undefined,
1053
+ passed: resultMessage.passed ? resultMessage.passed() : true,
1054
+ type: resultMessage.type,
1055
+ message: resultMessage.message,
1056
+ trace: {
1057
+ stack: resultMessage.passed && !resultMessage.passed() ? resultMessage.trace.stack : jasmine.undefined
1058
+ }
1059
+ });
1060
+ }
1061
+
1062
+ return {
1063
+ result : result.result,
1064
+ messages : summaryMessages
1065
+ };
1066
+ };
1067
+
1068
+ /**
1069
+ * @constructor
1070
+ * @param {jasmine.Env} env
1071
+ * @param actual
1072
+ * @param {jasmine.Spec} spec
1073
+ */
1074
+ jasmine.Matchers = function(env, actual, spec, opt_isNot) {
1075
+ this.env = env;
1076
+ this.actual = actual;
1077
+ this.spec = spec;
1078
+ this.isNot = opt_isNot || false;
1079
+ this.reportWasCalled_ = false;
1080
+ };
1081
+
1082
+ // todo: @deprecated as of Jasmine 0.11, remove soon [xw]
1083
+ jasmine.Matchers.pp = function(str) {
1084
+ throw new Error("jasmine.Matchers.pp() is no longer supported, please use jasmine.pp() instead!");
1085
+ };
1086
+
1087
+ // todo: @deprecated Deprecated as of Jasmine 0.10. Rewrite your custom matchers to return true or false. [xw]
1088
+ jasmine.Matchers.prototype.report = function(result, failing_message, details) {
1089
+ throw new Error("As of jasmine 0.11, custom matchers must be implemented differently -- please see jasmine docs");
1090
+ };
1091
+
1092
+ jasmine.Matchers.wrapInto_ = function(prototype, matchersClass) {
1093
+ for (var methodName in prototype) {
1094
+ if (methodName == 'report') continue;
1095
+ var orig = prototype[methodName];
1096
+ matchersClass.prototype[methodName] = jasmine.Matchers.matcherFn_(methodName, orig);
1097
+ }
1098
+ };
1099
+
1100
+ jasmine.Matchers.matcherFn_ = function(matcherName, matcherFunction) {
1101
+ return function() {
1102
+ var matcherArgs = jasmine.util.argsToArray(arguments);
1103
+ var result = matcherFunction.apply(this, arguments);
1104
+
1105
+ if (this.isNot) {
1106
+ result = !result;
1107
+ }
1108
+
1109
+ if (this.reportWasCalled_) return result;
1110
+
1111
+ var message;
1112
+ if (!result) {
1113
+ if (this.message) {
1114
+ message = this.message.apply(this, arguments);
1115
+ if (jasmine.isArray_(message)) {
1116
+ message = message[this.isNot ? 1 : 0];
1117
+ }
1118
+ } else {
1119
+ var englishyPredicate = matcherName.replace(/[A-Z]/g, function(s) { return ' ' + s.toLowerCase(); });
1120
+ message = "Expected " + jasmine.pp(this.actual) + (this.isNot ? " not " : " ") + englishyPredicate;
1121
+ if (matcherArgs.length > 0) {
1122
+ for (var i = 0; i < matcherArgs.length; i++) {
1123
+ if (i > 0) message += ",";
1124
+ message += " " + jasmine.pp(matcherArgs[i]);
1125
+ }
1126
+ }
1127
+ message += ".";
1128
+ }
1129
+ }
1130
+ var expectationResult = new jasmine.ExpectationResult({
1131
+ matcherName: matcherName,
1132
+ passed: result,
1133
+ expected: matcherArgs.length > 1 ? matcherArgs : matcherArgs[0],
1134
+ actual: this.actual,
1135
+ message: message
1136
+ });
1137
+ this.spec.addMatcherResult(expectationResult);
1138
+ return result;
1139
+ };
1140
+ };
1141
+
1142
+
1143
+
1144
+
1145
+ /**
1146
+ * toBe: compares the actual to the expected using ===
1147
+ * @param expected
1148
+ */
1149
+ jasmine.Matchers.prototype.toBe = function(expected) {
1150
+ return this.actual === expected;
1151
+ };
1152
+
1153
+ /**
1154
+ * toNotBe: compares the actual to the expected using !==
1155
+ * @param expected
1156
+ */
1157
+ jasmine.Matchers.prototype.toNotBe = function(expected) {
1158
+ return this.actual !== expected;
1159
+ };
1160
+
1161
+ /**
1162
+ * toEqual: compares the actual to the expected using common sense equality. Handles Objects, Arrays, etc.
1163
+ *
1164
+ * @param expected
1165
+ */
1166
+ jasmine.Matchers.prototype.toEqual = function(expected) {
1167
+ return this.env.equals_(this.actual, expected);
1168
+ };
1169
+
1170
+ /**
1171
+ * toNotEqual: compares the actual to the expected using the ! of jasmine.Matchers.toEqual
1172
+ * @param expected
1173
+ */
1174
+ jasmine.Matchers.prototype.toNotEqual = function(expected) {
1175
+ return !this.env.equals_(this.actual, expected);
1176
+ };
1177
+
1178
+ /**
1179
+ * Matcher that compares the actual to the expected using a regular expression. Constructs a RegExp, so takes
1180
+ * a pattern or a String.
1181
+ *
1182
+ * @param expected
1183
+ */
1184
+ jasmine.Matchers.prototype.toMatch = function(expected) {
1185
+ return new RegExp(expected).test(this.actual);
1186
+ };
1187
+
1188
+ /**
1189
+ * Matcher that compares the actual to the expected using the boolean inverse of jasmine.Matchers.toMatch
1190
+ * @param expected
1191
+ */
1192
+ jasmine.Matchers.prototype.toNotMatch = function(expected) {
1193
+ return !(new RegExp(expected).test(this.actual));
1194
+ };
1195
+
1196
+ /**
1197
+ * Matcher that compares the actual to jasmine.undefined.
1198
+ */
1199
+ jasmine.Matchers.prototype.toBeDefined = function() {
1200
+ return (this.actual !== jasmine.undefined);
1201
+ };
1202
+
1203
+ /**
1204
+ * Matcher that compares the actual to jasmine.undefined.
1205
+ */
1206
+ jasmine.Matchers.prototype.toBeUndefined = function() {
1207
+ return (this.actual === jasmine.undefined);
1208
+ };
1209
+
1210
+ /**
1211
+ * Matcher that compares the actual to null.
1212
+ */
1213
+ jasmine.Matchers.prototype.toBeNull = function() {
1214
+ return (this.actual === null);
1215
+ };
1216
+
1217
+ /**
1218
+ * Matcher that boolean not-nots the actual.
1219
+ */
1220
+ jasmine.Matchers.prototype.toBeTruthy = function() {
1221
+ return !!this.actual;
1222
+ };
1223
+
1224
+
1225
+ /**
1226
+ * Matcher that boolean nots the actual.
1227
+ */
1228
+ jasmine.Matchers.prototype.toBeFalsy = function() {
1229
+ return !this.actual;
1230
+ };
1231
+
1232
+
1233
+ /** @deprecated Use expect(xxx).toHaveBeenCalled() instead */
1234
+ jasmine.Matchers.prototype.wasCalled = function() {
1235
+ return this.toHaveBeenCalled();
1236
+ };
1237
+
1238
+ /**
1239
+ * Matcher that checks to see if the actual, a Jasmine spy, was called.
1240
+ */
1241
+ jasmine.Matchers.prototype.toHaveBeenCalled = function() {
1242
+ if (arguments.length > 0) {
1243
+ throw new Error('toHaveBeenCalled does not take arguments, use toHaveBeenCalledWith');
1244
+ }
1245
+
1246
+ if (!jasmine.isSpy(this.actual)) {
1247
+ throw new Error('Expected a spy, but got ' + jasmine.pp(this.actual) + '.');
1248
+ }
1249
+
1250
+ this.message = function() {
1251
+ return "Expected spy " + this.actual.identity + " to have been called.";
1252
+ };
1253
+
1254
+ return this.actual.wasCalled;
1255
+ };
1256
+
1257
+ /**
1258
+ * Matcher that checks to see if the actual, a Jasmine spy, was not called.
1259
+ *
1260
+ * @deprecated Use expect(xxx).not.toHaveBeenCalled() instead
1261
+ */
1262
+ jasmine.Matchers.prototype.wasNotCalled = function() {
1263
+ if (arguments.length > 0) {
1264
+ throw new Error('wasNotCalled does not take arguments');
1265
+ }
1266
+
1267
+ if (!jasmine.isSpy(this.actual)) {
1268
+ throw new Error('Expected a spy, but got ' + jasmine.pp(this.actual) + '.');
1269
+ }
1270
+
1271
+ this.message = function() {
1272
+ return "Expected spy " + this.actual.identity + " to not have been called.";
1273
+ };
1274
+
1275
+ return !this.actual.wasCalled;
1276
+ };
1277
+
1278
+ /** @deprecated Use expect(xxx).toHaveBeenCalledWith() instead */
1279
+ jasmine.Matchers.prototype.wasCalledWith = function() {
1280
+ return this.toHaveBeenCalledWith.apply(this, arguments);
1281
+ };
1282
+
1283
+ /**
1284
+ * Matcher that checks to see if the actual, a Jasmine spy, was called with a set of parameters.
1285
+ *
1286
+ * @example
1287
+ *
1288
+ */
1289
+ jasmine.Matchers.prototype.toHaveBeenCalledWith = function() {
1290
+ var expectedArgs = jasmine.util.argsToArray(arguments);
1291
+ if (!jasmine.isSpy(this.actual)) {
1292
+ throw new Error('Expected a spy, but got ' + jasmine.pp(this.actual) + '.');
1293
+ }
1294
+ this.message = function() {
1295
+ if (this.actual.callCount == 0) {
1296
+ return "Expected spy to have been called with " + jasmine.pp(expectedArgs) + " but it was never called.";
1297
+ } else {
1298
+ return "Expected spy to have been called with " + jasmine.pp(expectedArgs) + " but was called with " + jasmine.pp(this.actual.argsForCall);
1299
+ }
1300
+ };
1301
+
1302
+ return this.env.contains_(this.actual.argsForCall, expectedArgs);
1303
+ };
1304
+
1305
+ /** @deprecated Use expect(xxx).not.toHaveBeenCalledWith() instead */
1306
+ jasmine.Matchers.prototype.wasNotCalledWith = function() {
1307
+ var expectedArgs = jasmine.util.argsToArray(arguments);
1308
+ if (!jasmine.isSpy(this.actual)) {
1309
+ throw new Error('Expected a spy, but got ' + jasmine.pp(this.actual) + '.');
1310
+ }
1311
+
1312
+ this.message = function() {
1313
+ return "Expected spy not to have been called with " + jasmine.pp(expectedArgs) + " but it was";
1314
+ };
1315
+
1316
+ return !this.env.contains_(this.actual.argsForCall, expectedArgs);
1317
+ };
1318
+
1319
+ /**
1320
+ * Matcher that checks that the expected item is an element in the actual Array.
1321
+ *
1322
+ * @param {Object} expected
1323
+ */
1324
+ jasmine.Matchers.prototype.toContain = function(expected) {
1325
+ return this.env.contains_(this.actual, expected);
1326
+ };
1327
+
1328
+ /**
1329
+ * Matcher that checks that the expected item is NOT an element in the actual Array.
1330
+ *
1331
+ * @param {Object} expected
1332
+ */
1333
+ jasmine.Matchers.prototype.toNotContain = function(expected) {
1334
+ return !this.env.contains_(this.actual, expected);
1335
+ };
1336
+
1337
+ jasmine.Matchers.prototype.toBeLessThan = function(expected) {
1338
+ return this.actual < expected;
1339
+ };
1340
+
1341
+ jasmine.Matchers.prototype.toBeGreaterThan = function(expected) {
1342
+ return this.actual > expected;
1343
+ };
1344
+
1345
+ /**
1346
+ * Matcher that checks that the expected exception was thrown by the actual.
1347
+ *
1348
+ * @param {String} expected
1349
+ */
1350
+ jasmine.Matchers.prototype.toThrow = function(expected) {
1351
+ var result = false;
1352
+ var exception;
1353
+ if (typeof this.actual != 'function') {
1354
+ throw new Error('Actual is not a function');
1355
+ }
1356
+ try {
1357
+ this.actual();
1358
+ } catch (e) {
1359
+ exception = e;
1360
+ }
1361
+ if (exception) {
1362
+ result = (expected === jasmine.undefined || this.env.equals_(exception.message || exception, expected.message || expected));
1363
+ }
1364
+
1365
+ this.message = function() {
1366
+ if (exception && (expected === jasmine.undefined || !this.env.equals_(exception.message || exception, expected.message || expected))) {
1367
+ return ["Expected function to throw", expected.message || expected, ", but it threw", exception.message || exception].join(' ');
1368
+ } else {
1369
+ return "Expected function to throw an exception.";
1370
+ }
1371
+ };
1372
+
1373
+ return result;
1374
+ };
1375
+
1376
+ jasmine.Matchers.Any = function(expectedClass) {
1377
+ this.expectedClass = expectedClass;
1378
+ };
1379
+
1380
+ jasmine.Matchers.Any.prototype.matches = function(other) {
1381
+ if (this.expectedClass == String) {
1382
+ return typeof other == 'string' || other instanceof String;
1383
+ }
1384
+
1385
+ if (this.expectedClass == Number) {
1386
+ return typeof other == 'number' || other instanceof Number;
1387
+ }
1388
+
1389
+ if (this.expectedClass == Function) {
1390
+ return typeof other == 'function' || other instanceof Function;
1391
+ }
1392
+
1393
+ if (this.expectedClass == Object) {
1394
+ return typeof other == 'object';
1395
+ }
1396
+
1397
+ return other instanceof this.expectedClass;
1398
+ };
1399
+
1400
+ jasmine.Matchers.Any.prototype.toString = function() {
1401
+ return '<jasmine.any(' + this.expectedClass + ')>';
1402
+ };
1403
+
1404
+ /**
1405
+ * @constructor
1406
+ */
1407
+ jasmine.MultiReporter = function() {
1408
+ this.subReporters_ = [];
1409
+ };
1410
+ jasmine.util.inherit(jasmine.MultiReporter, jasmine.Reporter);
1411
+
1412
+ jasmine.MultiReporter.prototype.addReporter = function(reporter) {
1413
+ this.subReporters_.push(reporter);
1414
+ };
1415
+
1416
+ (function() {
1417
+ var functionNames = [
1418
+ "reportRunnerStarting",
1419
+ "reportRunnerResults",
1420
+ "reportSuiteResults",
1421
+ "reportSpecStarting",
1422
+ "reportSpecResults",
1423
+ "log"
1424
+ ];
1425
+ for (var i = 0; i < functionNames.length; i++) {
1426
+ var functionName = functionNames[i];
1427
+ jasmine.MultiReporter.prototype[functionName] = (function(functionName) {
1428
+ return function() {
1429
+ for (var j = 0; j < this.subReporters_.length; j++) {
1430
+ var subReporter = this.subReporters_[j];
1431
+ if (subReporter[functionName]) {
1432
+ subReporter[functionName].apply(subReporter, arguments);
1433
+ }
1434
+ }
1435
+ };
1436
+ })(functionName);
1437
+ }
1438
+ })();
1439
+ /**
1440
+ * Holds results for a set of Jasmine spec. Allows for the results array to hold another jasmine.NestedResults
1441
+ *
1442
+ * @constructor
1443
+ */
1444
+ jasmine.NestedResults = function() {
1445
+ /**
1446
+ * The total count of results
1447
+ */
1448
+ this.totalCount = 0;
1449
+ /**
1450
+ * Number of passed results
1451
+ */
1452
+ this.passedCount = 0;
1453
+ /**
1454
+ * Number of failed results
1455
+ */
1456
+ this.failedCount = 0;
1457
+ /**
1458
+ * Was this suite/spec skipped?
1459
+ */
1460
+ this.skipped = false;
1461
+ /**
1462
+ * @ignore
1463
+ */
1464
+ this.items_ = [];
1465
+ };
1466
+
1467
+ /**
1468
+ * Roll up the result counts.
1469
+ *
1470
+ * @param result
1471
+ */
1472
+ jasmine.NestedResults.prototype.rollupCounts = function(result) {
1473
+ this.totalCount += result.totalCount;
1474
+ this.passedCount += result.passedCount;
1475
+ this.failedCount += result.failedCount;
1476
+ };
1477
+
1478
+ /**
1479
+ * Adds a log message.
1480
+ * @param values Array of message parts which will be concatenated later.
1481
+ */
1482
+ jasmine.NestedResults.prototype.log = function(values) {
1483
+ this.items_.push(new jasmine.MessageResult(values));
1484
+ };
1485
+
1486
+ /**
1487
+ * Getter for the results: message & results.
1488
+ */
1489
+ jasmine.NestedResults.prototype.getItems = function() {
1490
+ return this.items_;
1491
+ };
1492
+
1493
+ /**
1494
+ * Adds a result, tracking counts (total, passed, & failed)
1495
+ * @param {jasmine.ExpectationResult|jasmine.NestedResults} result
1496
+ */
1497
+ jasmine.NestedResults.prototype.addResult = function(result) {
1498
+ if (result.type != 'log') {
1499
+ if (result.items_) {
1500
+ this.rollupCounts(result);
1501
+ } else {
1502
+ this.totalCount++;
1503
+ if (result.passed()) {
1504
+ this.passedCount++;
1505
+ } else {
1506
+ this.failedCount++;
1507
+ }
1508
+ }
1509
+ }
1510
+ this.items_.push(result);
1511
+ };
1512
+
1513
+ /**
1514
+ * @returns {Boolean} True if <b>everything</b> below passed
1515
+ */
1516
+ jasmine.NestedResults.prototype.passed = function() {
1517
+ return this.passedCount === this.totalCount;
1518
+ };
1519
+ /**
1520
+ * Base class for pretty printing for expectation results.
1521
+ */
1522
+ jasmine.PrettyPrinter = function() {
1523
+ this.ppNestLevel_ = 0;
1524
+ };
1525
+
1526
+ /**
1527
+ * Formats a value in a nice, human-readable string.
1528
+ *
1529
+ * @param value
1530
+ */
1531
+ jasmine.PrettyPrinter.prototype.format = function(value) {
1532
+ if (this.ppNestLevel_ > 40) {
1533
+ throw new Error('jasmine.PrettyPrinter: format() nested too deeply!');
1534
+ }
1535
+
1536
+ this.ppNestLevel_++;
1537
+ try {
1538
+ if (value === jasmine.undefined) {
1539
+ this.emitScalar('undefined');
1540
+ } else if (value === null) {
1541
+ this.emitScalar('null');
1542
+ } else if (value === jasmine.getGlobal()) {
1543
+ this.emitScalar('<global>');
1544
+ } else if (value instanceof jasmine.Matchers.Any) {
1545
+ this.emitScalar(value.toString());
1546
+ } else if (typeof value === 'string') {
1547
+ this.emitString(value);
1548
+ } else if (jasmine.isSpy(value)) {
1549
+ this.emitScalar("spy on " + value.identity);
1550
+ } else if (value instanceof RegExp) {
1551
+ this.emitScalar(value.toString());
1552
+ } else if (typeof value === 'function') {
1553
+ this.emitScalar('Function');
1554
+ } else if (typeof value.nodeType === 'number') {
1555
+ this.emitScalar('HTMLNode');
1556
+ } else if (value instanceof Date) {
1557
+ this.emitScalar('Date(' + value + ')');
1558
+ } else if (value.__Jasmine_been_here_before__) {
1559
+ this.emitScalar('<circular reference: ' + (jasmine.isArray_(value) ? 'Array' : 'Object') + '>');
1560
+ } else if (jasmine.isArray_(value) || typeof value == 'object') {
1561
+ value.__Jasmine_been_here_before__ = true;
1562
+ if (jasmine.isArray_(value)) {
1563
+ this.emitArray(value);
1564
+ } else {
1565
+ this.emitObject(value);
1566
+ }
1567
+ delete value.__Jasmine_been_here_before__;
1568
+ } else {
1569
+ this.emitScalar(value.toString());
1570
+ }
1571
+ } finally {
1572
+ this.ppNestLevel_--;
1573
+ }
1574
+ };
1575
+
1576
+ jasmine.PrettyPrinter.prototype.iterateObject = function(obj, fn) {
1577
+ for (var property in obj) {
1578
+ if (property == '__Jasmine_been_here_before__') continue;
1579
+ fn(property, obj.__lookupGetter__ ? (obj.__lookupGetter__(property) != null) : false);
1580
+ }
1581
+ };
1582
+
1583
+ jasmine.PrettyPrinter.prototype.emitArray = jasmine.unimplementedMethod_;
1584
+ jasmine.PrettyPrinter.prototype.emitObject = jasmine.unimplementedMethod_;
1585
+ jasmine.PrettyPrinter.prototype.emitScalar = jasmine.unimplementedMethod_;
1586
+ jasmine.PrettyPrinter.prototype.emitString = jasmine.unimplementedMethod_;
1587
+
1588
+ jasmine.StringPrettyPrinter = function() {
1589
+ jasmine.PrettyPrinter.call(this);
1590
+
1591
+ this.string = '';
1592
+ };
1593
+ jasmine.util.inherit(jasmine.StringPrettyPrinter, jasmine.PrettyPrinter);
1594
+
1595
+ jasmine.StringPrettyPrinter.prototype.emitScalar = function(value) {
1596
+ this.append(value);
1597
+ };
1598
+
1599
+ jasmine.StringPrettyPrinter.prototype.emitString = function(value) {
1600
+ this.append("'" + value + "'");
1601
+ };
1602
+
1603
+ jasmine.StringPrettyPrinter.prototype.emitArray = function(array) {
1604
+ this.append('[ ');
1605
+ for (var i = 0; i < array.length; i++) {
1606
+ if (i > 0) {
1607
+ this.append(', ');
1608
+ }
1609
+ this.format(array[i]);
1610
+ }
1611
+ this.append(' ]');
1612
+ };
1613
+
1614
+ jasmine.StringPrettyPrinter.prototype.emitObject = function(obj) {
1615
+ var self = this;
1616
+ this.append('{ ');
1617
+ var first = true;
1618
+
1619
+ this.iterateObject(obj, function(property, isGetter) {
1620
+ if (first) {
1621
+ first = false;
1622
+ } else {
1623
+ self.append(', ');
1624
+ }
1625
+
1626
+ self.append(property);
1627
+ self.append(' : ');
1628
+ if (isGetter) {
1629
+ self.append('<getter>');
1630
+ } else {
1631
+ self.format(obj[property]);
1632
+ }
1633
+ });
1634
+
1635
+ this.append(' }');
1636
+ };
1637
+
1638
+ jasmine.StringPrettyPrinter.prototype.append = function(value) {
1639
+ this.string += value;
1640
+ };
1641
+ jasmine.Queue = function(env) {
1642
+ this.env = env;
1643
+ this.blocks = [];
1644
+ this.running = false;
1645
+ this.index = 0;
1646
+ this.offset = 0;
1647
+ };
1648
+
1649
+ jasmine.Queue.prototype.addBefore = function(block) {
1650
+ this.blocks.unshift(block);
1651
+ };
1652
+
1653
+ jasmine.Queue.prototype.add = function(block) {
1654
+ this.blocks.push(block);
1655
+ };
1656
+
1657
+ jasmine.Queue.prototype.insertNext = function(block) {
1658
+ this.blocks.splice((this.index + this.offset + 1), 0, block);
1659
+ this.offset++;
1660
+ };
1661
+
1662
+ jasmine.Queue.prototype.start = function(onComplete) {
1663
+ this.running = true;
1664
+ this.onComplete = onComplete;
1665
+ this.next_();
1666
+ };
1667
+
1668
+ jasmine.Queue.prototype.isRunning = function() {
1669
+ return this.running;
1670
+ };
1671
+
1672
+ jasmine.Queue.LOOP_DONT_RECURSE = true;
1673
+
1674
+ jasmine.Queue.prototype.next_ = function() {
1675
+ var self = this;
1676
+ var goAgain = true;
1677
+
1678
+ while (goAgain) {
1679
+ goAgain = false;
1680
+
1681
+ if (self.index < self.blocks.length) {
1682
+ var calledSynchronously = true;
1683
+ var completedSynchronously = false;
1684
+
1685
+ var onComplete = function () {
1686
+ if (jasmine.Queue.LOOP_DONT_RECURSE && calledSynchronously) {
1687
+ completedSynchronously = true;
1688
+ return;
1689
+ }
1690
+
1691
+ self.offset = 0;
1692
+ self.index++;
1693
+
1694
+ var now = new Date().getTime();
1695
+ if (self.env.updateInterval && now - self.env.lastUpdate > self.env.updateInterval) {
1696
+ self.env.lastUpdate = now;
1697
+ self.env.setTimeout(function() {
1698
+ self.next_();
1699
+ }, 0);
1700
+ } else {
1701
+ if (jasmine.Queue.LOOP_DONT_RECURSE && completedSynchronously) {
1702
+ goAgain = true;
1703
+ } else {
1704
+ self.next_();
1705
+ }
1706
+ }
1707
+ };
1708
+ self.blocks[self.index].execute(onComplete);
1709
+
1710
+ calledSynchronously = false;
1711
+ if (completedSynchronously) {
1712
+ onComplete();
1713
+ }
1714
+
1715
+ } else {
1716
+ self.running = false;
1717
+ if (self.onComplete) {
1718
+ self.onComplete();
1719
+ }
1720
+ }
1721
+ }
1722
+ };
1723
+
1724
+ jasmine.Queue.prototype.results = function() {
1725
+ var results = new jasmine.NestedResults();
1726
+ for (var i = 0; i < this.blocks.length; i++) {
1727
+ if (this.blocks[i].results) {
1728
+ results.addResult(this.blocks[i].results());
1729
+ }
1730
+ }
1731
+ return results;
1732
+ };
1733
+
1734
+
1735
+ /**
1736
+ * Runner
1737
+ *
1738
+ * @constructor
1739
+ * @param {jasmine.Env} env
1740
+ */
1741
+ jasmine.Runner = function(env) {
1742
+ var self = this;
1743
+ self.env = env;
1744
+ self.queue = new jasmine.Queue(env);
1745
+ self.before_ = [];
1746
+ self.after_ = [];
1747
+ self.suites_ = [];
1748
+ };
1749
+
1750
+ jasmine.Runner.prototype.execute = function() {
1751
+ var self = this;
1752
+ if (self.env.reporter.reportRunnerStarting) {
1753
+ self.env.reporter.reportRunnerStarting(this);
1754
+ }
1755
+ self.queue.start(function () {
1756
+ self.finishCallback();
1757
+ });
1758
+ };
1759
+
1760
+ jasmine.Runner.prototype.beforeEach = function(beforeEachFunction) {
1761
+ beforeEachFunction.typeName = 'beforeEach';
1762
+ this.before_.splice(0,0,beforeEachFunction);
1763
+ };
1764
+
1765
+ jasmine.Runner.prototype.afterEach = function(afterEachFunction) {
1766
+ afterEachFunction.typeName = 'afterEach';
1767
+ this.after_.splice(0,0,afterEachFunction);
1768
+ };
1769
+
1770
+
1771
+ jasmine.Runner.prototype.finishCallback = function() {
1772
+ this.env.reporter.reportRunnerResults(this);
1773
+ };
1774
+
1775
+ jasmine.Runner.prototype.addSuite = function(suite) {
1776
+ this.suites_.push(suite);
1777
+ };
1778
+
1779
+ jasmine.Runner.prototype.add = function(block) {
1780
+ if (block instanceof jasmine.Suite) {
1781
+ this.addSuite(block);
1782
+ }
1783
+ this.queue.add(block);
1784
+ };
1785
+
1786
+ jasmine.Runner.prototype.specs = function () {
1787
+ var suites = this.suites();
1788
+ var specs = [];
1789
+ for (var i = 0; i < suites.length; i++) {
1790
+ specs = specs.concat(suites[i].specs());
1791
+ }
1792
+ return specs;
1793
+ };
1794
+
1795
+ jasmine.Runner.prototype.suites = function() {
1796
+ return this.suites_;
1797
+ };
1798
+
1799
+ jasmine.Runner.prototype.topLevelSuites = function() {
1800
+ var topLevelSuites = [];
1801
+ for (var i = 0; i < this.suites_.length; i++) {
1802
+ if (!this.suites_[i].parentSuite) {
1803
+ topLevelSuites.push(this.suites_[i]);
1804
+ }
1805
+ }
1806
+ return topLevelSuites;
1807
+ };
1808
+
1809
+ jasmine.Runner.prototype.results = function() {
1810
+ return this.queue.results();
1811
+ };
1812
+ /**
1813
+ * Internal representation of a Jasmine specification, or test.
1814
+ *
1815
+ * @constructor
1816
+ * @param {jasmine.Env} env
1817
+ * @param {jasmine.Suite} suite
1818
+ * @param {String} description
1819
+ */
1820
+ jasmine.Spec = function(env, suite, description) {
1821
+ if (!env) {
1822
+ throw new Error('jasmine.Env() required');
1823
+ }
1824
+ if (!suite) {
1825
+ throw new Error('jasmine.Suite() required');
1826
+ }
1827
+ var spec = this;
1828
+ spec.id = env.nextSpecId ? env.nextSpecId() : null;
1829
+ spec.env = env;
1830
+ spec.suite = suite;
1831
+ spec.description = description;
1832
+ spec.queue = new jasmine.Queue(env);
1833
+
1834
+ spec.afterCallbacks = [];
1835
+ spec.spies_ = [];
1836
+
1837
+ spec.results_ = new jasmine.NestedResults();
1838
+ spec.results_.description = description;
1839
+ spec.matchersClass = null;
1840
+ };
1841
+
1842
+ jasmine.Spec.prototype.getFullName = function() {
1843
+ return this.suite.getFullName() + ' ' + this.description + '.';
1844
+ };
1845
+
1846
+
1847
+ jasmine.Spec.prototype.results = function() {
1848
+ return this.results_;
1849
+ };
1850
+
1851
+ /**
1852
+ * All parameters are pretty-printed and concatenated together, then written to the spec's output.
1853
+ *
1854
+ * Be careful not to leave calls to <code>jasmine.log</code> in production code.
1855
+ */
1856
+ jasmine.Spec.prototype.log = function() {
1857
+ return this.results_.log(arguments);
1858
+ };
1859
+
1860
+ jasmine.Spec.prototype.runs = function (func) {
1861
+ var block = new jasmine.Block(this.env, func, this);
1862
+ this.addToQueue(block);
1863
+ return this;
1864
+ };
1865
+
1866
+ jasmine.Spec.prototype.addToQueue = function (block) {
1867
+ if (this.queue.isRunning()) {
1868
+ this.queue.insertNext(block);
1869
+ } else {
1870
+ this.queue.add(block);
1871
+ }
1872
+ };
1873
+
1874
+ /**
1875
+ * @param {jasmine.ExpectationResult} result
1876
+ */
1877
+ jasmine.Spec.prototype.addMatcherResult = function(result) {
1878
+ this.results_.addResult(result);
1879
+ };
1880
+
1881
+ jasmine.Spec.prototype.expect = function(actual) {
1882
+ var positive = new (this.getMatchersClass_())(this.env, actual, this);
1883
+ positive.not = new (this.getMatchersClass_())(this.env, actual, this, true);
1884
+ return positive;
1885
+ };
1886
+
1887
+ jasmine.Spec.prototype.waits = function(timeout) {
1888
+ var waitsFunc = new jasmine.WaitsBlock(this.env, timeout, this);
1889
+ this.addToQueue(waitsFunc);
1890
+ return this;
1891
+ };
1892
+
1893
+ jasmine.Spec.prototype.waitsFor = function(timeout, latchFunction, timeoutMessage) {
1894
+ var waitsForFunc = new jasmine.WaitsForBlock(this.env, timeout, latchFunction, timeoutMessage, this);
1895
+ this.addToQueue(waitsForFunc);
1896
+ return this;
1897
+ };
1898
+
1899
+ jasmine.Spec.prototype.fail = function (e) {
1900
+ var expectationResult = new jasmine.ExpectationResult({
1901
+ passed: false,
1902
+ message: e ? jasmine.util.formatException(e) : 'Exception'
1903
+ });
1904
+ this.results_.addResult(expectationResult);
1905
+ };
1906
+
1907
+ jasmine.Spec.prototype.getMatchersClass_ = function() {
1908
+ return this.matchersClass || this.env.matchersClass;
1909
+ };
1910
+
1911
+ jasmine.Spec.prototype.addMatchers = function(matchersPrototype) {
1912
+ var parent = this.getMatchersClass_();
1913
+ var newMatchersClass = function() {
1914
+ parent.apply(this, arguments);
1915
+ };
1916
+ jasmine.util.inherit(newMatchersClass, parent);
1917
+ jasmine.Matchers.wrapInto_(matchersPrototype, newMatchersClass);
1918
+ this.matchersClass = newMatchersClass;
1919
+ };
1920
+
1921
+ jasmine.Spec.prototype.finishCallback = function() {
1922
+ this.env.reporter.reportSpecResults(this);
1923
+ };
1924
+
1925
+ jasmine.Spec.prototype.finish = function(onComplete) {
1926
+ this.removeAllSpies();
1927
+ this.finishCallback();
1928
+ if (onComplete) {
1929
+ onComplete();
1930
+ }
1931
+ };
1932
+
1933
+ jasmine.Spec.prototype.after = function(doAfter) {
1934
+ if (this.queue.isRunning()) {
1935
+ this.queue.add(new jasmine.Block(this.env, doAfter, this));
1936
+ } else {
1937
+ this.afterCallbacks.unshift(doAfter);
1938
+ }
1939
+ };
1940
+
1941
+ jasmine.Spec.prototype.execute = function(onComplete) {
1942
+ var spec = this;
1943
+ if (!spec.env.specFilter(spec)) {
1944
+ spec.results_.skipped = true;
1945
+ spec.finish(onComplete);
1946
+ return;
1947
+ }
1948
+
1949
+ this.env.reporter.reportSpecStarting(this);
1950
+
1951
+ spec.env.currentSpec = spec;
1952
+
1953
+ spec.addBeforesAndAftersToQueue();
1954
+
1955
+ spec.queue.start(function () {
1956
+ spec.finish(onComplete);
1957
+ });
1958
+ };
1959
+
1960
+ jasmine.Spec.prototype.addBeforesAndAftersToQueue = function() {
1961
+ var runner = this.env.currentRunner();
1962
+ var i;
1963
+
1964
+ for (var suite = this.suite; suite; suite = suite.parentSuite) {
1965
+ for (i = 0; i < suite.before_.length; i++) {
1966
+ this.queue.addBefore(new jasmine.Block(this.env, suite.before_[i], this));
1967
+ }
1968
+ }
1969
+ for (i = 0; i < runner.before_.length; i++) {
1970
+ this.queue.addBefore(new jasmine.Block(this.env, runner.before_[i], this));
1971
+ }
1972
+ for (i = 0; i < this.afterCallbacks.length; i++) {
1973
+ this.queue.add(new jasmine.Block(this.env, this.afterCallbacks[i], this));
1974
+ }
1975
+ for (suite = this.suite; suite; suite = suite.parentSuite) {
1976
+ for (i = 0; i < suite.after_.length; i++) {
1977
+ this.queue.add(new jasmine.Block(this.env, suite.after_[i], this));
1978
+ }
1979
+ }
1980
+ for (i = 0; i < runner.after_.length; i++) {
1981
+ this.queue.add(new jasmine.Block(this.env, runner.after_[i], this));
1982
+ }
1983
+ };
1984
+
1985
+ jasmine.Spec.prototype.explodes = function() {
1986
+ throw 'explodes function should not have been called';
1987
+ };
1988
+
1989
+ jasmine.Spec.prototype.spyOn = function(obj, methodName, ignoreMethodDoesntExist) {
1990
+ if (obj == jasmine.undefined) {
1991
+ throw "spyOn could not find an object to spy upon for " + methodName + "()";
1992
+ }
1993
+
1994
+ if (!ignoreMethodDoesntExist && obj[methodName] === jasmine.undefined) {
1995
+ throw methodName + '() method does not exist';
1996
+ }
1997
+
1998
+ if (!ignoreMethodDoesntExist && obj[methodName] && obj[methodName].isSpy) {
1999
+ throw new Error(methodName + ' has already been spied upon');
2000
+ }
2001
+
2002
+ var spyObj = jasmine.createSpy(methodName);
2003
+
2004
+ this.spies_.push(spyObj);
2005
+ spyObj.baseObj = obj;
2006
+ spyObj.methodName = methodName;
2007
+ spyObj.originalValue = obj[methodName];
2008
+
2009
+ obj[methodName] = spyObj;
2010
+
2011
+ return spyObj;
2012
+ };
2013
+
2014
+ jasmine.Spec.prototype.removeAllSpies = function() {
2015
+ for (var i = 0; i < this.spies_.length; i++) {
2016
+ var spy = this.spies_[i];
2017
+ spy.baseObj[spy.methodName] = spy.originalValue;
2018
+ }
2019
+ this.spies_ = [];
2020
+ };
2021
+
2022
+ /**
2023
+ * Internal representation of a Jasmine suite.
2024
+ *
2025
+ * @constructor
2026
+ * @param {jasmine.Env} env
2027
+ * @param {String} description
2028
+ * @param {Function} specDefinitions
2029
+ * @param {jasmine.Suite} parentSuite
2030
+ */
2031
+ jasmine.Suite = function(env, description, specDefinitions, parentSuite) {
2032
+ var self = this;
2033
+ self.id = env.nextSuiteId ? env.nextSuiteId() : null;
2034
+ self.description = description;
2035
+ self.queue = new jasmine.Queue(env);
2036
+ self.parentSuite = parentSuite;
2037
+ self.env = env;
2038
+ self.before_ = [];
2039
+ self.after_ = [];
2040
+ self.children_ = [];
2041
+ self.suites_ = [];
2042
+ self.specs_ = [];
2043
+ };
2044
+
2045
+ jasmine.Suite.prototype.getFullName = function() {
2046
+ var fullName = this.description;
2047
+ for (var parentSuite = this.parentSuite; parentSuite; parentSuite = parentSuite.parentSuite) {
2048
+ fullName = parentSuite.description + ' ' + fullName;
2049
+ }
2050
+ return fullName;
2051
+ };
2052
+
2053
+ jasmine.Suite.prototype.finish = function(onComplete) {
2054
+ this.env.reporter.reportSuiteResults(this);
2055
+ this.finished = true;
2056
+ if (typeof(onComplete) == 'function') {
2057
+ onComplete();
2058
+ }
2059
+ };
2060
+
2061
+ jasmine.Suite.prototype.beforeEach = function(beforeEachFunction) {
2062
+ beforeEachFunction.typeName = 'beforeEach';
2063
+ this.before_.unshift(beforeEachFunction);
2064
+ };
2065
+
2066
+ jasmine.Suite.prototype.afterEach = function(afterEachFunction) {
2067
+ afterEachFunction.typeName = 'afterEach';
2068
+ this.after_.unshift(afterEachFunction);
2069
+ };
2070
+
2071
+ jasmine.Suite.prototype.results = function() {
2072
+ return this.queue.results();
2073
+ };
2074
+
2075
+ jasmine.Suite.prototype.add = function(suiteOrSpec) {
2076
+ this.children_.push(suiteOrSpec);
2077
+ if (suiteOrSpec instanceof jasmine.Suite) {
2078
+ this.suites_.push(suiteOrSpec);
2079
+ this.env.currentRunner().addSuite(suiteOrSpec);
2080
+ } else {
2081
+ this.specs_.push(suiteOrSpec);
2082
+ }
2083
+ this.queue.add(suiteOrSpec);
2084
+ };
2085
+
2086
+ jasmine.Suite.prototype.specs = function() {
2087
+ return this.specs_;
2088
+ };
2089
+
2090
+ jasmine.Suite.prototype.suites = function() {
2091
+ return this.suites_;
2092
+ };
2093
+
2094
+ jasmine.Suite.prototype.children = function() {
2095
+ return this.children_;
2096
+ };
2097
+
2098
+ jasmine.Suite.prototype.execute = function(onComplete) {
2099
+ var self = this;
2100
+ this.queue.start(function () {
2101
+ self.finish(onComplete);
2102
+ });
2103
+ };
2104
+ jasmine.WaitsBlock = function(env, timeout, spec) {
2105
+ this.timeout = timeout;
2106
+ jasmine.Block.call(this, env, null, spec);
2107
+ };
2108
+
2109
+ jasmine.util.inherit(jasmine.WaitsBlock, jasmine.Block);
2110
+
2111
+ jasmine.WaitsBlock.prototype.execute = function (onComplete) {
2112
+ this.env.reporter.log('>> Jasmine waiting for ' + this.timeout + ' ms...');
2113
+ this.env.setTimeout(function () {
2114
+ onComplete();
2115
+ }, this.timeout);
2116
+ };
2117
+ jasmine.WaitsForBlock = function(env, timeout, latchFunction, message, spec) {
2118
+ this.timeout = timeout;
2119
+ this.latchFunction = latchFunction;
2120
+ this.message = message;
2121
+ this.totalTimeSpentWaitingForLatch = 0;
2122
+ jasmine.Block.call(this, env, null, spec);
2123
+ };
2124
+
2125
+ jasmine.util.inherit(jasmine.WaitsForBlock, jasmine.Block);
2126
+
2127
+ jasmine.WaitsForBlock.TIMEOUT_INCREMENT = 100;
2128
+
2129
+ jasmine.WaitsForBlock.prototype.execute = function (onComplete) {
2130
+ var self = this;
2131
+ self.env.reporter.log('>> Jasmine waiting for ' + (self.message || 'something to happen'));
2132
+ var latchFunctionResult;
2133
+ try {
2134
+ latchFunctionResult = self.latchFunction.apply(self.spec);
2135
+ } catch (e) {
2136
+ self.spec.fail(e);
2137
+ onComplete();
2138
+ return;
2139
+ }
2140
+
2141
+ if (latchFunctionResult) {
2142
+ onComplete();
2143
+ } else if (self.totalTimeSpentWaitingForLatch >= self.timeout) {
2144
+ var message = 'timed out after ' + self.timeout + ' msec waiting for ' + (self.message || 'something to happen');
2145
+ self.spec.fail({
2146
+ name: 'timeout',
2147
+ message: message
2148
+ });
2149
+ } else {
2150
+ self.totalTimeSpentWaitingForLatch += jasmine.WaitsForBlock.TIMEOUT_INCREMENT;
2151
+ self.env.setTimeout(function () { self.execute(onComplete); }, jasmine.WaitsForBlock.TIMEOUT_INCREMENT);
2152
+ }
2153
+ };
2154
+ // Mock setTimeout, clearTimeout
2155
+ // Contributed by Pivotal Computer Systems, www.pivotalsf.com
2156
+
2157
+ jasmine.FakeTimer = function() {
2158
+ this.reset();
2159
+
2160
+ var self = this;
2161
+ self.setTimeout = function(funcToCall, millis) {
2162
+ self.timeoutsMade++;
2163
+ self.scheduleFunction(self.timeoutsMade, funcToCall, millis, false);
2164
+ return self.timeoutsMade;
2165
+ };
2166
+
2167
+ self.setInterval = function(funcToCall, millis) {
2168
+ self.timeoutsMade++;
2169
+ self.scheduleFunction(self.timeoutsMade, funcToCall, millis, true);
2170
+ return self.timeoutsMade;
2171
+ };
2172
+
2173
+ self.clearTimeout = function(timeoutKey) {
2174
+ self.scheduledFunctions[timeoutKey] = jasmine.undefined;
2175
+ };
2176
+
2177
+ self.clearInterval = function(timeoutKey) {
2178
+ self.scheduledFunctions[timeoutKey] = jasmine.undefined;
2179
+ };
2180
+
2181
+ };
2182
+
2183
+ jasmine.FakeTimer.prototype.reset = function() {
2184
+ this.timeoutsMade = 0;
2185
+ this.scheduledFunctions = {};
2186
+ this.nowMillis = 0;
2187
+ };
2188
+
2189
+ jasmine.FakeTimer.prototype.tick = function(millis) {
2190
+ var oldMillis = this.nowMillis;
2191
+ var newMillis = oldMillis + millis;
2192
+ this.runFunctionsWithinRange(oldMillis, newMillis);
2193
+ this.nowMillis = newMillis;
2194
+ };
2195
+
2196
+ jasmine.FakeTimer.prototype.runFunctionsWithinRange = function(oldMillis, nowMillis) {
2197
+ var scheduledFunc;
2198
+ var funcsToRun = [];
2199
+ for (var timeoutKey in this.scheduledFunctions) {
2200
+ scheduledFunc = this.scheduledFunctions[timeoutKey];
2201
+ if (scheduledFunc != jasmine.undefined &&
2202
+ scheduledFunc.runAtMillis >= oldMillis &&
2203
+ scheduledFunc.runAtMillis <= nowMillis) {
2204
+ funcsToRun.push(scheduledFunc);
2205
+ this.scheduledFunctions[timeoutKey] = jasmine.undefined;
2206
+ }
2207
+ }
2208
+
2209
+ if (funcsToRun.length > 0) {
2210
+ funcsToRun.sort(function(a, b) {
2211
+ return a.runAtMillis - b.runAtMillis;
2212
+ });
2213
+ for (var i = 0; i < funcsToRun.length; ++i) {
2214
+ try {
2215
+ var funcToRun = funcsToRun[i];
2216
+ this.nowMillis = funcToRun.runAtMillis;
2217
+ funcToRun.funcToCall();
2218
+ if (funcToRun.recurring) {
2219
+ this.scheduleFunction(funcToRun.timeoutKey,
2220
+ funcToRun.funcToCall,
2221
+ funcToRun.millis,
2222
+ true);
2223
+ }
2224
+ } catch(e) {
2225
+ }
2226
+ }
2227
+ this.runFunctionsWithinRange(oldMillis, nowMillis);
2228
+ }
2229
+ };
2230
+
2231
+ jasmine.FakeTimer.prototype.scheduleFunction = function(timeoutKey, funcToCall, millis, recurring) {
2232
+ this.scheduledFunctions[timeoutKey] = {
2233
+ runAtMillis: this.nowMillis + millis,
2234
+ funcToCall: funcToCall,
2235
+ recurring: recurring,
2236
+ timeoutKey: timeoutKey,
2237
+ millis: millis
2238
+ };
2239
+ };
2240
+
2241
+ /**
2242
+ * @namespace
2243
+ */
2244
+ jasmine.Clock = {
2245
+ defaultFakeTimer: new jasmine.FakeTimer(),
2246
+
2247
+ reset: function() {
2248
+ jasmine.Clock.assertInstalled();
2249
+ jasmine.Clock.defaultFakeTimer.reset();
2250
+ },
2251
+
2252
+ tick: function(millis) {
2253
+ jasmine.Clock.assertInstalled();
2254
+ jasmine.Clock.defaultFakeTimer.tick(millis);
2255
+ },
2256
+
2257
+ runFunctionsWithinRange: function(oldMillis, nowMillis) {
2258
+ jasmine.Clock.defaultFakeTimer.runFunctionsWithinRange(oldMillis, nowMillis);
2259
+ },
2260
+
2261
+ scheduleFunction: function(timeoutKey, funcToCall, millis, recurring) {
2262
+ jasmine.Clock.defaultFakeTimer.scheduleFunction(timeoutKey, funcToCall, millis, recurring);
2263
+ },
2264
+
2265
+ useMock: function() {
2266
+ if (!jasmine.Clock.isInstalled()) {
2267
+ var spec = jasmine.getEnv().currentSpec;
2268
+ spec.after(jasmine.Clock.uninstallMock);
2269
+
2270
+ jasmine.Clock.installMock();
2271
+ }
2272
+ },
2273
+
2274
+ installMock: function() {
2275
+ jasmine.Clock.installed = jasmine.Clock.defaultFakeTimer;
2276
+ },
2277
+
2278
+ uninstallMock: function() {
2279
+ jasmine.Clock.assertInstalled();
2280
+ jasmine.Clock.installed = jasmine.Clock.real;
2281
+ },
2282
+
2283
+ real: {
2284
+ setTimeout: jasmine.getGlobal().setTimeout,
2285
+ clearTimeout: jasmine.getGlobal().clearTimeout,
2286
+ setInterval: jasmine.getGlobal().setInterval,
2287
+ clearInterval: jasmine.getGlobal().clearInterval
2288
+ },
2289
+
2290
+ assertInstalled: function() {
2291
+ if (!jasmine.Clock.isInstalled()) {
2292
+ throw new Error("Mock clock is not installed, use jasmine.Clock.useMock()");
2293
+ }
2294
+ },
2295
+
2296
+ isInstalled: function() {
2297
+ return jasmine.Clock.installed == jasmine.Clock.defaultFakeTimer;
2298
+ },
2299
+
2300
+ installed: null
2301
+ };
2302
+ jasmine.Clock.installed = jasmine.Clock.real;
2303
+
2304
+ //else for IE support
2305
+ jasmine.getGlobal().setTimeout = function(funcToCall, millis) {
2306
+ if (jasmine.Clock.installed.setTimeout.apply) {
2307
+ return jasmine.Clock.installed.setTimeout.apply(this, arguments);
2308
+ } else {
2309
+ return jasmine.Clock.installed.setTimeout(funcToCall, millis);
2310
+ }
2311
+ };
2312
+
2313
+ jasmine.getGlobal().setInterval = function(funcToCall, millis) {
2314
+ if (jasmine.Clock.installed.setInterval.apply) {
2315
+ return jasmine.Clock.installed.setInterval.apply(this, arguments);
2316
+ } else {
2317
+ return jasmine.Clock.installed.setInterval(funcToCall, millis);
2318
+ }
2319
+ };
2320
+
2321
+ jasmine.getGlobal().clearTimeout = function(timeoutKey) {
2322
+ if (jasmine.Clock.installed.clearTimeout.apply) {
2323
+ return jasmine.Clock.installed.clearTimeout.apply(this, arguments);
2324
+ } else {
2325
+ return jasmine.Clock.installed.clearTimeout(timeoutKey);
2326
+ }
2327
+ };
2328
+
2329
+ jasmine.getGlobal().clearInterval = function(timeoutKey) {
2330
+ if (jasmine.Clock.installed.clearTimeout.apply) {
2331
+ return jasmine.Clock.installed.clearInterval.apply(this, arguments);
2332
+ } else {
2333
+ return jasmine.Clock.installed.clearInterval(timeoutKey);
2334
+ }
2335
+ };
2336
+
2337
+
2338
+ jasmine.version_= {
2339
+ "major": 0,
2340
+ "minor": 11,
2341
+ "build": 1,
2342
+ "revision": 1277514571
2343
+ };