ichabod 0.0.1

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