webfontloader 1.2.0 → 1.2.1

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