rally-jasmine-core 1.2.0.0

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