Completed
Push — GildedRose/js ( a01e2a )
by
unknown
05:41 queued 03:38
created

lib/jasmine-1.1.0/jasmine.js   F

Complexity

Total Complexity 470
Complexity/F 1.93

Size

Lines of Code 2476
Function Count 243

Duplication

Duplicated Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 13
c 1
b 0
f 0
nc 0
dl 0
loc 2476
rs 2.4
wmc 470
mnd 14
bc 424
fnc 243
bpm 1.7448
cpm 1.9341
noi 67

204 Functions

Rating   Name   Duplication   Size   Complexity  
A jasmine.ExpectationResult 0 11 3
A jasmine.Queue.results 0 9 3
A jasmine.PrettyPrinter 0 3 1
A jasmine.Spec.explodes 0 3 1
A jasmine.getEnv 0 4 1
A jasmine.util.htmlEscape 0 6 2
A jasmine.NestedResults 0 22 1
A jasmine.WaitsBlock.execute 0 8 2
A jasmine.JsApiReporter.suites 0 3 1
A jasmine.getGlobal.setInterval 0 7 2
A jasmine.Spec.getMatchersClass_ 0 3 1
A jasmine.Suite.children 0 3 1
A jasmine.NestedResults.getItems 0 3 1
A jasmine.StringPrettyPrinter.append 0 3 1
A jasmine.Env.it 0 11 2
A jasmine.js ➔ describe 0 3 1
A jasmine.createSpy 0 23 2
A jasmine.Runner.add 0 6 2
A jasmine.any 0 3 1
A jasmine.Queue.insertNext 0 4 1
A jasmine.Clock.tick 0 4 1
A jasmine.Suite.add 0 10 2
A jasmine.JsApiReporter.reportRunnerStarting 0 8 2
A jasmine.Spec.addMatchers 0 9 1
A jasmine.Queue.isRunning 0 3 1
A jasmine.isNumber_ 0 3 1
A jasmine.NestedResults.rollupCounts 0 5 1
A jasmine.Spy.reset 0 7 1
A jasmine.Env.addEqualityTester 0 3 1
A jasmine.Reporter.reportSpecResults 0 2 1
A jasmine.Env.afterEach 0 8 2
A jasmine.Spec.removeAllSpies 0 7 2
A jasmine.Matchers.toBeTruthy 0 3 1
A jasmine.bindOriginal_ 0 11 2
A jasmine.js ➔ it 0 3 1
A jasmine.Queue.add 0 3 1
A jasmine.Reporter.reportRunnerResults 0 2 1
A jasmine.isA_ 0 3 1
A jasmine.Spy.andThrow 0 6 1
A jasmine.MultiReporter[functionName].constructor 0 10 1
A jasmine.JsApiReporter.results 0 3 1
A jasmine.js ➔ xdescribe 0 3 1
A jasmine.StringPrettyPrinter.emitObject 0 23 1
A jasmine.Spec.execute 0 18 2
A jasmine.Spec.finish 0 7 2
A jasmine.WaitsBlock 0 4 1
A jasmine.log 0 4 1
A jasmine.Clock.assertInstalled 0 5 2
D jasmine.FakeTimer.runFunctionsWithinRange 0 34 9
A jasmine.Spec.results 0 3 1
A jasmine.isDomNode 0 3 1
A jasmine.Reporter 0 2 1
A jasmine.Spec.finishCallback 0 3 1
A jasmine.Runner.afterEach 0 4 1
A jasmine.createSpyObj 0 10 4
A jasmine.Suite 0 13 2
B jasmine.JsApiReporter.summarizeResult_ 0 21 6
A jasmine.Env.nextSuiteId 0 3 1
A jasmine.Matchers.toNotBe 0 3 1
A jasmine.Suite.specs 0 3 1
A jasmine.Matchers.toNotContain 0 3 1
B jasmine.FakeTimer 0 25 1
A jasmine.Spec.addToQueue 0 7 2
A jasmine.Clock.useMock 0 8 2
A jasmine.Spec.waits 0 5 1
A jasmine.Env.beforeEach 0 7 2
A jasmine.MessageResult.toString 0 12 4
A jasmine.Matchers.Any.toString 0 3 1
A jasmine.Env.versionString 0 13 3
B jasmine.PrettyPrinter.iterateObject 0 7 5
A jasmine.Runner.results 0 3 1
A jasmine.getGlobal.setTimeout 0 7 2
A jasmine.Matchers.toNotMatch 0 3 1
D jasmine.util.formatException 0 26 9
C jasmine.Spec.spyOn 0 24 7
A jasmine.getGlobal 0 7 1
A jasmine.Env.xit 0 7 1
A jasmine.StringPrettyPrinter.emitArray 0 10 3
A jasmine.Matchers.toBeNull 0 3 1
A jasmine.StringPrettyPrinter 0 5 1
A jasmine.js ➔ xit 0 3 1
A jasmine.Spec.addMatcherResult 0 3 1
A jasmine.JsApiReporter.summarize_ 0 17 4
A jasmine.Env.execute 0 3 1
A jasmine.Reporter.reportSpecStarting 0 2 1
A jasmine.pp 0 5 1
A jasmine.Block 0 5 1
A jasmine.FakeTimer.scheduleFunction 0 9 1
A jasmine.Runner.addSuite 0 3 1
A jasmine.Clock.uninstallMock 0 4 1
A jasmine.Reporter.log 0 2 1
A jasmine.getGlobal.clearInterval 0 7 2
A jasmine.Env.currentRunner 0 3 1
A jasmine.Env.xdescribe 0 6 1
A jasmine.FakeTimer.reset 0 5 1
A jasmine.util.argsToArray 0 5 2
A jasmine.Runner 0 8 1
A jasmine.js ➔ waitsFor 0 3 1
B jasmine.Spec.waitsFor 0 24 5
A jasmine.Reporter.reportSuiteResults 0 2 1
D jasmine.Env.equals_ 0 47 20
A jasmine.Matchers.toNotEqual 0 3 1
A jasmine.Suite.finish 0 7 2
A jasmine.Matchers.toMatch 0 3 1
A jasmine.ExpectationResult.toString 0 3 1
A jasmine.js ➔ waits 0 3 1
A jasmine.Matchers.toBeCloseTo 0 9 2
A jasmine.Queue.start 0 5 1
B jasmine.Queue.next_ 0 53 6
B jasmine.Spy 0 36 1
A jasmine.Spy.andReturn 0 6 1
A jasmine.Matchers.toBeFalsy 0 3 1
B jasmine.Matchers.Any.matches 0 19 5
A jasmine.getGlobal.clearTimeout 0 7 2
A jasmine.Spec.expect 0 5 1
A jasmine.JsApiReporter.reportRunnerResults 0 3 1
A jasmine.js ➔ afterEach 0 3 1
A jasmine.Spy.andCallThrough 0 4 1
A jasmine.StringPrettyPrinter.emitString 0 3 1
A jasmine.Matchers.toHaveBeenCalledWith 0 22 2
A jasmine.NestedResults.passed 0 3 1
A jasmine.Spec.log 0 3 1
A jasmine.NestedResults.addResult 0 15 4
A jasmine.Matchers.toBeLessThan 0 3 1
A jasmine.Block.execute 0 8 2
A jasmine.Matchers.pp 0 3 1
B jasmine.WaitsForBlock.execute 0 32 5
C jasmine.Matchers.toThrow 0 27 5
A jasmine.Matchers.Any 0 3 1
A jasmine.Matchers.wrapInto_ 0 7 3
A jasmine.Clock.installMock 0 3 1
A jasmine.util.inherit 0 9 1
A jasmine.MessageResult 0 5 1
A jasmine.js ➔ beforeEach 0 3 1
A jasmine.FakeTimer.tick 0 6 1
A jasmine.Runner.execute 0 9 2
A jasmine.Matchers.wasNotCalledWith 0 15 2
A jasmine.js ➔ runs 0 3 1
A jasmine.JsApiReporter.reportSpecResults 0 6 2
A jasmine.Env.contains_ 0 9 4
B jasmine.Env 0 26 1
A jasmine.Matchers.report 0 3 1
A jasmine.MultiReporter 0 3 1
A jasmine.JsApiReporter.resultsForSpec 0 3 1
A 0 23 2
B jasmine.Env.describe 0 29 4
A jasmine.Spec 0 21 4
A jasmine.Suite.afterEach 0 4 1
A jasmine.MultiReporter.addReporter 0 3 1
B jasmine.Matchers.matcherFn_ 0 41 1
A jasmine.js ➔ spyOn 0 3 1
A jasmine.Matchers.toBeGreaterThan 0 3 1
A jasmine.JsApiReporter.resultsForSpecs 0 8 2
A jasmine.Reporter.reportRunnerStarting 0 2 1
A jasmine.isSpy 0 3 1
F jasmine.Env.compareObjects_ 0 37 17
A jasmine.Spec.after 0 7 2
A jasmine.Spec.runs 0 5 1
A jasmine.Suite.suites 0 3 1
A jasmine.Matchers.toEqual 0 3 1
A jasmine.Clock.isInstalled 0 3 1
A jasmine.JsApiReporter 0 6 1
A jasmine.Env.addReporter 0 3 1
A jasmine.Queue 0 8 1
A jasmine.Matchers.toContain 0 3 1
A jasmine.Runner.topLevelSuites 0 9 3
A jasmine.Spec.getFullName 0 3 1
A jasmine.Clock.scheduleFunction 0 3 1
A jasmine.isString_ 0 3 1
A jasmine.StringPrettyPrinter.emitScalar 0 3 1
A jasmine.Queue.addBefore 0 3 1
A jasmine.Env.version 0 7 2
A jasmine.WaitsForBlock 0 7 1
A jasmine.NestedResults.log 0 3 1
A jasmine.Matchers.toBe 0 3 1
A jasmine.Suite.results 0 3 1
A jasmine.MultiReporter[functionName] 0 8 3
B jasmine.js ➔ ??? 0 26 2
A jasmine.JsApiReporter.log 0 2 1
A jasmine.Matchers.toBeUndefined 0 3 1
A jasmine.Clock.runFunctionsWithinRange 0 3 1
A jasmine.Clock.reset 0 4 1
A jasmine.Suite.getFullName 0 7 2
C jasmine.Spec.addBeforesAndAftersToQueue 0 24 8
A jasmine.ExpectationResult.passed 0 3 1
D jasmine.PrettyPrinter.format 0 44 17
A jasmine.Runner.finishCallback 0 3 1
A jasmine.isArray_ 0 3 1
A jasmine.Matchers.wasNotCalled 0 18 3
A jasmine.unimplementedMethod_ 0 3 1
A jasmine.Runner.beforeEach 0 4 1
A jasmine.js ➔ expect 0 3 1
A jasmine.JsApiReporter.reportSuiteResults 0 2 1
A jasmine.Matchers.toHaveBeenCalled 0 18 3
A jasmine.Matchers 0 7 1
A jasmine.Matchers.toBeDefined 0 3 1
A jasmine.Runner.suites 0 3 1
A jasmine.Env.nextSpecId 0 3 1
A jasmine.Spec.fail 0 8 2
A jasmine.Spy.andCallFake 0 4 1
A jasmine.Suite.beforeEach 0 4 1
A jasmine.Runner.specs 0 8 2
A jasmine.util.extend 0 4 2
A jasmine.Suite.execute 0 6 1

How to fix   Complexity   

Complexity

Complex classes like lib/jasmine-1.1.0/jasmine.js often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

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;
0 ignored issues
show
Coding Style Best Practice introduced by
Curly braces around statements make for more readable code and help prevent bugs when you add further statements.

Consider adding curly braces around all statements when they are executed conditionally. This is optional if there is only one statement, but leaving them out can lead to unexpected behaviour if another statement is added later.

Consider:

if (a > 0)
    b = 42;

If you or someone else later decides to put another statement in, only the first statement will be executed.

if (a > 0)
    console.log("a > 0");
    b = 42;

In this case the statement b = 42 will always be executed, while the logging statement will be executed conditionally.

if (a > 0) {
    console.log("a > 0");
    b = 42;
}

ensures that the proper code will be executed conditionally no matter how many statements are added or removed.

Loading history...
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
 * Show diagnostic messages in the console if set to true
27
 *
28
 */
29
jasmine.VERBOSE = false;
30
31
/**
32
 * 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.
33
 *
34
 */
35
jasmine.DEFAULT_UPDATE_INTERVAL = 250;
36
37
/**
38
 * Default timeout interval in milliseconds for waitsFor() blocks.
39
 */
40
jasmine.DEFAULT_TIMEOUT_INTERVAL = 5000;
41
42
jasmine.getGlobal = function() {
43
  function getGlobal() {
44
    return this;
45
  }
46
47
  return getGlobal();
48
};
49
50
/**
51
 * Allows for bound functions to be compared.  Internal use only.
52
 *
53
 * @ignore
54
 * @private
55
 * @param base {Object} bound 'this' for the function
56
 * @param name {Function} function to find
57
 */
58
jasmine.bindOriginal_ = function(base, name) {
59
  var original = base[name];
60
  if (original.apply) {
61
    return function() {
62
      return original.apply(base, arguments);
63
    };
64
  } else {
65
    // IE support
66
    return jasmine.getGlobal()[name];
67
  }
68
};
69
70
jasmine.setTimeout = jasmine.bindOriginal_(jasmine.getGlobal(), 'setTimeout');
71
jasmine.clearTimeout = jasmine.bindOriginal_(jasmine.getGlobal(), 'clearTimeout');
72
jasmine.setInterval = jasmine.bindOriginal_(jasmine.getGlobal(), 'setInterval');
73
jasmine.clearInterval = jasmine.bindOriginal_(jasmine.getGlobal(), 'clearInterval');
74
75
jasmine.MessageResult = function(values) {
76
  this.type = 'log';
77
  this.values = values;
78
  this.trace = new Error(); // todo: test better
79
};
80
81
jasmine.MessageResult.prototype.toString = function() {
82
  var text = "";
83
  for (var i = 0; i < this.values.length; i++) {
84
    if (i > 0) text += " ";
0 ignored issues
show
Coding Style Best Practice introduced by
Curly braces around statements make for more readable code and help prevent bugs when you add further statements.

Consider adding curly braces around all statements when they are executed conditionally. This is optional if there is only one statement, but leaving them out can lead to unexpected behaviour if another statement is added later.

Consider:

if (a > 0)
    b = 42;

If you or someone else later decides to put another statement in, only the first statement will be executed.

if (a > 0)
    console.log("a > 0");
    b = 42;

In this case the statement b = 42 will always be executed, while the logging statement will be executed conditionally.

if (a > 0) {
    console.log("a > 0");
    b = 42;
}

ensures that the proper code will be executed conditionally no matter how many statements are added or removed.

Loading history...
85
    if (jasmine.isString_(this.values[i])) {
86
      text += this.values[i];
87
    } else {
88
      text += jasmine.pp(this.values[i]);
89
    }
90
  }
91
  return text;
92
};
93
94
jasmine.ExpectationResult = function(params) {
95
  this.type = 'expect';
96
  this.matcherName = params.matcherName;
97
  this.passed_ = params.passed;
98
  this.expected = params.expected;
99
  this.actual = params.actual;
100
  this.message = this.passed_ ? 'Passed.' : params.message;
101
102
  var trace = (params.trace || new Error(this.message));
103
  this.trace = this.passed_ ? '' : trace;
104
};
105
106
jasmine.ExpectationResult.prototype.toString = function () {
107
  return this.message;
108
};
109
110
jasmine.ExpectationResult.prototype.passed = function () {
111
  return this.passed_;
112
};
113
114
/**
115
 * Getter for the Jasmine environment. Ensures one gets created
116
 */
