jasmine-headless-webkit 0.0.1

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