117
jasmine.getEnv = function() {
118
  var env = jasmine.currentEnv_ = jasmine.currentEnv_ || new jasmine.Env();
119
  return env;
120
};
121
122
/**
123
 * @ignore
124
 * @private
125
 * @param value
126
 * @returns {Boolean}
127
 */
128
jasmine.isArray_ = function(value) {
129
  return jasmine.isA_("Array", value);
130
};
131
132
/**
133
 * @ignore
134
 * @private
135
 * @param value
136
 * @returns {Boolean}
137
 */
138
jasmine.isString_ = function(value) {
139
  return jasmine.isA_("String", value);
140
};
141
142
/**
143
 * @ignore
144
 * @private
145
 * @param value
146
 * @returns {Boolean}
147
 */
148
jasmine.isNumber_ = function(value) {
149
  return jasmine.isA_("Number", value);
150
};
151
152
/**
153
 * @ignore
154
 * @private
155
 * @param {String} typeName
156
 * @param value
157
 * @returns {Boolean}
158
 */
159
jasmine.isA_ = function(typeName, value) {
160
  return Object.prototype.toString.apply(value) === '[object ' + typeName + ']';
161
};
162
163
/**
164
 * Pretty printer for expecations.  Takes any object and turns it into a human-readable string.
165
 *
166
 * @param value {Object} an object to be outputted
167
 * @returns {String}
168
 */
169
jasmine.pp = function(value) {
170
  var stringPrettyPrinter = new jasmine.StringPrettyPrinter();
171
  stringPrettyPrinter.format(value);
172
  return stringPrettyPrinter.string;
173
};
174
175
/**
176
 * Returns true if the object is a DOM Node.
177
 *
178
 * @param {Object} obj object to check
179
 * @returns {Boolean}
180
 */
181
jasmine.isDomNode = function(obj) {
182
  return obj.nodeType > 0;
183
};
184
185
/**
186
 * Returns a matchable 'generic' object of the class type.  For use in expecations of type when values don't matter.
187
 *
188
 * @example
189
 * // don't care about which function is passed in, as long as it's a function
190
 * expect(mySpy).toHaveBeenCalledWith(jasmine.any(Function));
191
 *
192
 * @param {Class} clazz
193
 * @returns matchable object of the type clazz
194
 */
195
jasmine.any = function(clazz) {
196
  return new jasmine.Matchers.Any(clazz);
197
};
198
199
/**
200
 * Jasmine Spies are test doubles that can act as stubs, spies, fakes or when used in an expecation, mocks.
201
 *
202
 * Spies should be created in test setup, before expectations.  They can then be checked, using the standard Jasmine
203
 * expectation syntax. Spies can be checked if they were called or not and what the calling params were.
204
 *
205
 * A Spy has the following fields: wasCalled, callCount, mostRecentCall, and argsForCall (see docs).
206
 *
207
 * Spies are torn down at the end of every spec.
208
 *
209
 * Note: Do <b>not</b> call new jasmine.Spy() directly - a spy must be created using spyOn, jasmine.createSpy or jasmine.createSpyObj.
210
 *
211
 * @example
212
 * // a stub
213
 * var myStub = jasmine.createSpy('myStub');  // can be used anywhere
214
 *
215
 * // spy example
216
 * var foo = {
217
 *   not: function(bool) { return !bool; }
218
 * }
219
 *
220
 * // actual foo.not will not be called, execution stops
221
 * spyOn(foo, 'not');
222
223
 // foo.not spied upon, execution will continue to implementation
224
 * spyOn(foo, 'not').andCallThrough();
225
 *
226
 * // fake example
227
 * var foo = {
228
 *   not: function(bool) { return !bool; }
229
 * }
230
 *
231
 * // foo.not(val) will return val
232
 * spyOn(foo, 'not').andCallFake(function(value) {return value;});
233
 *
234
 * // mock example
235
 * foo.not(7 == 7);
236
 * expect(foo.not).toHaveBeenCalled();
237
 * expect(foo.not).toHaveBeenCalledWith(true);
238
 *
239
 * @constructor
240
 * @see spyOn, jasmine.createSpy, jasmine.createSpyObj
241
 * @param {String} name
242
 */
243
jasmine.Spy = function(name) {
244
  /**
245
   * The name of the spy, if provided.
246
   */
247
  this.identity = name || 'unknown';
248
  /**
249
   *  Is this Object a spy?
250
   */
251
  this.isSpy = true;
252
  /**
253
   * The actual function this spy stubs.
254
   */
255
  this.plan = function() {
256
  };
257
  /**
258
   * Tracking of the most recent call to the spy.
259
   * @example
260
   * var mySpy = jasmine.createSpy('foo');
261
   * mySpy(1, 2);
262
   * mySpy.mostRecentCall.args = [1, 2];
263
   */
264
  this.mostRecentCall = {};
265
266
  /**
267
   * Holds arguments for each call to the spy, indexed by call count
268
   * @example
269
   * var mySpy = jasmine.createSpy('foo');
270
   * mySpy(1, 2);
271
   * mySpy(7, 8);
272
   * mySpy.mostRecentCall.args = [7, 8];
273
   * mySpy.argsForCall[0] = [1, 2];
274
   * mySpy.argsForCall[1] = [7, 8];
275
   */
276
  this.argsForCall = [];
277
  this.calls = [];
278
};
279
280
/**
281
 * Tells a spy to call through to the actual implemenatation.
282
 *
283
 * @example
284
 * var foo = {
285
 *   bar: function() { // do some stuff }
286
 * }
287
 *
288
 * // defining a spy on an existing property: foo.bar
289
 * spyOn(foo, 'bar').andCallThrough();
290
 */
291
jasmine.Spy.prototype.andCallThrough = function() {
292
  this.plan = this.originalValue;
293
  return this;
294
};
295
296
/**
297
 * For setting the return value of a spy.
298
 *
299
 * @example
300
 * // defining a spy from scratch: foo() returns 'baz'
301
 * var foo = jasmine.createSpy('spy on foo').andReturn('baz');
302
 *
303
 * // defining a spy on an existing property: foo.bar() returns 'baz'
304
 * spyOn(foo, 'bar').andReturn('baz');
305
 *
306
 * @param {Object} value
307
 */
308
jasmine.Spy.prototype.andReturn = function(value) {
309
  this.plan = function() {
310
    return value;
311
  };
312
  return this;
313
};
314
315
/**
316
 * For throwing an exception when a spy is called.
317
 *
318
 * @example
319
 * // defining a spy from scratch: foo() throws an exception w/ message 'ouch'
320
 * var foo = jasmine.createSpy('spy on foo').andThrow('baz');
321
 *
322
 * // defining a spy on an existing property: foo.bar() throws an exception w/ message 'ouch'
323
 * spyOn(foo, 'bar').andThrow('baz');
324
 *
325
 * @param {String} exceptionMsg
326
 */
327
jasmine.Spy.prototype.andThrow = function(exceptionMsg) {
328
  this.plan = function() {
329
    throw exceptionMsg;
330
  };
331
  return this;
332
};
333
334
/**
335
 * Calls an alternate implementation when a spy is called.
336
 *
337
 * @example
338
 * var baz = function() {
339
 *   // do some stuff, return something
340
 * }
341
 * // defining a spy from scratch: foo() calls the function baz
342
 * var foo = jasmine.createSpy('spy on foo').andCall(baz);
343
 *
344
 * // defining a spy on an existing property: foo.bar() calls an anonymnous function
345
 * spyOn(foo, 'bar').andCall(function() { return 'baz';} );
346
 *
347
 * @param {Function} fakeFunc
348
 */
349
jasmine.Spy.prototype.andCallFake = function(fakeFunc) {
350
  this.plan = fakeFunc;
351
  return this;
352
};
353
354
/**
355
 * Resets all of a spy's the tracking variables so that it can be used again.
356
 *
357
 * @example
358
 * spyOn(foo, 'bar');
359
 *
360
 * foo.bar();
361
 *
362
 * expect(foo.bar.callCount).toEqual(1);
363
 *
364
 * foo.bar.reset();
365
 *
366
 * expect(foo.bar.callCount).toEqual(0);
367
 */
368
jasmine.Spy.prototype.reset = function() {
369
  this.wasCalled = false;
370
  this.callCount = 0;
371
  this.argsForCall = [];
372
  this.calls = [];
373
  this.mostRecentCall = {};
374
};
375
376
jasmine.createSpy = function(name) {
377
378
  var spyObj = function() {
379
    spyObj.wasCalled = true;
380
    spyObj.callCount++;
381
    var args = jasmine.util.argsToArray(arguments);
382
    spyObj.mostRecentCall.object = this;
383
    spyObj.mostRecentCall.args = args;
384
    spyObj.argsForCall.push(args);
385
    spyObj.calls.push({object: this, args: args});
386
    return spyObj.plan.apply(this, arguments);
387
  };
388
389
  var spy = new jasmine.Spy(name);
390
391
  for (var prop in spy) {
0 ignored issues
show
Complexity introduced by
A for in loop automatically includes the property of any prototype object, consider checking the key using hasOwnProperty.

When iterating over the keys of an object, this includes not only the keys of the object, but also keys contained in the prototype of that object. It is generally a best practice to check for these keys specifically:

var someObject;
for (var key in someObject) {
    if ( ! someObject.hasOwnProperty(key)) {
        continue; // Skip keys from the prototype.
    }

    doSomethingWith(key);
}
Loading history...
392
    spyObj[prop] = spy[prop];
393
  }
394
395
  spyObj.reset();
396
397
  return spyObj;
398
};
399
400
/**
401
 * Determines whether an object is a spy.
402
 *
403
 * @param {jasmine.Spy|Object} putativeSpy
404
 * @returns {Boolean}
405
 */
406
jasmine.isSpy = function(putativeSpy) {
407
  return putativeSpy && putativeSpy.isSpy;
408
};
409
410
/**
411
 * Creates a more complicated spy: an Object that has every property a function that is a spy.  Used for stubbing something
412
 * large in one call.
413
 *
414
 * @param {String} baseName name of spy class
415
 * @param {Array} methodNames array of names of methods to make spies
416
 */
417
jasmine.createSpyObj = function(baseName, methodNames) {
418
  if (!jasmine.isArray_(methodNames) || methodNames.length === 0) {
419
    throw new Error('createSpyObj requires a non-empty array of method names to create spies for');
420
  }
421
  var obj = {};
422
  for (var i = 0; i < methodNames.length; i++) {
423
    obj[methodNames[i]] = jasmine.createSpy(baseName + '.' + methodNames[i]);
424
  }
425
  return obj;
426
};
427
428
/**
429
 * All parameters are pretty-printed and concatenated together, then written to the current spec's output.
430
 *
431
 * Be careful not to leave calls to <code>jasmine.log</code> in production code.
432
 */
433
jasmine.log = function() {
434
  var spec = jasmine.getEnv().currentSpec;
435
  spec.log.apply(spec, arguments);
436
};
437
438
/**
439
 * Function that installs a spy on an existing object's method name.  Used within a Spec to create a spy.
440
 *
441
 * @example
442
 * // spy example
443
 * var foo = {
444
 *   not: function(bool) { return !bool; }
445
 * }
446
 * spyOn(foo, 'not'); // actual foo.not will not be called, execution stops
447
 *
448
 * @see jasmine.createSpy
449
 * @param obj
450
 * @param methodName
451
 * @returns a Jasmine spy that can be chained with all spy methods
452
 */
453
var spyOn = function(obj, methodName) {
454
  return jasmine.getEnv().currentSpec.spyOn(obj, methodName);
455
};
456
if (isCommonJS) exports.spyOn = spyOn;
0 ignored issues
show
Coding Style Best Practice introduced by
Curly braces around statements make for more readable code and help prevent bugs when you add further statements.

Consider adding curly braces around all statements when they are executed conditionally. This is optional if there is only one statement, but leaving them out can lead to unexpected behaviour if another statement is added later.

Consider:

if (a > 0)
    b = 42;

If you or someone else later decides to put another statement in, only the first statement will be executed.

if (a > 0)
    console.log("a > 0");
    b = 42;

In this case the statement b = 42 will always be executed, while the logging statement will be executed conditionally.

if (a > 0) {
    console.log("a > 0");
    b = 42;
}

ensures that the proper code will be executed conditionally no matter how many statements are added or removed.

Loading history...
457
458
/**
459
 * Creates a Jasmine spec that will be added to the current suite.
460
 *
461
 * // TODO: pending tests
462
 *
463
 * @example
464
 * it('should be true', function() {
465
 *   expect(true).toEqual(true);
466
 * });
467
 *
468
 * @param {String} desc description of this specification
469
 * @param {Function} func defines the preconditions and expectations of the spec
470
 */
471
var it = function(desc, func) {
472
  return jasmine.getEnv().it(desc, func);
473
};
474
if (isCommonJS) exports.it = it;
0 ignored issues
show
Coding Style Best Practice introduced by
Curly braces around statements make for more readable code and help prevent bugs when you add further statements.

Consider adding curly braces around all statements when they are executed conditionally. This is optional if there is only one statement, but leaving them out can lead to unexpected behaviour if another statement is added later.

Consider:

if (a > 0)
    b = 42;

If you or someone else later decides to put another statement in, only the first statement will be executed.

if (a > 0)
    console.log("a > 0");
    b = 42;

In this case the statement b = 42 will always be executed, while the logging statement will be executed conditionally.

if (a > 0) {
    console.log("a > 0");
    b = 42;
}

ensures that the proper code will be executed conditionally no matter how many statements are added or removed.

Loading history...
475
476
/**
477
 * Creates a <em>disabled</em> Jasmine spec.
478
 *
479
 * A convenience method that allows existing specs to be disabled temporarily during development.
480
 *
481
 * @param {String} desc description of this specification
482
 * @param {Function} func defines the preconditions and expectations of the spec
483
 */
484
var xit = function(desc, func) {
485
  return jasmine.getEnv().xit(desc, func);
486
};
487
if (isCommonJS) exports.xit = xit;
0 ignored issues
show
Coding Style Best Practice introduced by
Curly braces around statements make for more readable code and help prevent bugs when you add further statements.

Consider adding curly braces around all statements when they are executed conditionally. This is optional if there is only one statement, but leaving them out can lead to unexpected behaviour if another statement is added later.

Consider:

if (a > 0)
    b = 42;

If you or someone else later decides to put another statement in, only the first statement will be executed.

if (a > 0)
    console.log("a > 0");
    b = 42;

In this case the statement b = 42 will always be executed, while the logging statement will be executed conditionally.

if (a > 0) {
    console.log("a > 0");
    b = 42;
}

ensures that the proper code will be executed conditionally no matter how many statements are added or removed.

Loading history...
488
489
/**
490
 * Starts a chain for a Jasmine expectation.
491
 *
492
 * It is passed an Object that is the actual value and should chain to one of the many
493
 * jasmine.Matchers functions.
494
 *
495
 * @param {Object} actual Actual value to test against and expected value
496
 */
497
var expect = function(actual) {
498
  return jasmine.getEnv().currentSpec.expect(actual);
499
};
500
if (isCommonJS) exports.expect = expect;
0 ignored issues
show
Coding Style Best Practice introduced by
Curly braces around statements make for more readable code and help prevent bugs when you add further statements.

Consider adding curly braces around all statements when they are executed conditionally. This is optional if there is only one statement, but leaving them out can lead to unexpected behaviour if another statement is added later.

Consider:

if (a > 0)
    b = 42;

If you or someone else later decides to put another statement in, only the first statement will be executed.

if (a > 0)
    console.log("a > 0");
    b = 42;

In this case the statement b = 42 will always be executed, while the logging statement will be executed conditionally.

if (a > 0) {
    console.log("a > 0");
    b = 42;
}

ensures that the proper code will be executed conditionally no matter how many statements are added or removed.

Loading history...
501
502
/**
503
 * Defines part of a jasmine spec.  Used in cominbination with waits or waitsFor in asynchrnous specs.
504
 *
505
 * @param {Function} func Function that defines part of a jasmine spec.
506
 */
507
var runs = function(func) {
508
  jasmine.getEnv().currentSpec.runs(func);
509
};
510
if (isCommonJS) exports.runs = runs;
0 ignored issues
show
Coding Style Best Practice introduced by
Curly braces around statements make for more readable code and help prevent bugs when you add further statements.

Consider adding curly braces around all statements when they are executed conditionally. This is optional if there is only one statement, but leaving them out can lead to unexpected behaviour if another statement is added later.

Consider:

if (a > 0)
    b = 42;

If you or someone else later decides to put another statement in, only the first statement will be executed.

if (a > 0)
    console.log("a > 0");
    b = 42;

In this case the statement b = 42 will always be executed, while the logging statement will be executed conditionally.

if (a > 0) {
    console.log("a > 0");
    b = 42;
}

ensures that the proper code will be executed conditionally no matter how many statements are added or removed.

Loading history...
511
512
/**
513
 * Waits a fixed time period before moving to the next block.
514
 *
515
 * @deprecated Use waitsFor() instead
516
 * @param {Number} timeout milliseconds to wait
517
 */
518
var waits = function(timeout) {
519
  jasmine.getEnv().currentSpec.waits(timeout);
520
};
521
if (isCommonJS) exports.waits = waits;
0 ignored issues
show
Coding Style Best Practice introduced by
Curly braces around statements make for more readable code and help prevent bugs when you add further statements.

Consider adding curly braces around all statements when they are executed conditionally. This is optional if there is only one statement, but leaving them out can lead to unexpected behaviour if another statement is added later.

Consider:

if (a > 0)
    b = 42;

If you or someone else later decides to put another statement in, only the first statement will be executed.

if (a > 0)
    console.log("a > 0");
    b = 42;

In this case the statement b = 42 will always be executed, while the logging statement will be executed conditionally.

if (a > 0) {
    console.log("a > 0");
    b = 42;
}

ensures that the proper code will be executed conditionally no matter how many statements are added or removed.

Loading history...
522
523
/**
524
 * Waits for the latchFunction to return true before proceeding to the next block.
525
 *
526
 * @param {Function} latchFunction
527
 * @param {String} optional_timeoutMessage
528
 * @param {Number} optional_timeout
529
 */
530
var waitsFor = function(latchFunction, optional_timeoutMessage, optional_timeout) {
0 ignored issues
show
Unused Code introduced by
The parameter optional_timeout is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
Unused Code introduced by
The parameter optional_timeoutMessage is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
Unused Code introduced by
The parameter latchFunction is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
531
  jasmine.getEnv().currentSpec.waitsFor.apply(jasmine.getEnv().currentSpec, arguments);
532
};
533
if (isCommonJS) exports.waitsFor = waitsFor;
0 ignored issues
show
Coding Style Best Practice introduced by
Curly braces around statements make for more readable code and help prevent bugs when you add further statements.

Consider adding curly braces around all statements when they are executed conditionally. This is optional if there is only one statement, but leaving them out can lead to unexpected behaviour if another statement is added later.

Consider:

if (a > 0)
    b = 42;

If you or someone else later decides to put another statement in, only the first statement will be executed.

if (a > 0)
    console.log("a > 0");
    b = 42;

In this case the statement b = 42 will always be executed, while the logging statement will be executed conditionally.

if (a > 0) {
    console.log("a > 0");
    b = 42;
}

ensures that the proper code will be executed conditionally no matter how many statements are added or removed.

Loading history...
534
535
/**
536
 * A function that is called before each spec in a suite.
537
 *
538
 * Used for spec setup, including validating assumptions.
539
 *
540
 * @param {Function} beforeEachFunction
541
 */
542
var beforeEach = function(beforeEachFunction) {
543
  jasmine.getEnv().beforeEach(beforeEachFunction);
544
};
545
if (isCommonJS) exports.beforeEach = beforeEach;
0 ignored issues
show
Coding Style Best Practice introduced by
Curly braces around statements make for more readable code and help prevent bugs when you add further statements.

Consider adding curly braces around all statements when they are executed conditionally. This is optional if there is only one statement, but leaving them out can lead to unexpected behaviour if another statement is added later.

Consider:

if (a > 0)
    b = 42;

If you or someone else later decides to put another statement in, only the first statement will be executed.

if (a > 0)
    console.log("a > 0");
    b = 42;

In this case the statement b = 42 will always be executed, while the logging statement will be executed conditionally.

if (a > 0) {
    console.log("a > 0");
    b = 42;
}

ensures that the proper code will be executed conditionally no matter how many statements are added or removed.

Loading history...
546
547
/**
548
 * A function that is called after each spec in a suite.
549
 *
550
 * Used for restoring any state that is hijacked during spec execution.
551
 *
552
 * @param {Function} afterEachFunction
553
 */
554
var afterEach = function(afterEachFunction) {
555
  jasmine.getEnv().afterEach(afterEachFunction);
556
};
557
if (isCommonJS) exports.afterEach = afterEach;
0 ignored issues
show
Coding Style Best Practice introduced by
Curly braces around statements make for more readable code and help prevent bugs when you add further statements.

Consider adding curly braces around all statements when they are executed conditionally. This is optional if there is only one statement, but leaving them out can lead to unexpected behaviour if another statement is added later.

Consider:

if (a > 0)
    b = 42;

If you or someone else later decides to put another statement in, only the first statement will be executed.

if (a > 0)
    console.log("a > 0");
    b = 42;

In this case the statement b = 42 will always be executed, while the logging statement will be executed conditionally.

if (a > 0) {
    console.log("a > 0");
    b = 42;
}

ensures that the proper code will be executed conditionally no matter how many statements are added or removed.

Loading history...
558
559
/**
560
 * Defines a suite of specifications.
561
 *
562
 * Stores the description and all defined specs in the Jasmine environment as one suite of specs. Variables declared
563
 * are accessible by calls to beforeEach, it, and afterEach. Describe blocks can be nested, allowing for specialization
564
 * of setup in some tests.
565
 *
566
 * @example
567
 * // TODO: a simple suite
568
 *
569
 * // TODO: a simple suite with a nested describe block
570
 *
571
 * @param {String} description A string, usually the class under test.
572
 * @param {Function} specDefinitions function that defines several specs.
573
 */
574
var describe = function(description, specDefinitions) {
575
  return jasmine.getEnv().describe(description, specDefinitions);
576
};
577
if (isCommonJS) exports.describe = describe;
0 ignored issues
show
Coding Style Best Practice introduced by
Curly braces around statements make for more readable code and help prevent bugs when you add further statements.

Consider adding curly braces around all statements when they are executed conditionally. This is optional if there is only one statement, but leaving them out can lead to unexpected behaviour if another statement is added later.

Consider:

if (a > 0)
    b = 42;

If you or someone else later decides to put another statement in, only the first statement will be executed.

if (a > 0)
    console.log("a > 0");
    b = 42;

In this case the statement b = 42 will always be executed, while the logging statement will be executed conditionally.

if (a > 0) {
    console.log("a > 0");
    b = 42;
}

ensures that the proper code will be executed conditionally no matter how many statements are added or removed.

Loading history...
578
579
/**
580
 * Disables a suite of specifications.  Used to disable some suites in a file, or files, temporarily during development.
581
 *
582
 * @param {String} description A string, usually the class under test.
583
 * @param {Function} specDefinitions function that defines several specs.
584
 */
585
var xdescribe = function(description, specDefinitions) {
586
  return jasmine.getEnv().xdescribe(description, specDefinitions);
587
};
588
if (isCommonJS) exports.xdescribe = xdescribe;
0 ignored issues
show
Coding Style Best Practice introduced by
Curly braces around statements make for more readable code and help prevent bugs when you add further statements.

Consider adding curly braces around all statements when they are executed conditionally. This is optional if there is only one statement, but leaving them out can lead to unexpected behaviour if another statement is added later.

Consider:

if (a > 0)
    b = 42;

If you or someone else later decides to put another statement in, only the first statement will be executed.

if (a > 0)
    console.log("a > 0");
    b = 42;

In this case the statement b = 42 will always be executed, while the logging statement will be executed conditionally.

if (a > 0) {
    console.log("a > 0");
    b = 42;
}

ensures that the proper code will be executed conditionally no matter how many statements are added or removed.

Loading history...
589
590
591
// Provide the XMLHttpRequest class for IE 5.x-6.x:
592
jasmine.XmlHttpRequest = (typeof XMLHttpRequest == "undefined") ? function() {
0 ignored issues
show
Bug introduced by
The variable XMLHttpRequest seems to be never declared. If this is a global, consider adding a /** global: XMLHttpRequest */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
593
  function tryIt(f) {
594
    try {
595
      return f();
596
    } catch(e) {
0 ignored issues
show
Coding Style Comprehensibility Best Practice introduced by
Empty catch clauses should be used with caution; consider adding a comment why this is needed.
Loading history...
597
    }
598
    return null;
599
  }
600
601
  var xhr = tryIt(function() {
602
    return new ActiveXObject("Msxml2.XMLHTTP.6.0");
0 ignored issues
show
Bug introduced by
The variable ActiveXObject seems to be never declared. If this is a global, consider adding a /** global: ActiveXObject */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
603
  }) ||
604
    tryIt(function() {
605
      return new ActiveXObject("Msxml2.XMLHTTP.3.0");
0 ignored issues
show
Bug introduced by
The variable ActiveXObject seems to be never declared. If this is a global, consider adding a /** global: ActiveXObject */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
606
    }) ||
607
    tryIt(function() {
608
      return new ActiveXObject("Msxml2.XMLHTTP");
0 ignored issues
show
Bug introduced by
The variable ActiveXObject seems to be never declared. If this is a global, consider adding a /** global: ActiveXObject */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
609
    }) ||
610
    tryIt(function() {
611
      return new ActiveXObject("Microsoft.XMLHTTP");
0 ignored issues
show
Bug introduced by
The variable ActiveXObject seems to be never declared. If this is a global, consider adding a /** global: ActiveXObject */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
612
    });
613
614
  if (!xhr) throw new Error("This browser does not support XMLHttpRequest.");
0 ignored issues
show
Coding Style Best Practice introduced by
Curly braces around statements make for more readable code and help prevent bugs when you add further statements.

Consider adding curly braces around all statements when they are executed conditionally. This is optional if there is only one statement, but leaving them out can lead to unexpected behaviour if another statement is added later.

Consider:

if (a > 0)
    b = 42;

If you or someone else later decides to put another statement in, only the first statement will be executed.

if (a > 0)
    console.log("a > 0");
    b = 42;

In this case the statement b = 42 will always be executed, while the logging statement will be executed conditionally.

if (a > 0) {
    console.log("a > 0");
    b = 42;
}

ensures that the proper code will be executed conditionally no matter how many statements are added or removed.

Loading history...
615
616
  return xhr;
617
} : XMLHttpRequest;
0 ignored issues
show
Bug introduced by
The variable XMLHttpRequest seems to be never declared. If this is a global, consider adding a /** global: XMLHttpRequest */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
618
/**
619
 * @namespace
620
 */
621
jasmine.util = {};
622
623
/**
624
 * Declare that a child class inherit it's prototype from the parent class.
625
 *
626
 * @private
627
 * @param {Function} childClass
628
 * @param {Function} parentClass
629
 */
630
jasmine.util.inherit = function(childClass, parentClass) {
631
  /**
632
   * @private
633
   */
634
  var subclass = function() {
635
  };
636
  subclass.prototype = parentClass.prototype;
637
  childClass.prototype = new subclass();
0 ignored issues
show
Coding Style Best Practice introduced by
By convention, constructors like subclass should be capitalized.
Loading history...
638
};
639
640
jasmine.util.formatException = function(e) {
641
  var lineNumber;
642
  if (e.line) {
643
    lineNumber = e.line;
644
  }
645
  else if (e.lineNumber) {
646
    lineNumber = e.lineNumber;
647
  }
648
649
  var file;
650
651
  if (e.sourceURL) {
652
    file = e.sourceURL;
653
  }
654
  else if (e.fileName) {
655
    file = e.fileName;
656
  }
657
658
  var message = (e.name && e.message) ? (e.name + ': ' + e.message) : e.toString();
659
660
  if (file && lineNumber) {
661
    message += ' in ' + file + ' (line ' + lineNumber + ')';
662
  }
663
664
  return message;
665
};
666
667
jasmine.util.htmlEscape = function(str) {
668
  if (!str) return str;
0 ignored issues
show
Coding Style Best Practice introduced by
Curly braces around statements make for more readable code and help prevent bugs when you add further statements.

Consider adding curly braces around all statements when they are executed conditionally. This is optional if there is only one statement, but leaving them out can lead to unexpected behaviour if another statement is added later.

Consider:

if (a > 0)
    b = 42;

If you or someone else later decides to put another statement in, only the first statement will be executed.

if (a > 0)
    console.log("a > 0");
    b = 42;

In this case the statement b = 42 will always be executed, while the logging statement will be executed conditionally.

if (a > 0) {
    console.log("a > 0");
    b = 42;
}

ensures that the proper code will be executed conditionally no matter how many statements are added or removed.

Loading history...
669
  return str.replace(/&/g, '&amp;')
670
    .replace(/</g, '&lt;')
671
    .replace(/>/g, '&gt;');
672
};
673
674
jasmine.util.argsToArray = function(args) {
675
  var arrayOfArgs = [];
676
  for (var i = 0; i < args.length; i++) arrayOfArgs.push(args[i]);
0 ignored issues
show
Coding Style Best Practice introduced by
Curly braces around statements make for more readable code and help prevent bugs when you add further statements.

Consider adding curly braces around all statements when they are executed conditionally. This is optional if there is only one statement, but leaving them out can lead to unexpected behaviour if another statement is added later.

Consider:

if (a > 0)
    b = 42;

If you or someone else later decides to put another statement in, only the first statement will be executed.

if (a > 0)
    console.log("a > 0");
    b = 42;

In this case the statement b = 42 will always be executed, while the logging statement will be executed conditionally.

if (a > 0) {
    console.log("a > 0");
    b = 42;
}

ensures that the proper code will be executed conditionally no matter how many statements are added or removed.

Loading history...
677
  return arrayOfArgs;
678
};
679
680
jasmine.util.extend = function(destination, source) {
681
  for (var property in source) destination[property] = source[property];
0 ignored issues
show
Complexity introduced by
A for in loop automatically includes the property of any prototype object, consider checking the key using hasOwnProperty.

When iterating over the keys of an object, this includes not only the keys of the object, but also keys contained in the prototype of that object. It is generally a best practice to check for these keys specifically:

var someObject;
for (var key in someObject) {
    if ( ! someObject.hasOwnProperty(key)) {
        continue; // Skip keys from the prototype.
    }

    doSomethingWith(key);
}
Loading history...
Coding Style Best Practice introduced by
Curly braces around statements make for more readable code and help prevent bugs when you add further statements.

Consider adding curly braces around all statements when they are executed conditionally. This is optional if there is only one statement, but leaving them out can lead to unexpected behaviour if another statement is added later.

Consider:

if (a > 0)
    b = 42;

If you or someone else later decides to put another statement in, only the first statement will be executed.

if (a > 0)
    console.log("a > 0");
    b = 42;

In this case the statement b = 42 will always be executed, while the logging statement will be executed conditionally.

if (a > 0) {
    console.log("a > 0");
    b = 42;
}

ensures that the proper code will be executed conditionally no matter how many statements are added or removed.

Loading history...
682
  return destination;
683
};
684
685
/**
686
 * Environment for Jasmine
687
 *
688
 * @constructor
689
 */
690
jasmine.Env = function() {
691
  this.currentSpec = null;
692
  this.currentSuite = null;
693
  this.currentRunner_ = new jasmine.Runner(this);
694
695
  this.reporter = new jasmine.MultiReporter();
696
697
  this.updateInterval = jasmine.DEFAULT_UPDATE_INTERVAL;
698
  this.defaultTimeoutInterval = jasmine.DEFAULT_TIMEOUT_INTERVAL;
699
  this.lastUpdate = 0;
700
  this.specFilter = function() {
701
    return true;
702
  };
703
704
  this.nextSpecId_ = 0;
705
  this.nextSuiteId_ = 0;
706
  this.equalityTesters_ = [];
707
708
  // wrap matchers
709
  this.matchersClass = function() {
710
    jasmine.Matchers.apply(this, arguments);
711
  };
712
  jasmine.util.inherit(this.matchersClass, jasmine.Matchers);
713
714
  jasmine.Matchers.wrapInto_(jasmine.Matchers.prototype, this.matchersClass);
715
};
716
717
718
jasmine.Env.prototype.setTimeout = jasmine.setTimeout;
719
jasmine.Env.prototype.clearTimeout = jasmine.clearTimeout;
720
jasmine.Env.prototype.setInterval = jasmine.setInterval;
721
jasmine.Env.prototype.clearInterval = jasmine.clearInterval;
722
723
/**
724
 * @returns an object containing jasmine version build info, if set.
725
 */
726
jasmine.Env.prototype.version = function () {
727
  if (jasmine.version_) {
728
    return jasmine.version_;
729
  } else {
730
    throw new Error('Version not set');
731
  }
732
};
733
734
/**
735
 * @returns string containing jasmine version build info, if set.
736
 */
737
jasmine.Env.prototype.versionString = function() {
738
  if (!jasmine.version_) {
739
    return "version unknown";
740
  }
741
742
  var version = this.version();
743
  var versionString = version.major + "." + version.minor + "." + version.build;
744
  if (version.release_candidate) {
745
    versionString += ".rc" + version.release_candidate;
746
  }
747
  versionString += " revision " + version.revision;
748
  return versionString;
749
};
750
751
/**
752
 * @returns a sequential integer starting at 0
753
 */
754
jasmine.Env.prototype.nextSpecId = function () {
755
  return this.nextSpecId_++;
756
};
757
758
/**
759
 * @returns a sequential integer starting at 0
760
 */
761
jasmine.Env.prototype.nextSuiteId = function () {
762
  return this.nextSuiteId_++;
763
};
764
765
/**
766
 * Register a reporter to receive status updates from Jasmine.
767
 * @param {jasmine.Reporter} reporter An object which will receive status updates.
768
 */
769
jasmine.Env.prototype.addReporter = function(reporter) {
770
  this.reporter.addReporter(reporter);
771
};
772
773
jasmine.Env.prototype.execute = function() {
774
  this.currentRunner_.execute();
775
};
776
777
jasmine.Env.prototype.describe = function(description, specDefinitions) {
778
  var suite = new jasmine.Suite(this, description, specDefinitions, this.currentSuite);
779
780
  var parentSuite = this.currentSuite;
781
  if (parentSuite) {
782
    parentSuite.add(suite);
783
  } else {
784
    this.currentRunner_.add(suite);
785
  }
786
787
  this.currentSuite = suite;
788
789
  var declarationError = null;
790
  try {
791
    specDefinitions.call(suite);
792
  } catch(e) {
793
    declarationError = e;
794
  }
795
796
  if (declarationError) {
797
    this.it("encountered a declaration exception", function() {
798
      throw declarationError;
799
    });
800
  }
801
802
  this.currentSuite = parentSuite;
803
804
  return suite;
805
};
806
807
jasmine.Env.prototype.beforeEach = function(beforeEachFunction) {
808
  if (this.currentSuite) {
809
    this.currentSuite.beforeEach(beforeEachFunction);
810
  } else {
811
    this.currentRunner_.beforeEach(beforeEachFunction);
812
  }
813
};
814
815
jasmine.Env.prototype.currentRunner = function () {
816
  return this.currentRunner_;
817
};
818
819
jasmine.Env.prototype.afterEach = function(afterEachFunction) {
820
  if (this.currentSuite) {
821
    this.currentSuite.afterEach(afterEachFunction);
822
  } else {
823
    this.currentRunner_.afterEach(afterEachFunction);
824
  }
825
826
};
827
828
jasmine.Env.prototype.xdescribe = function(desc, specDefinitions) {
0 ignored issues
show
Unused Code introduced by
The parameter specDefinitions is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
Unused Code introduced by
The parameter desc is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
829
  return {
830
    execute: function() {
831
    }
832
  };
833
};
834
835
jasmine.Env.prototype.it = function(description, func) {
836
  var spec = new jasmine.Spec(this, this.currentSuite, description);
837
  this.currentSuite.add(spec);
838
  this.currentSpec = spec;
839
840
  if (func) {
841
    spec.runs(func);
842
  }
843
844
  return spec;
845
};
846
847
jasmine.Env.prototype.xit = function(desc, func) {
0 ignored issues
show
Unused Code introduced by
The parameter desc is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
Unused Code introduced by
The parameter func is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
848
  return {
849
    id: this.nextSpecId(),
850
    runs: function() {
851
    }
852
  };
853
};
854
855
jasmine.Env.prototype.compareObjects_ = function(a, b, mismatchKeys, mismatchValues) {
856
  if (a.__Jasmine_been_here_before__ === b && b.__Jasmine_been_here_before__ === a) {
857
    return true;
858
  }
859
860
  a.__Jasmine_been_here_before__ = b;
861
  b.__Jasmine_been_here_before__ = a;
862
863
  var hasKey = function(obj, keyName) {
864
    return obj !== null && obj[keyName] !== jasmine.undefined;
865
  };
866
867
  for (var property in b) {
0 ignored issues
show
Complexity introduced by
A for in loop automatically includes the property of any prototype object, consider checking the key using hasOwnProperty.

When iterating over the keys of an object, this includes not only the keys of the object, but also keys contained in the prototype of that object. It is generally a best practice to check for these keys specifically:

var someObject;
for (var key in someObject) {
    if ( ! someObject.hasOwnProperty(key)) {
        continue; // Skip keys from the prototype.
    }

    doSomethingWith(key);
}
Loading history...
868
    if (!hasKey(a, property) && hasKey(b, property)) {
869
      mismatchKeys.push("expected has key '" + property + "', but missing from actual.");
870
    }
871
  }
872
  for (property in a) {
873
    if (!hasKey(b, property) && hasKey(a, property)) {
874
      mismatchKeys.push("expected missing key '" + property + "', but present in actual.");
875
    }
876
  }
877
  for (property in b) {
878
    if (property == '__Jasmine_been_here_before__') continue;
0 ignored issues
show
Coding Style Best Practice introduced by
Curly braces around statements make for more readable code and help prevent bugs when you add further statements.

Consider adding curly braces around all statements when they are executed conditionally. This is optional if there is only one statement, but leaving them out can lead to unexpected behaviour if another statement is added later.

Consider:

if (a > 0)
    b = 42;

If you or someone else later decides to put another statement in, only the first statement will be executed.

if (a > 0)
    console.log("a > 0");
    b = 42;

In this case the statement b = 42 will always be executed, while the logging statement will be executed conditionally.

if (a > 0) {
    console.log("a > 0");
    b = 42;
}

ensures that the proper code will be executed conditionally no matter how many statements are added or removed.

Loading history...
879
    if (!this.equals_(a[property], b[property], mismatchKeys, mismatchValues)) {
880
      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.");
881
    }
882
  }
883
884
  if (jasmine.isArray_(a) && jasmine.isArray_(b) && a.length != b.length) {
885
    mismatchValues.push("arrays were not the same length");
886
  }
887
888
  delete a.__Jasmine_been_here_before__;
889
  delete b.__Jasmine_been_here_before__;
890
  return (mismatchKeys.length === 0 && mismatchValues.length === 0);
891
};
892
893
jasmine.Env.prototype.equals_ = function(a, b, mismatchKeys, mismatchValues) {
894
  mismatchKeys = mismatchKeys || [];
895
  mismatchValues = mismatchValues || [];
896
897
  for (var i = 0; i < this.equalityTesters_.length; i++) {
898
    var equalityTester = this.equalityTesters_[i];
899
    var result = equalityTester(a, b, this, mismatchKeys, mismatchValues);
900
    if (result !== jasmine.undefined) return result;
0 ignored issues
show
Coding Style Best Practice introduced by
Curly braces around statements make for more readable code and help prevent bugs when you add further statements.

Consider adding curly braces around all statements when they are executed conditionally. This is optional if there is only one statement, but leaving them out can lead to unexpected behaviour if another statement is added later.

Consider:

if (a > 0)
    b = 42;

If you or someone else later decides to put another statement in, only the first statement will be executed.

if (a > 0)
    console.log("a > 0");
    b = 42;

In this case the statement b = 42 will always be executed, while the logging statement will be executed conditionally.

if (a > 0) {
    console.log("a > 0");
    b = 42;
}

ensures that the proper code will be executed conditionally no matter how many statements are added or removed.

Loading history...
901
  }
902
903
  if (a === b) return true;
0 ignored issues
show
Coding Style Best Practice introduced by
Curly braces around statements make for more readable code and help prevent bugs when you add further statements.

Consider adding curly braces around all statements when they are executed conditionally. This is optional if there is only one statement, but leaving them out can lead to unexpected behaviour if another statement is added later.

Consider:

if (a > 0)
    b = 42;

If you or someone else later decides to put another statement in, only the first statement will be executed.

if (a > 0)
    console.log("a > 0");
    b = 42;

In this case the statement b = 42 will always be executed, while the logging statement will be executed conditionally.

if (a > 0) {
    console.log("a > 0");
    b = 42;
}

ensures that the proper code will be executed conditionally no matter how many statements are added or removed.

Loading history...
904
905
  if (a === jasmine.undefined || a === null || b === jasmine.undefined || b === null) {
906
    return (a == jasmine.undefined && b == jasmine.undefined);
907
  }
908
909
  if (jasmine.isDomNode(a) && jasmine.isDomNode(b)) {
910
    return a === b;
911
  }
912
913
  if (a instanceof Date && b instanceof Date) {
914
    return a.getTime() == b.getTime();
915
  }
916
917
  if (a instanceof jasmine.Matchers.Any) {
918
    return a.matches(b);
919
  }
920
921
  if (b instanceof jasmine.Matchers.Any) {
922
    return b.matches(a);
923
  }
924
925
  if (jasmine.isString_(a) && jasmine.isString_(b)) {
926
    return (a == b);
927
  }
928
929
  if (jasmine.isNumber_(a) && jasmine.isNumber_(b)) {
930
    return (a == b);
931
  }
932
933
  if (typeof a === "object" && typeof b === "object") {
934
    return this.compareObjects_(a, b, mismatchKeys, mismatchValues);
935
  }
936
937
  //Straight check
938
  return (a === b);
939
};
940
941
jasmine.Env.prototype.contains_ = function(haystack, needle) {
942
  if (jasmine.isArray_(haystack)) {
943
    for (var i = 0; i < haystack.length; i++) {
944
      if (this.equals_(haystack[i], needle)) return true;
0 ignored issues
show
Coding Style Best Practice introduced by
Curly braces around statements make for more readable code and help prevent bugs when you add further statements.

Consider adding curly braces around all statements when they are executed conditionally. This is optional if there is only one statement, but leaving them out can lead to unexpected behaviour if another statement is added later.

Consider:

if (a > 0)
    b = 42;

If you or someone else later decides to put another statement in, only the first statement will be executed.

if (a > 0)
    console.log("a > 0");
    b = 42;

In this case the statement b = 42 will always be executed, while the logging statement will be executed conditionally.

if (a > 0) {
    console.log("a > 0");
    b = 42;
}

ensures that the proper code will be executed conditionally no matter how many statements are added or removed.

Loading history...
945
    }
946
    return false;
947
  }
948
  return haystack.indexOf(needle) >= 0;
949
};
950
951
jasmine.Env.prototype.addEqualityTester = function(equalityTester) {
952
  this.equalityTesters_.push(equalityTester);
953
};
954
/** No-op base class for Jasmine reporters.
955
 *
956
 * @constructor
957
 */
958
jasmine.Reporter = function() {
959
};
960
961
//noinspection JSUnusedLocalSymbols
962
jasmine.Reporter.prototype.reportRunnerStarting = function(runner) {
0 ignored issues
show
Unused Code introduced by
The parameter runner is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
963
};
964
965
//noinspection JSUnusedLocalSymbols
966
jasmine.Reporter.prototype.reportRunnerResults = function(runner) {
0 ignored issues
show
Unused Code introduced by
The parameter runner is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
967
};
968
969
//noinspection JSUnusedLocalSymbols
970
jasmine.Reporter.prototype.reportSuiteResults = function(suite) {
0 ignored issues
show
Unused Code introduced by
The parameter suite is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
971
};
972
973
//noinspection JSUnusedLocalSymbols
974
jasmine.Reporter.prototype.reportSpecStarting = function(spec) {
0 ignored issues
show
Unused Code introduced by
The parameter spec is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
975
};
976
977
//noinspection JSUnusedLocalSymbols
978
jasmine.Reporter.prototype.reportSpecResults = function(spec) {
0 ignored issues
show
Unused Code introduced by
The parameter spec is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
979
};
980
981
//noinspection JSUnusedLocalSymbols
982
jasmine.Reporter.prototype.log = function(str) {
0 ignored issues
show
Unused Code introduced by
The parameter str is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
983
};
984
985
/**
986
 * Blocks are functions with executable code that make up a spec.
987
 *
988
 * @constructor
989
 * @param {jasmine.Env} env
990
 * @param {Function} func
991
 * @param {jasmine.Spec} spec
992
 */
993
jasmine.Block = function(env, func, spec) {
994
  this.env = env;
995
  this.func = func;
996
  this.spec = spec;
997
};
998
999
jasmine.Block.prototype.execute = function(onComplete) {  
1000
  try {
1001
    this.func.apply(this.spec);
1002
  } catch (e) {
1003
    this.spec.fail(e);
1004
  }
1005
  onComplete();
1006
};
1007
/** JavaScript API reporter.
1008
 *
1009
 * @constructor
1010
 */
1011
jasmine.JsApiReporter = function() {
1012
  this.started = false;
1013
  this.finished = false;
1014
  this.suites_ = [];
1015
  this.results_ = {};
1016
};
1017
1018
jasmine.JsApiReporter.prototype.reportRunnerStarting = function(runner) {
1019
  this.started = true;
1020
  var suites = runner.topLevelSuites();
1021
  for (var i = 0; i < suites.length; i++) {
1022
    var suite = suites[i];
1023
    this.suites_.push(this.summarize_(suite));
1024
  }
1025
};
1026
1027
jasmine.JsApiReporter.prototype.suites = function() {
1028
  return this.suites_;
1029
};
1030
1031
jasmine.JsApiReporter.prototype.summarize_ = function(suiteOrSpec) {
1032
  var isSuite = suiteOrSpec instanceof jasmine.Suite;
1033
  var summary = {
1034
    id: suiteOrSpec.id,
1035
    name: suiteOrSpec.description,
1036
    type: isSuite ? 'suite' : 'spec',
1037
    children: []
1038
  };
1039
  
1040
  if (isSuite) {
1041
    var children = suiteOrSpec.children();
1042
    for (var i = 0; i < children.length; i++) {
1043
      summary.children.push(this.summarize_(children[i]));
1044
    }
1045
  }
1046
  return summary;
1047
};
1048
1049
jasmine.JsApiReporter.prototype.results = function() {
1050
  return this.results_;
1051
};
1052
1053
jasmine.JsApiReporter.prototype.resultsForSpec = function(specId) {
1054
  return this.results_[specId];
1055
};
1056
1057
//noinspection JSUnusedLocalSymbols
1058
jasmine.JsApiReporter.prototype.reportRunnerResults = function(runner) {
0 ignored issues
show
Unused Code introduced by
The parameter runner is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
1059
  this.finished = true;
1060
};
1061
1062
//noinspection JSUnusedLocalSymbols
1063
jasmine.JsApiReporter.prototype.reportSuiteResults = function(suite) {
0 ignored issues
show
Unused Code introduced by
The parameter suite is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
1064
};
1065
1066
//noinspection JSUnusedLocalSymbols
1067
jasmine.JsApiReporter.prototype.reportSpecResults = function(spec) {
1068
  this.results_[spec.id] = {
1069
    messages: spec.results().getItems(),
1070
    result: spec.results().failedCount > 0 ? "failed" : "passed"
1071
  };
1072
};
1073
1074
//noinspection JSUnusedLocalSymbols
1075
jasmine.JsApiReporter.prototype.log = function(str) {
0 ignored issues
show
Unused Code introduced by
The parameter str is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
1076
};
1077
1078
jasmine.JsApiReporter.prototype.resultsForSpecs = function(specIds){
1079
  var results = {};
1080
  for (var i = 0; i < specIds.length; i++) {
1081
    var specId = specIds[i];
1082
    results[specId] = this.summarizeResult_(this.results_[specId]);
1083
  }
1084
  return results;
1085
};
1086
1087
jasmine.JsApiReporter.prototype.summarizeResult_ = function(result){
1088
  var summaryMessages = [];
1089
  var messagesLength = result.messages.length;
1090
  for (var messageIndex = 0; messageIndex < messagesLength; messageIndex++) {
1091
    var resultMessage = result.messages[messageIndex];
1092
    summaryMessages.push({
1093
      text: resultMessage.type == 'log' ? resultMessage.toString() : jasmine.undefined,
1094
      passed: resultMessage.passed ? resultMessage.passed() : true,
1095
      type: resultMessage.type,
1096
      message: resultMessage.message,
1097
      trace: {
1098
        stack: resultMessage.passed && !resultMessage.passed() ? resultMessage.trace.stack : jasmine.undefined
1099
      }
1100
    });
1101
  }
1102
1103
  return {
1104
    result : result.result,
1105
    messages : summaryMessages
1106
  };
1107
};
1108
1109
/**
1110
 * @constructor
1111
 * @param {jasmine.Env} env
1112
 * @param actual
1113
 * @param {jasmine.Spec} spec
1114
 */
1115
jasmine.Matchers = function(env, actual, spec, opt_isNot) {
1116
  this.env = env;
1117
  this.actual = actual;
1118
  this.spec = spec;
1119
  this.isNot = opt_isNot || false;
1120
  this.reportWasCalled_ = false;
1121
};
1122
1123
// todo: @deprecated as of Jasmine 0.11, remove soon [xw]
1124
jasmine.Matchers.pp = function(str) {
0 ignored issues
show
Unused Code introduced by
The parameter str is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
1125
  throw new Error("jasmine.Matchers.pp() is no longer supported, please use jasmine.pp() instead!");
1126
};
1127
1128
// todo: @deprecated Deprecated as of Jasmine 0.10. Rewrite your custom matchers to return true or false. [xw]
1129
jasmine.Matchers.prototype.report = function(result, failing_message, details) {
0 ignored issues
show
Unused Code introduced by
The parameter failing_message is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
Unused Code introduced by
The parameter result is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
Unused Code introduced by
The parameter details is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
1130
  throw new Error("As of jasmine 0.11, custom matchers must be implemented differently -- please see jasmine docs");
1131
};
1132
1133
jasmine.Matchers.wrapInto_ = function(prototype, matchersClass) {
1134
  for (var methodName in prototype) {
0 ignored issues
show
Complexity introduced by
A for in loop automatically includes the property of any prototype object, consider checking the key using hasOwnProperty.

When iterating over the keys of an object, this includes not only the keys of the object, but also keys contained in the prototype of that object. It is generally a best practice to check for these keys specifically:

var someObject;
for (var key in someObject) {
    if ( ! someObject.hasOwnProperty(key)) {
        continue; // Skip keys from the prototype.
    }

    doSomethingWith(key);
}
Loading history...
1135
    if (methodName == 'report') continue;
0 ignored issues
show
Coding Style Best Practice introduced by
Curly braces around statements make for more readable code and help prevent bugs when you add further statements.

Consider adding curly braces around all statements when they are executed conditionally. This is optional if there is only one statement, but leaving them out can lead to unexpected behaviour if another statement is added later.

Consider:

if (a > 0)
    b = 42;

If you or someone else later decides to put another statement in, only the first statement will be executed.

if (a > 0)
    console.log("a > 0");
    b = 42;

In this case the statement b = 42 will always be executed, while the logging statement will be executed conditionally.

if (a > 0) {
    console.log("a > 0");
    b = 42;
}

ensures that the proper code will be executed conditionally no matter how many statements are added or removed.

Loading history...
1136
    var orig = prototype[methodName];
1137
    matchersClass.prototype[methodName] = jasmine.Matchers.matcherFn_(methodName, orig);
1138
  }
1139
};
1140
1141
jasmine.Matchers.matcherFn_ = function(matcherName, matcherFunction) {
1142
  return function() {
1143
    var matcherArgs = jasmine.util.argsToArray(arguments);
1144
    var result = matcherFunction.apply(this, arguments);
1145
1146
    if (this.isNot) {
1147
      result = !result;
1148
    }
1149
1150
    if (this.reportWasCalled_) return result;
0 ignored issues
show
Coding Style Best Practice introduced by
Curly braces around statements make for more readable code and help prevent bugs when you add further statements.

Consider adding curly braces around all statements when they are executed conditionally. This is optional if there is only one statement, but leaving them out can lead to unexpected behaviour if another statement is added later.

Consider:

if (a > 0)
    b = 42;

If you or someone else later decides to put another statement in, only the first statement will be executed.

if (a > 0)
    console.log("a > 0");
    b = 42;

In this case the statement b = 42 will always be executed, while the logging statement will be executed conditionally.

if (a > 0) {
    console.log("a > 0");
    b = 42;
}

ensures that the proper code will be executed conditionally no matter how many statements are added or removed.

Loading history...
1151
1152
    var message;
1153
    if (!result) {
1154
      if (this.message) {
1155
        message = this.message.apply(this, arguments);
1156
        if (jasmine.isArray_(message)) {
1157
          message = message[this.isNot ? 1 : 0];
1158
        }
1159
      } else {
1160
        var englishyPredicate = matcherName.replace(/[A-Z]/g, function(s) { return ' ' + s.toLowerCase(); });
1161
        message = "Expected " + jasmine.pp(this.actual) + (this.isNot ? " not " : " ") + englishyPredicate;
1162
        if (matcherArgs.length > 0) {
1163
          for (var i = 0; i < matcherArgs.length; i++) {
1164
            if (i > 0) message += ",";
0 ignored issues
show
Coding Style Best Practice introduced by
Curly braces around statements make for more readable code and help prevent bugs when you add further statements.

Consider adding curly braces around all statements when they are executed conditionally. This is optional if there is only one statement, but leaving them out can lead to unexpected behaviour if another statement is added later.

Consider:

if (a > 0)
    b = 42;

If you or someone else later decides to put another statement in, only the first statement will be executed.

if (a > 0)
    console.log("a > 0");
    b = 42;

In this case the statement b = 42 will always be executed, while the logging statement will be executed conditionally.

if (a > 0) {
    console.log("a > 0");
    b = 42;
}

ensures that the proper code will be executed conditionally no matter how many statements are added or removed.

Loading history...
1165
            message += " " + jasmine.pp(matcherArgs[i]);
1166
          }
1167
        }
1168
        message += ".";
1169
      }
1170
    }
1171
    var expectationResult = new jasmine.ExpectationResult({
1172
      matcherName: matcherName,
1173
      passed: result,
1174
      expected: matcherArgs.length > 1 ? matcherArgs : matcherArgs[0],
1175
      actual: this.actual,
1176
      message: message
0 ignored issues
show
Bug introduced by
The variable message does not seem to be initialized in case !result on line 1153 is false. Are you sure this can never be the case?
Loading history...
1177
    });
1178
    this.spec.addMatcherResult(expectationResult);
1179
    return jasmine.undefined;
1180
  };
1181
};
1182
1183
1184
1185
1186
/**
1187
 * toBe: compares the actual to the expected using ===
1188
 * @param expected
1189
 */
1190
jasmine.Matchers.prototype.toBe = function(expected) {
1191
  return this.actual === expected;
1192
};
1193
1194
/**
1195
 * toNotBe: compares the actual to the expected using !==
1196
 * @param expected
1197
 * @deprecated as of 1.0. Use not.toBe() instead.
1198
 */
1199
jasmine.Matchers.prototype.toNotBe = function(expected) {
1200
  return this.actual !== expected;
1201
};
1202
1203
/**
1204
 * toEqual: compares the actual to the expected using common sense equality. Handles Objects, Arrays, etc.
1205
 *
1206
 * @param expected
1207
 */
1208
jasmine.Matchers.prototype.toEqual = function(expected) {
1209
  return this.env.equals_(this.actual, expected);
1210
};
1211
1212
/**
1213
 * toNotEqual: compares the actual to the expected using the ! of jasmine.Matchers.toEqual
1214
 * @param expected
1215
 * @deprecated as of 1.0. Use not.toNotEqual() instead.
1216
 */
1217
jasmine.Matchers.prototype.toNotEqual = function(expected) {
1218
  return !this.env.equals_(this.actual, expected);
1219
};
1220
1221
/**
1222
 * Matcher that compares the actual to the expected using a regular expression.  Constructs a RegExp, so takes
1223
 * a pattern or a String.
1224
 *
1225
 * @param expected
1226
 */
1227
jasmine.Matchers.prototype.toMatch = function(expected) {
1228
  return new RegExp(expected).test(this.actual);
1229
};
1230
1231
/**
1232
 * Matcher that compares the actual to the expected using the boolean inverse of jasmine.Matchers.toMatch
1233
 * @param expected
1234
 * @deprecated as of 1.0. Use not.toMatch() instead.
1235
 */
1236
jasmine.Matchers.prototype.toNotMatch = function(expected) {
1237
  return !(new RegExp(expected).test(this.actual));
1238
};
1239
1240
/**
1241
 * Matcher that compares the actual to jasmine.undefined.
1242
 */
1243
jasmine.Matchers.prototype.toBeDefined = function() {
1244
  return (this.actual !== jasmine.undefined);
1245
};
1246
1247
/**
1248
 * Matcher that compares the actual to jasmine.undefined.
1249
 */
1250
jasmine.Matchers.prototype.toBeUndefined = function() {
1251
  return (this.actual === jasmine.undefined);
1252
};
1253
1254
/**
1255
 * Matcher that compares the actual to null.
1256
 */
1257
jasmine.Matchers.prototype.toBeNull = function() {
1258
  return (this.actual === null);
1259
};
1260
1261
/**
1262
 * Matcher that boolean not-nots the actual.
1263
 */
1264
jasmine.Matchers.prototype.toBeTruthy = function() {
1265
  return !!this.actual;
1266
};
1267
1268
1269
/**
1270
 * Matcher that boolean nots the actual.
1271
 */
1272
jasmine.Matchers.prototype.toBeFalsy = function() {
1273
  return !this.actual;
1274
};
1275
1276
1277
/**
1278
 * Matcher that checks to see if the actual, a Jasmine spy, was called.
1279
 */
1280
jasmine.Matchers.prototype.toHaveBeenCalled = function() {
1281
  if (arguments.length > 0) {
1282
    throw new Error('toHaveBeenCalled does not take arguments, use toHaveBeenCalledWith');
1283
  }
1284
1285
  if (!jasmine.isSpy(this.actual)) {
1286
    throw new Error('Expected a spy, but got ' + jasmine.pp(this.actual) + '.');
1287
  }
1288
1289
  this.message = function() {
1290
    return [
1291
      "Expected spy " + this.actual.identity + " to have been called.",
1292
      "Expected spy " + this.actual.identity + " not to have been called."
1293
    ];
1294
  };
1295
1296
  return this.actual.wasCalled;
1297
};
1298
1299
/** @deprecated Use expect(xxx).toHaveBeenCalled() instead */
1300
jasmine.Matchers.prototype.wasCalled = jasmine.Matchers.prototype.toHaveBeenCalled;
1301
1302
/**
1303
 * Matcher that checks to see if the actual, a Jasmine spy, was not called.
1304
 *
1305
 * @deprecated Use expect(xxx).not.toHaveBeenCalled() instead
1306
 */
1307
jasmine.Matchers.prototype.wasNotCalled = function() {
1308
  if (arguments.length > 0) {
1309
    throw new Error('wasNotCalled does not take arguments');
1310
  }
1311
1312
  if (!jasmine.isSpy(this.actual)) {
1313
    throw new Error('Expected a spy, but got ' + jasmine.pp(this.actual) + '.');
1314
  }
1315
1316
  this.message = function() {
1317
    return [
1318
      "Expected spy " + this.actual.identity + " to not have been called.",
1319
      "Expected spy " + this.actual.identity + " to have been called."
1320
    ];
1321
  };
1322
1323
  return !this.actual.wasCalled;
1324
};
1325
1326
/**
1327
 * Matcher that checks to see if the actual, a Jasmine spy, was called with a set of parameters.
1328
 *
1329
 * @example
1330
 *
1331
 */
1332
jasmine.Matchers.prototype.toHaveBeenCalledWith = function() {
1333
  var expectedArgs = jasmine.util.argsToArray(arguments);
1334
  if (!jasmine.isSpy(this.actual)) {
1335
    throw new Error('Expected a spy, but got ' + jasmine.pp(this.actual) + '.');
1336
  }
1337
  this.message = function() {
1338
    if (this.actual.callCount === 0) {
1339
      // todo: what should the failure message for .not.toHaveBeenCalledWith() be? is this right? test better. [xw]
1340
      return [
1341
        "Expected spy " + this.actual.identity + " to have been called with " + jasmine.pp(expectedArgs) + " but it was never called.",
1342
        "Expected spy " + this.actual.identity + " not to have been called with " + jasmine.pp(expectedArgs) + " but it was."
1343
      ];
1344
    } else {
1345
      return [
1346
        "Expected spy " + this.actual.identity + " to have been called with " + jasmine.pp(expectedArgs) + " but was called with " + jasmine.pp(this.actual.argsForCall),
1347
        "Expected spy " + this.actual.identity + " not to have been called with " + jasmine.pp(expectedArgs) + " but was called with " + jasmine.pp(this.actual.argsForCall)
1348
      ];
1349
    }
1350
  };
1351
1352
  return this.env.contains_(this.actual.argsForCall, expectedArgs);
1353
};
1354
1355
/** @deprecated Use expect(xxx).toHaveBeenCalledWith() instead */
1356
jasmine.Matchers.prototype.wasCalledWith = jasmine.Matchers.prototype.toHaveBeenCalledWith;
1357
1358
/** @deprecated Use expect(xxx).not.toHaveBeenCalledWith() instead */
1359
jasmine.Matchers.prototype.wasNotCalledWith = function() {
1360
  var expectedArgs = jasmine.util.argsToArray(arguments);
1361
  if (!jasmine.isSpy(this.actual)) {
1362
    throw new Error('Expected a spy, but got ' + jasmine.pp(this.actual) + '.');
1363
  }
1364
1365
  this.message = function() {
1366
    return [
1367
      "Expected spy not to have been called with " + jasmine.pp(expectedArgs) + " but it was",
1368
      "Expected spy to have been called with " + jasmine.pp(expectedArgs) + " but it was"
1369
    ];
1370
  };
1371
1372
  return !this.env.contains_(this.actual.argsForCall, expectedArgs);
1373
};
1374
1375
/**
1376
 * Matcher that checks that the expected item is an element in the actual Array.
1377
 *
1378
 * @param {Object} expected
1379
 */
1380
jasmine.Matchers.prototype.toContain = function(expected) {
1381
  return this.env.contains_(this.actual, expected);
1382
};
1383
1384
/**
1385
 * Matcher that checks that the expected item is NOT an element in the actual Array.
1386
 *
1387
 * @param {Object} expected
1388
 * @deprecated as of 1.0. Use not.toNotContain() instead.
1389
 */
1390
jasmine.Matchers.prototype.toNotContain = function(expected) {
1391
  return !this.env.contains_(this.actual, expected);
1392
};
1393
1394
jasmine.Matchers.prototype.toBeLessThan = function(expected) {
1395
  return this.actual < expected;
1396
};
1397
1398
jasmine.Matchers.prototype.toBeGreaterThan = function(expected) {
1399
  return this.actual > expected;
1400
};
1401
1402
/**
1403
 * Matcher that checks that the expected item is equal to the actual item
1404
 * up to a given level of decimal precision (default 2).
1405
 *
1406
 * @param {Number} expected
1407
 * @param {Number} precision
1408
 */
1409
jasmine.Matchers.prototype.toBeCloseTo = function(expected, precision) {
1410
  if (!(precision === 0)) {
1411
    precision = precision || 2;
1412
  }
1413
  var multiplier = Math.pow(10, precision);
1414
  var actual = Math.round(this.actual * multiplier);
1415
  expected = Math.round(expected * multiplier);
1416
  return expected == actual;
1417
};
1418
1419
/**
1420
 * Matcher that checks that the expected exception was thrown by the actual.
1421
 *
1422
 * @param {String} expected
1423
 */
1424
jasmine.Matchers.prototype.toThrow = function(expected) {
1425
  var result = false;
1426
  var exception;
1427
  if (typeof this.actual != 'function') {
1428
    throw new Error('Actual is not a function');
1429
  }
1430
  try {
1431
    this.actual();
1432
  } catch (e) {
1433
    exception = e;
1434
  }
1435
  if (exception) {
1436
    result = (expected === jasmine.undefined || this.env.equals_(exception.message || exception, expected.message || expected));
1437
  }
1438
1439
  var not = this.isNot ? "not " : "";
1440
1441
  this.message = function() {
1442
    if (exception && (expected === jasmine.undefined || !this.env.equals_(exception.message || exception, expected.message || expected))) {
1443
      return ["Expected function " + not + "to throw", expected ? expected.message || expected : "an exception", ", but it threw", exception.message || exception].join(' ');
1444
    } else {
1445
      return "Expected function to throw an exception.";
1446
    }
1447
  };
1448
1449
  return result;
1450
};
1451
1452
jasmine.Matchers.Any = function(expectedClass) {
1453
  this.expectedClass = expectedClass;
1454
};
1455
1456
jasmine.Matchers.Any.prototype.matches = function(other) {
1457
  if (this.expectedClass == String) {
1458
    return typeof other == 'string' || other instanceof String;
1459
  }
1460
1461
  if (this.expectedClass == Number) {
1462
    return typeof other == 'number' || other instanceof Number;
1463
  }
1464
1465
  if (this.expectedClass == Function) {
1466
    return typeof other == 'function' || other instanceof Function;
1467
  }
1468
1469
  if (this.expectedClass == Object) {
1470
    return typeof other == 'object';
1471
  }
1472
1473
  return other instanceof this.expectedClass;
1474
};
1475
1476
jasmine.Matchers.Any.prototype.toString = function() {
1477
  return '<jasmine.any(' + this.expectedClass + ')>';
1478
};
1479
1480
/**
1481
 * @constructor
1482
 */
1483
jasmine.MultiReporter = function() {
1484
  this.subReporters_ = [];
1485
};
1486
jasmine.util.inherit(jasmine.MultiReporter, jasmine.Reporter);
1487
1488
jasmine.MultiReporter.prototype.addReporter = function(reporter) {
1489
  this.subReporters_.push(reporter);
1490
};
1491
1492
(function() {
1493
  var functionNames = [
1494
    "reportRunnerStarting",
1495
    "reportRunnerResults",
1496
    "reportSuiteResults",
1497
    "reportSpecStarting",
1498
    "reportSpecResults",
1499
    "log"
1500
  ];
1501
  for (var i = 0; i < functionNames.length; i++) {
1502
    var functionName = functionNames[i];
1503
    jasmine.MultiReporter.prototype[functionName] = (function(functionName) {
1504
      return function() {
1505
        for (var j = 0; j < this.subReporters_.length; j++) {
1506
          var subReporter = this.subReporters_[j];
1507
          if (subReporter[functionName]) {
1508
            subReporter[functionName].apply(subReporter, arguments);
1509
          }
1510
        }
1511
      };
1512
    })(functionName);
1513
  }
1514
})();
1515
/**
1516
 * Holds results for a set of Jasmine spec. Allows for the results array to hold another jasmine.NestedResults
1517
 *
1518
 * @constructor
1519
 */
1520
jasmine.NestedResults = function() {
1521
  /**
1522
   * The total count of results
1523
   */
1524
  this.totalCount = 0;
1525
  /**
1526
   * Number of passed results
1527
   */
1528
  this.passedCount = 0;
1529
  /**
1530
   * Number of failed results
1531
   */
1532
  this.failedCount = 0;
1533
  /**
1534
   * Was this suite/spec skipped?
1535
   */
1536
  this.skipped = false;
1537
  /**
1538
   * @ignore
1539
   */
1540
  this.items_ = [];
1541
};
1542
1543
/**
1544
 * Roll up the result counts.
1545
 *
1546
 * @param result
1547
 */
1548
jasmine.NestedResults.prototype.rollupCounts = function(result) {
1549
  this.totalCount += result.totalCount;
1550
  this.passedCount += result.passedCount;
1551
  this.failedCount += result.failedCount;
1552
};
1553
1554
/**
1555
 * Adds a log message.
1556
 * @param values Array of message parts which will be concatenated later.
1557
 */
1558
jasmine.NestedResults.prototype.log = function(values) {
1559
  this.items_.push(new jasmine.MessageResult(values));
1560
};
1561
1562
/**
1563
 * Getter for the results: message & results.
1564
 */
1565
jasmine.NestedResults.prototype.getItems = function() {
1566
  return this.items_;
1567
};
1568
1569
/**
1570
 * Adds a result, tracking counts (total, passed, & failed)
1571
 * @param {jasmine.ExpectationResult|jasmine.NestedResults} result
1572
 */
1573
jasmine.NestedResults.prototype.addResult = function(result) {
1574
  if (result.type != 'log') {
1575
    if (result.items_) {
1576
      this.rollupCounts(result);
1577
    } else {
1578
      this.totalCount++;
1579
      if (result.passed()) {
1580
        this.passedCount++;
1581
      } else {
1582
        this.failedCount++;
1583
      }
1584
    }
1585
  }
1586
  this.items_.push(result);
1587
};
1588
1589
/**
1590
 * @returns {Boolean} True if <b>everything</b> below passed
1591
 */
1592
jasmine.NestedResults.prototype.passed = function() {
1593
  return this.passedCount === this.totalCount;
1594
};
1595
/**
1596
 * Base class for pretty printing for expectation results.
1597
 */
1598
jasmine.PrettyPrinter = function() {
1599
  this.ppNestLevel_ = 0;
1600
};
1601
1602
/**
1603
 * Formats a value in a nice, human-readable string.
1604
 *
1605
 * @param value
1606
 */
1607
jasmine.PrettyPrinter.prototype.format = function(value) {
1608
  if (this.ppNestLevel_ > 40) {
1609
    throw new Error('jasmine.PrettyPrinter: format() nested too deeply!');
1610
  }
1611
1612
  this.ppNestLevel_++;
1613
  try {
1614
    if (value === jasmine.undefined) {
1615
      this.emitScalar('undefined');
1616
    } else if (value === null) {
1617
      this.emitScalar('null');
1618
    } else if (value === jasmine.getGlobal()) {
1619
      this.emitScalar('<global>');
1620
    } else if (value instanceof jasmine.Matchers.Any) {
1621
      this.emitScalar(value.toString());
1622
    } else if (typeof value === 'string') {
1623
      this.emitString(value);
1624
    } else if (jasmine.isSpy(value)) {
1625
      this.emitScalar("spy on " + value.identity);
1626
    } else if (value instanceof RegExp) {
1627
      this.emitScalar(value.toString());
1628
    } else if (typeof value === 'function') {
1629
      this.emitScalar('Function');
1630
    } else if (typeof value.nodeType === 'number') {
1631
      this.emitScalar('HTMLNode');
1632
    } else if (value instanceof Date) {
1633
      this.emitScalar('Date(' + value + ')');
1634
    } else if (value.__Jasmine_been_here_before__) {
1635
      this.emitScalar('<circular reference: ' + (jasmine.isArray_(value) ? 'Array' : 'Object') + '>');
1636
    } else if (jasmine.isArray_(value) || typeof value == 'object') {
1637
      value.__Jasmine_been_here_before__ = true;
1638
      if (jasmine.isArray_(value)) {
1639
        this.emitArray(value);
1640
      } else {
1641
        this.emitObject(value);
1642
      }
1643
      delete value.__Jasmine_been_here_before__;
1644
    } else {
1645
      this.emitScalar(value.toString());
1646
    }
1647
  } finally {
1648
    this.ppNestLevel_--;
1649
  }
1650
};
1651
1652
jasmine.PrettyPrinter.prototype.iterateObject = function(obj, fn) {
1653
  for (var property in obj) {
0 ignored issues
show
Complexity introduced by
A for in loop automatically includes the property of any prototype object, consider checking the key using hasOwnProperty.

When iterating over the keys of an object, this includes not only the keys of the object, but also keys contained in the prototype of that object. It is generally a best practice to check for these keys specifically:

var someObject;
for (var key in someObject) {
    if ( ! someObject.hasOwnProperty(key)) {
        continue; // Skip keys from the prototype.
    }

    doSomethingWith(key);
}
Loading history...
1654
    if (property == '__Jasmine_been_here_before__') continue;
0 ignored issues
show
Coding Style Best Practice introduced by
Curly braces around statements make for more readable code and help prevent bugs when you add further statements.

Consider adding curly braces around all statements when they are executed conditionally. This is optional if there is only one statement, but leaving them out can lead to unexpected behaviour if another statement is added later.

Consider:

if (a > 0)
    b = 42;

If you or someone else later decides to put another statement in, only the first statement will be executed.

if (a > 0)
    console.log("a > 0");
    b = 42;

In this case the statement b = 42 will always be executed, while the logging statement will be executed conditionally.

if (a > 0) {
    console.log("a > 0");
    b = 42;
}

ensures that the proper code will be executed conditionally no matter how many statements are added or removed.

Loading history...
1655
    fn(property, obj.__lookupGetter__ ? (obj.__lookupGetter__(property) !== jasmine.undefined && 
1656
                                         obj.__lookupGetter__(property) !== null) : false);
1657
  }
1658
};
1659
1660
jasmine.PrettyPrinter.prototype.emitArray = jasmine.unimplementedMethod_;
1661
jasmine.PrettyPrinter.prototype.emitObject = jasmine.unimplementedMethod_;
1662
jasmine.PrettyPrinter.prototype.emitScalar = jasmine.unimplementedMethod_;
1663
jasmine.PrettyPrinter.prototype.emitString = jasmine.unimplementedMethod_;
1664
1665
jasmine.StringPrettyPrinter = function() {
1666
  jasmine.PrettyPrinter.call(this);
1667
1668
  this.string = '';
1669
};
1670
jasmine.util.inherit(jasmine.StringPrettyPrinter, jasmine.PrettyPrinter);
1671
1672
jasmine.StringPrettyPrinter.prototype.emitScalar = function(value) {
1673
  this.append(value);
1674
};
1675
1676
jasmine.StringPrettyPrinter.prototype.emitString = function(value) {
1677
  this.append("'" + value + "'");
1678
};
1679
1680
jasmine.StringPrettyPrinter.prototype.emitArray = function(array) {
1681
  this.append('[ ');
1682
  for (var i = 0; i < array.length; i++) {
1683
    if (i > 0) {
1684
      this.append(', ');
1685
    }
1686
    this.format(array[i]);
1687
  }
1688
  this.append(' ]');
1689
};
1690
1691
jasmine.StringPrettyPrinter.prototype.emitObject = function(obj) {
1692
  var self = this;
1693
  this.append('{ ');
1694
  var first = true;
1695
1696
  this.iterateObject(obj, function(property, isGetter) {
1697
    if (first) {
1698
      first = false;
1699
    } else {
1700
      self.append(', ');
1701
    }
1702
1703
    self.append(property);
1704
    self.append(' : ');
1705
    if (isGetter) {
1706
      self.append('<getter>');
1707
    } else {
1708
      self.format(obj[property]);
1709
    }
1710
  });
1711
1712
  this.append(' }');
1713
};
1714
1715
jasmine.StringPrettyPrinter.prototype.append = function(value) {
1716
  this.string += value;
1717
};
1718
jasmine.Queue = function(env) {
1719
  this.env = env;
1720
  this.blocks = [];
1721
  this.running = false;
1722
  this.index = 0;
1723
  this.offset = 0;
1724
  this.abort = false;
1725
};
1726
1727
jasmine.Queue.prototype.addBefore = function(block) {
1728
  this.blocks.unshift(block);
1729
};
1730
1731
jasmine.Queue.prototype.add = function(block) {
1732
  this.blocks.push(block);
1733
};
1734
1735
jasmine.Queue.prototype.insertNext = function(block) {
1736
  this.blocks.splice((this.index + this.offset + 1), 0, block);
1737
  this.offset++;
1738
};
1739
1740
jasmine.Queue.prototype.start = function(onComplete) {
1741
  this.running = true;
1742
  this.onComplete = onComplete;
1743
  this.next_();
1744
};
1745
1746
jasmine.Queue.prototype.isRunning = function() {
1747
  return this.running;
1748
};
1749
1750
jasmine.Queue.LOOP_DONT_RECURSE = true;
1751
1752
jasmine.Queue.prototype.next_ = function() {
1753
  var self = this;
1754
  var goAgain = true;
1755
1756
  while (goAgain) {
1757
    goAgain = false;
1758
    
1759
    if (self.index < self.blocks.length && !this.abort) {
1760
      var calledSynchronously = true;
1761
      var completedSynchronously = false;
1762
1763
      var onComplete = function () {
1764
        if (jasmine.Queue.LOOP_DONT_RECURSE && calledSynchronously) {
0 ignored issues
show
Bug introduced by
The variable calledSynchronously is changed as part of the while loop for example by true on line 1760. Only the value of the last iteration will be visible in this function if it is called after the loop.
Loading history...
1765
          completedSynchronously = true;
1766
          return;
1767
        }
1768
1769
        if (self.blocks[self.index].abort) {
1770
          self.abort = true;
1771
        }
1772
1773
        self.offset = 0;
1774
        self.index++;
1775
1776
        var now = new Date().getTime();
1777
        if (self.env.updateInterval && now - self.env.lastUpdate > self.env.updateInterval) {
1778
          self.env.lastUpdate = now;
1779
          self.env.setTimeout(function() {
1780
            self.next_();
1781
          }, 0);
1782
        } else {
1783
          if (jasmine.Queue.LOOP_DONT_RECURSE && completedSynchronously) {
0 ignored issues
show
Bug introduced by
The variable completedSynchronously is changed as part of the while loop for example by false on line 1761. Only the value of the last iteration will be visible in this function if it is called after the loop.
Loading history...
1784
            goAgain = true;
1785
          } else {
1786
            self.next_();
1787
          }
1788
        }
1789
      };
1790
      self.blocks[self.index].execute(onComplete);
1791
1792
      calledSynchronously = false;
1793
      if (completedSynchronously) {
1794
        onComplete();
1795
      }
1796
      
1797
    } else {
1798
      self.running = false;
1799
      if (self.onComplete) {
1800
        self.onComplete();
1801
      }
1802
    }
1803
  }
1804
};
1805
1806
jasmine.Queue.prototype.results = function() {
1807
  var results = new jasmine.NestedResults();
1808
  for (var i = 0; i < this.blocks.length; i++) {
1809
    if (this.blocks[i].results) {
1810
      results.addResult(this.blocks[i].results());
1811
    }
1812
  }
1813
  return results;
1814
};
1815
1816
1817
/**
1818
 * Runner
1819
 *
1820
 * @constructor
1821
 * @param {jasmine.Env} env
1822
 */
1823
jasmine.Runner = function(env) {
1824
  var self = this;
1825
  self.env = env;
1826
  self.queue = new jasmine.Queue(env);
1827
  self.before_ = [];
1828
  self.after_ = [];
1829
  self.suites_ = [];
1830
};
1831
1832
jasmine.Runner.prototype.execute = function() {
1833
  var self = this;
1834
  if (self.env.reporter.reportRunnerStarting) {
1835
    self.env.reporter.reportRunnerStarting(this);
1836
  }
1837
  self.queue.start(function () {
1838
    self.finishCallback();
1839
  });
1840
};
1841
1842
jasmine.Runner.prototype.beforeEach = function(beforeEachFunction) {
1843
  beforeEachFunction.typeName = 'beforeEach';
1844
  this.before_.splice(0,0,beforeEachFunction);
1845
};
1846
1847
jasmine.Runner.prototype.afterEach = function(afterEachFunction) {
1848
  afterEachFunction.typeName = 'afterEach';
1849
  this.after_.splice(0,0,afterEachFunction);
1850
};
1851
1852
1853
jasmine.Runner.prototype.finishCallback = function() {
1854
  this.env.reporter.reportRunnerResults(this);
1855
};
1856
1857
jasmine.Runner.prototype.addSuite = function(suite) {
1858
  this.suites_.push(suite);
1859
};
1860
1861
jasmine.Runner.prototype.add = function(block) {
1862
  if (block instanceof jasmine.Suite) {
1863
    this.addSuite(block);
1864
  }
1865
  this.queue.add(block);
1866
};
1867
1868
jasmine.Runner.prototype.specs = function () {
1869
  var suites = this.suites();
1870
  var specs = [];
1871
  for (var i = 0; i < suites.length; i++) {
1872
    specs = specs.concat(suites[i].specs());
1873
  }
1874
  return specs;
1875
};
1876
1877
jasmine.Runner.prototype.suites = function() {
1878
  return this.suites_;
1879
};
1880
1881
jasmine.Runner.prototype.topLevelSuites = function() {
1882
  var topLevelSuites = [];
1883
  for (var i = 0; i < this.suites_.length; i++) {
1884
    if (!this.suites_[i].parentSuite) {
1885
      topLevelSuites.push(this.suites_[i]);
1886
    }
1887
  }
1888
  return topLevelSuites;
1889
};
1890
1891
jasmine.Runner.prototype.results = function() {
1892
  return this.queue.results();
1893
};
1894
/**
1895
 * Internal representation of a Jasmine specification, or test.
1896
 *
1897
 * @constructor
1898
 * @param {jasmine.Env} env
1899
 * @param {jasmine.Suite} suite
1900
 * @param {String} description
1901
 */
1902
jasmine.Spec = function(env, suite, description) {
1903
  if (!env) {
1904
    throw new Error('jasmine.Env() required');
1905
  }
1906
  if (!suite) {
1907
    throw new Error('jasmine.Suite() required');
1908
  }
1909
  var spec = this;
1910
  spec.id = env.nextSpecId ? env.nextSpecId() : null;
1911
  spec.env = env;
1912
  spec.suite = suite;
1913
  spec.description = description;
1914
  spec.queue = new jasmine.Queue(env);
1915
1916
  spec.afterCallbacks = [];
1917
  spec.spies_ = [];
1918
1919
  spec.results_ = new jasmine.NestedResults();
1920
  spec.results_.description = description;
1921
  spec.matchersClass = null;
1922
};
1923
1924
jasmine.Spec.prototype.getFullName = function() {
1925
  return this.suite.getFullName() + ' ' + this.description + '.';
1926
};
1927
1928
1929
jasmine.Spec.prototype.results = function() {
1930
  return this.results_;
1931
};
1932
1933
/**
1934
 * All parameters are pretty-printed and concatenated together, then written to the spec's output.
1935
 *
1936
 * Be careful not to leave calls to <code>jasmine.log</code> in production code.
1937
 */
1938
jasmine.Spec.prototype.log = function() {
1939
  return this.results_.log(arguments);
1940
};
1941
1942
jasmine.Spec.prototype.runs = function (func) {
1943
  var block = new jasmine.Block(this.env, func, this);
1944
  this.addToQueue(block);
1945
  return this;
1946
};
1947
1948
jasmine.Spec.prototype.addToQueue = function (block) {
1949
  if (this.queue.isRunning()) {
1950
    this.queue.insertNext(block);
1951
  } else {
1952
    this.queue.add(block);
1953
  }
1954
};
1955
1956
/**
1957
 * @param {jasmine.ExpectationResult} result
1958
 */
1959
jasmine.Spec.prototype.addMatcherResult = function(result) {
1960
  this.results_.addResult(result);
1961
};
1962
1963
jasmine.Spec.prototype.expect = function(actual) {
1964
  var positive = new (this.getMatchersClass_())(this.env, actual, this);
1965
  positive.not = new (this.getMatchersClass_())(this.env, actual, this, true);
1966
  return positive;
1967
};
1968
1969
/**
1970
 * Waits a fixed time period before moving to the next block.
1971
 *
1972
 * @deprecated Use waitsFor() instead
1973
 * @param {Number} timeout milliseconds to wait
1974
 */
1975
jasmine.Spec.prototype.waits = function(timeout) {
1976
  var waitsFunc = new jasmine.WaitsBlock(this.env, timeout, this);
1977
  this.addToQueue(waitsFunc);
1978
  return this;
1979
};
1980
1981
/**
1982
 * Waits for the latchFunction to return true before proceeding to the next block.
1983
 *
1984
 * @param {Function} latchFunction
1985
 * @param {String} optional_timeoutMessage
1986
 * @param {Number} optional_timeout
1987
 */
1988
jasmine.Spec.prototype.waitsFor = function(latchFunction, optional_timeoutMessage, optional_timeout) {
0 ignored issues
show
Unused Code introduced by
The parameter optional_timeout is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
Unused Code introduced by
The parameter optional_timeoutMessage is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
Unused Code introduced by
The parameter latchFunction is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
1989
  var latchFunction_ = null;
1990
  var optional_timeoutMessage_ = null;
1991
  var optional_timeout_ = null;
1992
1993
  for (var i = 0; i < arguments.length; i++) {
1994
    var arg = arguments[i];
1995
    switch (typeof arg) {
0 ignored issues
show
Coding Style introduced by
As per coding-style, switch statements should have a default case.
Loading history...
1996
      case 'function':
1997
        latchFunction_ = arg;
1998
        break;
1999
      case 'string':
2000
        optional_timeoutMessage_ = arg;
2001
        break;
2002
      case 'number':
2003
        optional_timeout_ = arg;
2004
        break;
2005
    }
2006
  }
2007
2008
  var waitsForFunc = new jasmine.WaitsForBlock(this.env, optional_timeout_, latchFunction_, optional_timeoutMessage_, this);
2009
  this.addToQueue(waitsForFunc);
2010
  return this;
2011
};
2012
2013
jasmine.Spec.prototype.fail = function (e) {
2014
  var expectationResult = new jasmine.ExpectationResult({
2015
    passed: false,
2016
    message: e ? jasmine.util.formatException(e) : 'Exception',
2017
    trace: { stack: e.stack }
2018
  });
2019
  this.results_.addResult(expectationResult);
2020
};
2021
2022
jasmine.Spec.prototype.getMatchersClass_ = function() {
2023
  return this.matchersClass || this.env.matchersClass;
2024
};
2025
2026
jasmine.Spec.prototype.addMatchers = function(matchersPrototype) {
2027
  var parent = this.getMatchersClass_();
2028
  var newMatchersClass = function() {
2029
    parent.apply(this, arguments);
2030
  };
2031
  jasmine.util.inherit(newMatchersClass, parent);
2032
  jasmine.Matchers.wrapInto_(matchersPrototype, newMatchersClass);
2033
  this.matchersClass = newMatchersClass;
2034
};
2035
2036
jasmine.Spec.prototype.finishCallback = function() {
2037
  this.env.reporter.reportSpecResults(this);
2038
};
2039
2040
jasmine.Spec.prototype.finish = function(onComplete) {
2041
  this.removeAllSpies();
2042
  this.finishCallback();
2043
  if (onComplete) {
2044
    onComplete();
2045
  }
2046
};
2047
2048
jasmine.Spec.prototype.after = function(doAfter) {
2049
  if (this.queue.isRunning()) {
2050
    this.queue.add(new jasmine.Block(this.env, doAfter, this));
2051
  } else {
2052
    this.afterCallbacks.unshift(doAfter);
2053
  }
2054
};
2055
2056
jasmine.Spec.prototype.execute = function(onComplete) {
2057
  var spec = this;
2058
  if (!spec.env.specFilter(spec)) {
2059
    spec.results_.skipped = true;
2060
    spec.finish(onComplete);
2061
    return;
2062
  }
2063
2064
  this.env.reporter.reportSpecStarting(this);
2065
2066
  spec.env.currentSpec = spec;
2067
2068
  spec.addBeforesAndAftersToQueue();
2069
2070
  spec.queue.start(function () {
2071
    spec.finish(onComplete);
2072
  });
2073
};
2074
2075
jasmine.Spec.prototype.addBeforesAndAftersToQueue = function() {
2076
  var runner = this.env.currentRunner();
2077
  var i;
2078
2079
  for (var suite = this.suite; suite; suite = suite.parentSuite) {
2080
    for (i = 0; i < suite.before_.length; i++) {
2081
      this.queue.addBefore(new jasmine.Block(this.env, suite.before_[i], this));
2082
    }
2083
  }
2084
  for (i = 0; i < runner.before_.length; i++) {
2085
    this.queue.addBefore(new jasmine.Block(this.env, runner.before_[i], this));
2086
  }
2087
  for (i = 0; i < this.afterCallbacks.length; i++) {
2088
    this.queue.add(new jasmine.Block(this.env, this.afterCallbacks[i], this));
2089
  }
2090
  for (suite = this.suite; suite; suite = suite.parentSuite) {
2091
    for (i = 0; i < suite.after_.length; i++) {
2092
      this.queue.add(new jasmine.Block(this.env, suite.after_[i], this));
2093
    }
2094
  }
2095
  for (i = 0; i < runner.after_.length; i++) {
2096
    this.queue.add(new jasmine.Block(this.env, runner.after_[i], this));
2097
  }
2098
};
2099
2100
jasmine.Spec.prototype.explodes = function() {
2101
  throw 'explodes function should not have been called';
2102
};
2103
2104
jasmine.Spec.prototype.spyOn = function(obj, methodName, ignoreMethodDoesntExist) {
2105
  if (obj == jasmine.undefined) {
2106
    throw "spyOn could not find an object to spy upon for " + methodName + "()";
2107
  }
2108
2109
  if (!ignoreMethodDoesntExist && obj[methodName] === jasmine.undefined) {
2110
    throw methodName + '() method does not exist';
2111
  }
2112
2113
  if (!ignoreMethodDoesntExist && obj[methodName] && obj[methodName].isSpy) {
2114
    throw new Error(methodName + ' has already been spied upon');
2115
  }
2116
2117
  var spyObj = jasmine.createSpy(methodName);
2118
2119
  this.spies_.push(spyObj);
2120
  spyObj.baseObj = obj;
2121
  spyObj.methodName = methodName;
2122
  spyObj.originalValue = obj[methodName];
2123
2124
  obj[methodName] = spyObj;
2125
2126
  return spyObj;
2127
};
2128
2129
jasmine.Spec.prototype.removeAllSpies = function() {
2130
  for (var i = 0; i < this.spies_.length; i++) {
2131
    var spy = this.spies_[i];
2132
    spy.baseObj[spy.methodName] = spy.originalValue;
2133
  }
2134
  this.spies_ = [];
2135
};
2136
2137
/**
2138
 * Internal representation of a Jasmine suite.
2139
 *
2140
 * @constructor
2141
 * @param {jasmine.Env} env
2142
 * @param {String} description
2143
 * @param {Function} specDefinitions
2144
 * @param {jasmine.Suite} parentSuite
2145
 */
2146
jasmine.Suite = function(env, description, specDefinitions, parentSuite) {
2147
  var self = this;
2148
  self.id = env.nextSuiteId ? env.nextSuiteId() : null;
2149
  self.description = description;
2150
  self.queue = new jasmine.Queue(env);
2151
  self.parentSuite = parentSuite;
2152
  self.env = env;
2153
  self.before_ = [];
2154
  self.after_ = [];
2155
  self.children_ = [];
2156
  self.suites_ = [];
2157
  self.specs_ = [];
2158
};
2159
2160
jasmine.Suite.prototype.getFullName = function() {
2161
  var fullName = this.description;
2162
  for (var parentSuite = this.parentSuite; parentSuite; parentSuite = parentSuite.parentSuite) {
2163
    fullName = parentSuite.description + ' ' + fullName;
2164
  }
2165
  return fullName;
2166
};
2167
2168
jasmine.Suite.prototype.finish = function(onComplete) {
2169
  this.env.reporter.reportSuiteResults(this);
2170
  this.finished = true;
2171
  if (typeof(onComplete) == 'function') {
2172
    onComplete();
2173
  }
2174
};
2175
2176
jasmine.Suite.prototype.beforeEach = function(beforeEachFunction) {
2177
  beforeEachFunction.typeName = 'beforeEach';
2178
  this.before_.unshift(beforeEachFunction);
2179
};
2180
2181
jasmine.Suite.prototype.afterEach = function(afterEachFunction) {
2182
  afterEachFunction.typeName = 'afterEach';
2183
  this.after_.unshift(afterEachFunction);
2184
};
2185
2186
jasmine.Suite.prototype.results = function() {
2187
  return this.queue.results();
2188
};
2189
2190
jasmine.Suite.prototype.add = function(suiteOrSpec) {
2191
  this.children_.push(suiteOrSpec);
2192
  if (suiteOrSpec instanceof jasmine.Suite) {
2193
    this.suites_.push(suiteOrSpec);
2194
    this.env.currentRunner().addSuite(suiteOrSpec);
2195
  } else {
2196
    this.specs_.push(suiteOrSpec);
2197
  }
2198
  this.queue.add(suiteOrSpec);
2199
};
2200
2201
jasmine.Suite.prototype.specs = function() {
2202
  return this.specs_;
2203
};
2204
2205
jasmine.Suite.prototype.suites = function() {
2206
  return this.suites_;
2207
};
2208
2209
jasmine.Suite.prototype.children = function() {
2210
  return this.children_;
2211
};
2212
2213
jasmine.Suite.prototype.execute = function(onComplete) {
2214
  var self = this;
2215
  this.queue.start(function () {
2216
    self.finish(onComplete);
2217
  });
2218
};
2219
jasmine.WaitsBlock = function(env, timeout, spec) {
2220
  this.timeout = timeout;
2221
  jasmine.Block.call(this, env, null, spec);
2222
};
2223
2224
jasmine.util.inherit(jasmine.WaitsBlock, jasmine.Block);
2225
2226
jasmine.WaitsBlock.prototype.execute = function (onComplete) {
2227
  if (jasmine.VERBOSE) {
2228
    this.env.reporter.log('>> Jasmine waiting for ' + this.timeout + ' ms...');
2229
  }
2230
  this.env.setTimeout(function () {
2231
    onComplete();
2232
  }, this.timeout);
2233
};
2234
/**
2235
 * A block which waits for some condition to become true, with timeout.
2236
 *
2237
 * @constructor
2238
 * @extends jasmine.Block
2239
 * @param {jasmine.Env} env The Jasmine environment.
2240
 * @param {Number} timeout The maximum time in milliseconds to wait for the condition to become true.
2241
 * @param {Function} latchFunction A function which returns true when the desired condition has been met.
2242
 * @param {String} message The message to display if the desired condition hasn't been met within the given time period.
2243
 * @param {jasmine.Spec} spec The Jasmine spec.
2244
 */
2245
jasmine.WaitsForBlock = function(env, timeout, latchFunction, message, spec) {
2246
  this.timeout = timeout || env.defaultTimeoutInterval;
2247
  this.latchFunction = latchFunction;
2248
  this.message = message;
2249
  this.totalTimeSpentWaitingForLatch = 0;
2250
  jasmine.Block.call(this, env, null, spec);
2251
};
2252
jasmine.util.inherit(jasmine.WaitsForBlock, jasmine.Block);
2253
2254
jasmine.WaitsForBlock.TIMEOUT_INCREMENT = 10;
2255
2256
jasmine.WaitsForBlock.prototype.execute = function(onComplete) {
2257
  if (jasmine.VERBOSE) {
2258
    this.env.reporter.log('>> Jasmine waiting for ' + (this.message || 'something to happen'));
2259
  }
2260
  var latchFunctionResult;
2261
  try {
2262
    latchFunctionResult = this.latchFunction.apply(this.spec);
2263
  } catch (e) {
2264
    this.spec.fail(e);
2265
    onComplete();
2266
    return;
2267
  }
2268
2269
  if (latchFunctionResult) {
2270
    onComplete();
2271
  } else if (this.totalTimeSpentWaitingForLatch >= this.timeout) {
2272
    var message = 'timed out after ' + this.timeout + ' msec waiting for ' + (this.message || 'something to happen');
2273
    this.spec.fail({
2274
      name: 'timeout',
2275
      message: message
2276
    });
2277
2278
    this.abort = true;
2279
    onComplete();
2280
  } else {
2281
    this.totalTimeSpentWaitingForLatch += jasmine.WaitsForBlock.TIMEOUT_INCREMENT;
2282
    var self = this;
2283
    this.env.setTimeout(function() {
2284
      self.execute(onComplete);
2285
    }, jasmine.WaitsForBlock.TIMEOUT_INCREMENT);
2286
  }
2287
};
2288
// Mock setTimeout, clearTimeout
2289
// Contributed by Pivotal Computer Systems, www.pivotalsf.com
2290
2291
jasmine.FakeTimer = function() {
2292
  this.reset();
2293
2294
  var self = this;
2295
  self.setTimeout = function(funcToCall, millis) {
2296
    self.timeoutsMade++;
2297
    self.scheduleFunction(self.timeoutsMade, funcToCall, millis, false);
2298
    return self.timeoutsMade;
2299
  };
2300
2301
  self.setInterval = function(funcToCall, millis) {
2302
    self.timeoutsMade++;
2303
    self.scheduleFunction(self.timeoutsMade, funcToCall, millis, true);
2304
    return self.timeoutsMade;
2305
  };
2306
2307
  self.clearTimeout = function(timeoutKey) {
2308
    self.scheduledFunctions[timeoutKey] = jasmine.undefined;
2309
  };
2310
2311
  self.clearInterval = function(timeoutKey) {
2312
    self.scheduledFunctions[timeoutKey] = jasmine.undefined;
2313
  };
2314
2315
};
2316
2317
jasmine.FakeTimer.prototype.reset = function() {
2318
  this.timeoutsMade = 0;
2319
  this.scheduledFunctions = {};
2320
  this.nowMillis = 0;
2321
};
2322
2323
jasmine.FakeTimer.prototype.tick = function(millis) {
2324
  var oldMillis = this.nowMillis;
2325
  var newMillis = oldMillis + millis;
2326
  this.runFunctionsWithinRange(oldMillis, newMillis);
2327
  this.nowMillis = newMillis;
2328
};
2329
2330
jasmine.FakeTimer.prototype.runFunctionsWithinRange = function(oldMillis, nowMillis) {
2331
  var scheduledFunc;
2332
  var funcsToRun = [];
2333
  for (var timeoutKey in this.scheduledFunctions) {
0 ignored issues
show
Complexity introduced by
A for in loop automatically includes the property of any prototype object, consider checking the key using hasOwnProperty.

When iterating over the keys of an object, this includes not only the keys of the object, but also keys contained in the prototype of that object. It is generally a best practice to check for these keys specifically:

var someObject;
for (var key in someObject) {
    if ( ! someObject.hasOwnProperty(key)) {
        continue; // Skip keys from the prototype.
    }

    doSomethingWith(key);
}
Loading history...
2334
    scheduledFunc = this.scheduledFunctions[timeoutKey];
2335
    if (scheduledFunc != jasmine.undefined &&
2336
        scheduledFunc.runAtMillis >= oldMillis &&
2337
        scheduledFunc.runAtMillis <= nowMillis) {
2338
      funcsToRun.push(scheduledFunc);
2339
      this.scheduledFunctions[timeoutKey] = jasmine.undefined;
2340
    }
2341
  }
2342
2343
  if (funcsToRun.length > 0) {
2344
    funcsToRun.sort(function(a, b) {
2345
      return a.runAtMillis - b.runAtMillis;
2346
    });
2347
    for (var i = 0; i < funcsToRun.length; ++i) {
2348
      try {
2349
        var funcToRun = funcsToRun[i];
2350
        this.nowMillis = funcToRun.runAtMillis;
2351
        funcToRun.funcToCall();
2352
        if (funcToRun.recurring) {
2353
          this.scheduleFunction(funcToRun.timeoutKey,
2354
              funcToRun.funcToCall,
2355
              funcToRun.millis,
2356
              true);
2357
        }
2358
      } catch(e) {
0 ignored issues
show
Coding Style Comprehensibility Best Practice introduced by
Empty catch clauses should be used with caution; consider adding a comment why this is needed.
Loading history...
2359
      }
2360
    }
2361
    this.runFunctionsWithinRange(oldMillis, nowMillis);
2362
  }
2363
};
2364
2365
jasmine.FakeTimer.prototype.scheduleFunction = function(timeoutKey, funcToCall, millis, recurring) {
2366
  this.scheduledFunctions[timeoutKey] = {
2367
    runAtMillis: this.nowMillis + millis,
2368
    funcToCall: funcToCall,
2369
    recurring: recurring,
2370
    timeoutKey: timeoutKey,
2371
    millis: millis
2372
  };
2373
};
2374
2375
/**
2376
 * @namespace
2377
 */
2378
jasmine.Clock = {
2379
  defaultFakeTimer: new jasmine.FakeTimer(),
2380
2381
  reset: function() {
2382
    jasmine.Clock.assertInstalled();
2383
    jasmine.Clock.defaultFakeTimer.reset();
2384
  },
2385
2386
  tick: function(millis) {
2387
    jasmine.Clock.assertInstalled();
2388
    jasmine.Clock.defaultFakeTimer.tick(millis);
2389
  },
2390
2391
  runFunctionsWithinRange: function(oldMillis, nowMillis) {
2392
    jasmine.Clock.defaultFakeTimer.runFunctionsWithinRange(oldMillis, nowMillis);
2393
  },
2394
2395
  scheduleFunction: function(timeoutKey, funcToCall, millis, recurring) {
2396
    jasmine.Clock.defaultFakeTimer.scheduleFunction(timeoutKey, funcToCall, millis, recurring);
2397
  },
2398
2399
  useMock: function() {
2400
    if (!jasmine.Clock.isInstalled()) {
2401
      var spec = jasmine.getEnv().currentSpec;
2402
      spec.after(jasmine.Clock.uninstallMock);
2403
2404
      jasmine.Clock.installMock();
2405
    }
2406
  },
2407
2408
  installMock: function() {
2409
    jasmine.Clock.installed = jasmine.Clock.defaultFakeTimer;
2410
  },
2411
2412
  uninstallMock: function() {
2413
    jasmine.Clock.assertInstalled();
2414
    jasmine.Clock.installed = jasmine.Clock.real;
2415
  },
2416
2417
  real: {
2418
    setTimeout: jasmine.getGlobal().setTimeout,
2419
    clearTimeout: jasmine.getGlobal().clearTimeout,
2420
    setInterval: jasmine.getGlobal().setInterval,
2421
    clearInterval: jasmine.getGlobal().clearInterval
2422
  },
2423
2424
  assertInstalled: function() {
2425
    if (!jasmine.Clock.isInstalled()) {
2426
      throw new Error("Mock clock is not installed, use jasmine.Clock.useMock()");
2427
    }
2428
  },
2429
2430
  isInstalled: function() {
2431
    return jasmine.Clock.installed == jasmine.Clock.defaultFakeTimer;
2432
  },
2433
2434
  installed: null
2435
};
2436
jasmine.Clock.installed = jasmine.Clock.real;
2437
2438
//else for IE support
2439
jasmine.getGlobal().setTimeout = function(funcToCall, millis) {
2440
  if (jasmine.Clock.installed.setTimeout.apply) {
2441
    return jasmine.Clock.installed.setTimeout.apply(this, arguments);
2442
  } else {
2443
    return jasmine.Clock.installed.setTimeout(funcToCall, millis);
2444
  }
2445
};
2446
2447
jasmine.getGlobal().setInterval = function(funcToCall, millis) {
2448
  if (jasmine.Clock.installed.setInterval.apply) {
2449
    return jasmine.Clock.installed.setInterval.apply(this, arguments);
2450
  } else {
2451
    return jasmine.Clock.installed.setInterval(funcToCall, millis);
2452
  }
2453
};
2454
2455
jasmine.getGlobal().clearTimeout = function(timeoutKey) {
2456
  if (jasmine.Clock.installed.clearTimeout.apply) {
2457
    return jasmine.Clock.installed.clearTimeout.apply(this, arguments);
2458
  } else {
2459
    return jasmine.Clock.installed.clearTimeout(timeoutKey);
2460
  }
2461
};
2462
2463
jasmine.getGlobal().clearInterval = function(timeoutKey) {
2464
  if (jasmine.Clock.installed.clearTimeout.apply) {
2465
    return jasmine.Clock.installed.clearInterval.apply(this, arguments);
2466
  } else {
2467
    return jasmine.Clock.installed.clearInterval(timeoutKey);
2468
  }
2469
};
2470
2471
jasmine.version_= {
2472
  "major": 1,
2473
  "minor": 1,
2474
  "build": 0,
2475
  "revision": 1315677058
2476
};
2477