teaspoon 0.7.9 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (163) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +382 -260
  3. data/app/assets/javascripts/teaspoon-angular.js +108 -26241
  4. data/app/assets/javascripts/teaspoon-jasmine.js +103 -2642
  5. data/app/assets/javascripts/teaspoon-mocha.js +109 -5416
  6. data/app/assets/javascripts/teaspoon-qunit.js +107 -2255
  7. data/app/assets/javascripts/teaspoon-teaspoon.js +0 -1
  8. data/app/assets/javascripts/teaspoon/angular.coffee +3 -1
  9. data/app/assets/javascripts/teaspoon/base/hook.coffee +21 -0
  10. data/app/assets/javascripts/teaspoon/base/reporters/html.coffee +26 -14
  11. data/app/assets/javascripts/teaspoon/base/reporters/html/progress_view.coffee +1 -1
  12. data/app/assets/javascripts/teaspoon/base/reporters/html/template.coffee +3 -3
  13. data/app/assets/javascripts/teaspoon/base/teaspoon.coffee +10 -1
  14. data/app/assets/javascripts/teaspoon/jasmine.coffee +3 -1
  15. data/app/assets/javascripts/teaspoon/mocha.coffee +3 -1
  16. data/app/assets/javascripts/teaspoon/mocha/reporters/html.coffee +1 -1
  17. data/app/assets/javascripts/teaspoon/qunit.coffee +3 -1
  18. data/app/assets/javascripts/teaspoon/qunit/reporters/html.coffee +1 -1
  19. data/app/assets/javascripts/teaspoon/teaspoon.coffee +0 -1
  20. data/app/assets/stylesheets/teaspoon.css +12 -8
  21. data/app/controllers/teaspoon/suite_controller.rb +32 -0
  22. data/app/views/teaspoon/suite/_body.html.erb +0 -0
  23. data/app/views/teaspoon/suite/_boot.html.erb +4 -0
  24. data/app/views/teaspoon/suite/_boot_require_js.html.erb +19 -0
  25. data/app/views/teaspoon/{spec/suites.html.erb → suite/index.html.erb} +6 -7
  26. data/app/views/teaspoon/suite/show.html.erb +19 -0
  27. data/bin/teaspoon +1 -1
  28. data/config/routes.rb +14 -4
  29. data/lib/generators/teaspoon/install/POST_INSTALL +2 -2
  30. data/lib/generators/teaspoon/install/install_generator.rb +22 -11
  31. data/lib/generators/teaspoon/install/templates/_body.html.erb +0 -0
  32. data/lib/generators/teaspoon/install/templates/_boot.html.erb +4 -0
  33. data/lib/generators/teaspoon/install/templates/jasmine/env.rb +11 -0
  34. data/lib/generators/teaspoon/install/templates/jasmine/env_comments.rb +182 -0
  35. data/lib/generators/teaspoon/install/templates/jasmine/spec_helper.coffee +8 -6
  36. data/lib/generators/teaspoon/install/templates/jasmine/spec_helper.js +8 -7
  37. data/lib/generators/teaspoon/install/templates/mocha/env.rb +11 -0
  38. data/lib/generators/teaspoon/install/templates/mocha/env_comments.rb +182 -0
  39. data/lib/generators/teaspoon/install/templates/mocha/spec_helper.coffee +13 -13
  40. data/lib/generators/teaspoon/install/templates/mocha/spec_helper.js +13 -13
  41. data/lib/generators/teaspoon/install/templates/qunit/env.rb +11 -0
  42. data/lib/generators/teaspoon/install/templates/qunit/env_comments.rb +182 -0
  43. data/lib/generators/teaspoon/install/templates/qunit/test_helper.coffee +6 -5
  44. data/lib/generators/teaspoon/install/templates/qunit/test_helper.js +6 -5
  45. data/lib/tasks/teaspoon.rake +9 -2
  46. data/lib/teaspoon.rb +4 -6
  47. data/lib/teaspoon/command_line.rb +116 -134
  48. data/lib/teaspoon/configuration.rb +144 -66
  49. data/lib/teaspoon/console.rb +70 -37
  50. data/lib/teaspoon/coverage.rb +42 -15
  51. data/lib/teaspoon/deprecated.rb +65 -0
  52. data/lib/teaspoon/drivers/base.rb +10 -0
  53. data/lib/teaspoon/drivers/phantomjs/runner.js +9 -11
  54. data/lib/teaspoon/drivers/phantomjs_driver.rb +21 -21
  55. data/lib/teaspoon/drivers/selenium_driver.rb +32 -13
  56. data/lib/teaspoon/engine.rb +32 -12
  57. data/lib/teaspoon/environment.rb +16 -12
  58. data/lib/teaspoon/exceptions.rb +41 -5
  59. data/lib/teaspoon/exporter.rb +52 -0
  60. data/lib/teaspoon/formatters/base.rb +171 -0
  61. data/lib/teaspoon/formatters/clean_formatter.rb +2 -4
  62. data/lib/teaspoon/formatters/documentation_formatter.rb +60 -0
  63. data/lib/teaspoon/formatters/dot_formatter.rb +12 -90
  64. data/lib/teaspoon/formatters/json_formatter.rb +36 -0
  65. data/lib/teaspoon/formatters/junit_formatter.rb +51 -32
  66. data/lib/teaspoon/formatters/modules/report_module.rb +76 -0
  67. data/lib/teaspoon/formatters/pride_formatter.rb +23 -27
  68. data/lib/teaspoon/formatters/snowday_formatter.rb +7 -11
  69. data/lib/teaspoon/formatters/swayze_or_oprah_formatter.rb +88 -64
  70. data/lib/teaspoon/formatters/tap_formatter.rb +18 -27
  71. data/lib/teaspoon/formatters/tap_y_formatter.rb +35 -45
  72. data/lib/teaspoon/formatters/teamcity_formatter.rb +69 -31
  73. data/lib/teaspoon/instrumentation.rb +33 -33
  74. data/lib/teaspoon/result.rb +2 -1
  75. data/lib/teaspoon/runner.rb +40 -28
  76. data/lib/teaspoon/server.rb +23 -25
  77. data/lib/teaspoon/suite.rb +52 -72
  78. data/lib/teaspoon/utility.rb +3 -14
  79. data/lib/teaspoon/version.rb +1 -1
  80. data/spec/dummy/app/assets/javascripts/integration/integration_spec.coffee +3 -0
  81. data/spec/dummy/app/assets/javascripts/integration/spec_helper.coffee +2 -0
  82. data/spec/dummy/config/application.rb +3 -0
  83. data/spec/features/console_reporter_spec.rb +48 -18
  84. data/spec/features/hooks_spec.rb +23 -41
  85. data/spec/features/html_reporter_spec.rb +38 -21
  86. data/spec/features/install_generator_spec.rb +34 -20
  87. data/spec/features/instrumentation_spec.rb +3 -2
  88. data/spec/fixtures/coverage.json +243 -0
  89. data/spec/javascripts/fixtures/_body.html.erb +1 -0
  90. data/spec/javascripts/jasmine_helper.coffee +1 -1
  91. data/spec/javascripts/teaspoon/base/fixture_spec.coffee +4 -4
  92. data/spec/javascripts/teaspoon/base/reporters/html_spec.coffee +9 -10
  93. data/spec/javascripts/teaspoon/mocha/reporters/html_mspec.coffee +0 -6
  94. data/spec/javascripts/teaspoon/phantomjs/runner_spec.coffee +5 -6
  95. data/spec/javascripts/turbolinks_helper.coffee +1 -1
  96. data/spec/spec_helper.rb +3 -4
  97. data/spec/teaspoon/command_line_spec.rb +139 -23
  98. data/spec/teaspoon/configuration_spec.rb +164 -46
  99. data/spec/teaspoon/console_spec.rb +142 -47
  100. data/spec/teaspoon/coverage_spec.rb +98 -28
  101. data/spec/teaspoon/drivers/base_spec.rb +5 -0
  102. data/spec/teaspoon/drivers/phantomjs_driver_spec.rb +32 -14
  103. data/spec/teaspoon/drivers/selenium_driver_spec.rb +32 -24
  104. data/spec/teaspoon/engine_spec.rb +8 -5
  105. data/spec/teaspoon/environment_spec.rb +56 -33
  106. data/spec/teaspoon/exceptions_spec.rb +57 -0
  107. data/spec/teaspoon/exporter_spec.rb +96 -0
  108. data/spec/teaspoon/formatters/base_spec.rb +259 -0
  109. data/spec/teaspoon/formatters/clean_formatter_spec.rb +37 -0
  110. data/spec/teaspoon/formatters/documentation_formatter_spec.rb +127 -0
  111. data/spec/teaspoon/formatters/dot_formatter_spec.rb +52 -56
  112. data/spec/teaspoon/formatters/json_formatter_spec.rb +77 -0
  113. data/spec/teaspoon/formatters/junit_formatter_spec.rb +72 -35
  114. data/spec/teaspoon/formatters/pride_formatter_spec.rb +37 -0
  115. data/spec/teaspoon/formatters/snowday_formatter_spec.rb +35 -0
  116. data/spec/teaspoon/formatters/tap_formatter_spec.rb +29 -81
  117. data/spec/teaspoon/formatters/tap_y_formatter_spec.rb +31 -141
  118. data/spec/teaspoon/formatters/teamcity_formatter_spec.rb +99 -42
  119. data/spec/teaspoon/instrumentation_spec.rb +44 -44
  120. data/spec/teaspoon/result_spec.rb +37 -0
  121. data/spec/teaspoon/runner_spec.rb +70 -59
  122. data/spec/teaspoon/server_spec.rb +34 -52
  123. data/spec/teaspoon/suite_spec.rb +42 -188
  124. data/spec/teaspoon_env.rb +39 -28
  125. data/vendor/assets/javascripts/{angular-scenario-1.0.5.js → angular/1.0.5.js} +0 -0
  126. data/vendor/assets/javascripts/{angular-scenario-1.0.5.MIT-LICENSE → angular/MIT-LICENSE} +0 -0
  127. data/vendor/assets/javascripts/{jasmine-1.3.1.js → jasmine/1.3.1.js} +0 -0
  128. data/vendor/assets/javascripts/jasmine/2.0.0.js +2412 -0
  129. data/vendor/assets/javascripts/{jasmine-1.3.1.MIT.LICENSE → jasmine/MIT.LICENSE} +0 -0
  130. data/vendor/assets/javascripts/{mocha-1.10.0.js → mocha/1.10.0.js} +1 -0
  131. data/vendor/assets/javascripts/mocha/1.17.1.js +5813 -0
  132. data/vendor/assets/javascripts/{mocha-1.10.1.MIT.LICENSE → mocha/MIT.LICENSE} +0 -0
  133. data/vendor/assets/javascripts/{qunit-1.12.0.js → qunit/1.12.0.js} +1 -1
  134. data/vendor/assets/javascripts/qunit/1.14.0.js +2288 -0
  135. data/vendor/assets/javascripts/{qunit-1.12.0.MIT.LICENSE → qunit/MIT.LICENSE} +0 -0
  136. data/vendor/assets/javascripts/support/chai.js +827 -385
  137. data/vendor/assets/javascripts/support/jasmine-jquery-1.7.0.js +720 -0
  138. data/vendor/assets/javascripts/support/jasmine-jquery-2.0.0.js +812 -0
  139. data/vendor/assets/javascripts/support/sinon-chai.js +17 -0
  140. data/vendor/assets/javascripts/support/sinon.js +1138 -643
  141. metadata +57 -36
  142. data/app/controllers/teaspoon/spec_controller.rb +0 -38
  143. data/app/helpers/teaspoon/spec_helper.rb +0 -36
  144. data/app/views/teaspoon/spec/_require_js.html.erb +0 -21
  145. data/app/views/teaspoon/spec/_standard.html.erb +0 -4
  146. data/app/views/teaspoon/spec/runner.html.erb +0 -19
  147. data/lib/generators/teaspoon/install/templates/env.rb +0 -38
  148. data/lib/generators/teaspoon/install/templates/jasmine/initializer.rb +0 -64
  149. data/lib/generators/teaspoon/install/templates/mocha/initializer.rb +0 -64
  150. data/lib/generators/teaspoon/install/templates/qunit/initializer.rb +0 -64
  151. data/lib/teaspoon/check_coverage.rb +0 -33
  152. data/lib/teaspoon/drivers/base_driver.rb +0 -10
  153. data/lib/teaspoon/exception_handling.rb +0 -18
  154. data/lib/teaspoon/formatters/base_formatter.rb +0 -63
  155. data/spec/dummy/config/initializers/teaspoon.rb +0 -41
  156. data/spec/teaspoon/check_coverage_spec.rb +0 -50
  157. data/spec/teaspoon/formatters/base_formatter_spec.rb +0 -45
  158. data/vendor/assets/javascripts/support/chai.MIT.LICENSE +0 -22
  159. data/vendor/assets/javascripts/support/expect.MIT.LICENSE +0 -22
  160. data/vendor/assets/javascripts/support/jasmine-jquery.MIT.LICENSE +0 -20
  161. data/vendor/assets/javascripts/support/jasmine-jquery.js +0 -659
  162. data/vendor/assets/javascripts/support/sinon-chai.MIT-ISH.LICENSE +0 -13
  163. data/vendor/assets/javascripts/support/sinon.BSD.LICENSE +0 -27
@@ -0,0 +1,2412 @@
1
+ /*
2
+ Copyright (c) 2008-2014 Pivotal Labs
3
+
4
+ Permission is hereby granted, free of charge, to any person obtaining
5
+ a copy of this software and associated documentation files (the
6
+ "Software"), to deal in the Software without restriction, including
7
+ without limitation the rights to use, copy, modify, merge, publish,
8
+ distribute, sublicense, and/or sell copies of the Software, and to
9
+ permit persons to whom the Software is furnished to do so, subject to
10
+ the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be
13
+ included in all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+ */
23
+ function getJasmineRequireObj() {
24
+ if (typeof module !== "undefined" && module.exports) {
25
+ return exports;
26
+ } else {
27
+ window.jasmineRequire = window.jasmineRequire || {};
28
+ return window.jasmineRequire;
29
+ }
30
+ }
31
+
32
+ getJasmineRequireObj().core = function(jRequire) {
33
+ var j$ = {};
34
+
35
+ jRequire.base(j$);
36
+ j$.util = jRequire.util();
37
+ j$.Any = jRequire.Any();
38
+ j$.CallTracker = jRequire.CallTracker();
39
+ j$.Clock = jRequire.Clock();
40
+ j$.DelayedFunctionScheduler = jRequire.DelayedFunctionScheduler();
41
+ j$.Env = jRequire.Env(j$);
42
+ j$.ExceptionFormatter = jRequire.ExceptionFormatter();
43
+ j$.Expectation = jRequire.Expectation();
44
+ j$.buildExpectationResult = jRequire.buildExpectationResult();
45
+ j$.JsApiReporter = jRequire.JsApiReporter();
46
+ j$.matchersUtil = jRequire.matchersUtil(j$);
47
+ j$.ObjectContaining = jRequire.ObjectContaining(j$);
48
+ j$.pp = jRequire.pp(j$);
49
+ j$.QueueRunner = jRequire.QueueRunner();
50
+ j$.ReportDispatcher = jRequire.ReportDispatcher();
51
+ j$.Spec = jRequire.Spec(j$);
52
+ j$.SpyStrategy = jRequire.SpyStrategy();
53
+ j$.Suite = jRequire.Suite();
54
+ j$.Timer = jRequire.Timer();
55
+ j$.version = jRequire.version();
56
+
57
+ j$.matchers = jRequire.requireMatchers(jRequire, j$);
58
+
59
+ return j$;
60
+ };
61
+
62
+ getJasmineRequireObj().requireMatchers = function(jRequire, j$) {
63
+ var availableMatchers = [
64
+ "toBe",
65
+ "toBeCloseTo",
66
+ "toBeDefined",
67
+ "toBeFalsy",
68
+ "toBeGreaterThan",
69
+ "toBeLessThan",
70
+ "toBeNaN",
71
+ "toBeNull",
72
+ "toBeTruthy",
73
+ "toBeUndefined",
74
+ "toContain",
75
+ "toEqual",
76
+ "toHaveBeenCalled",
77
+ "toHaveBeenCalledWith",
78
+ "toMatch",
79
+ "toThrow",
80
+ "toThrowError"
81
+ ],
82
+ matchers = {};
83
+
84
+ for (var i = 0; i < availableMatchers.length; i++) {
85
+ var name = availableMatchers[i];
86
+ matchers[name] = jRequire[name](j$);
87
+ }
88
+
89
+ return matchers;
90
+ };
91
+
92
+ getJasmineRequireObj().base = function(j$) {
93
+ j$.unimplementedMethod_ = function() {
94
+ throw new Error("unimplemented method");
95
+ };
96
+
97
+ j$.MAX_PRETTY_PRINT_DEPTH = 40;
98
+ j$.DEFAULT_TIMEOUT_INTERVAL = 5000;
99
+
100
+ j$.getGlobal = (function() {
101
+ var jasmineGlobal = eval.call(null, "this");
102
+ return function() {
103
+ return jasmineGlobal;
104
+ };
105
+ })();
106
+
107
+ j$.getEnv = function(options) {
108
+ var env = j$.currentEnv_ = j$.currentEnv_ || new j$.Env(options);
109
+ //jasmine. singletons in here (setTimeout blah blah).
110
+ return env;
111
+ };
112
+
113
+ j$.isArray_ = function(value) {
114
+ return j$.isA_("Array", value);
115
+ };
116
+
117
+ j$.isString_ = function(value) {
118
+ return j$.isA_("String", value);
119
+ };
120
+
121
+ j$.isNumber_ = function(value) {
122
+ return j$.isA_("Number", value);
123
+ };
124
+
125
+ j$.isA_ = function(typeName, value) {
126
+ return Object.prototype.toString.apply(value) === '[object ' + typeName + ']';
127
+ };
128
+
129
+ j$.isDomNode = function(obj) {
130
+ return obj.nodeType > 0;
131
+ };
132
+
133
+ j$.any = function(clazz) {
134
+ return new j$.Any(clazz);
135
+ };
136
+
137
+ j$.objectContaining = function(sample) {
138
+ return new j$.ObjectContaining(sample);
139
+ };
140
+
141
+ j$.createSpy = function(name, originalFn) {
142
+
143
+ var spyStrategy = new j$.SpyStrategy({
144
+ name: name,
145
+ fn: originalFn,
146
+ getSpy: function() { return spy; }
147
+ }),
148
+ callTracker = new j$.CallTracker(),
149
+ spy = function() {
150
+ callTracker.track({
151
+ object: this,
152
+ args: Array.prototype.slice.apply(arguments)
153
+ });
154
+ return spyStrategy.exec.apply(this, arguments);
155
+ };
156
+
157
+ for (var prop in originalFn) {
158
+ if (prop === 'and' || prop === 'calls') {
159
+ throw new Error("Jasmine spies would overwrite the 'and' and 'calls' properties on the object being spied upon");
160
+ }
161
+
162
+ spy[prop] = originalFn[prop];
163
+ }
164
+
165
+ spy.and = spyStrategy;
166
+ spy.calls = callTracker;
167
+
168
+ return spy;
169
+ };
170
+
171
+ j$.isSpy = function(putativeSpy) {
172
+ if (!putativeSpy) {
173
+ return false;
174
+ }
175
+ return putativeSpy.and instanceof j$.SpyStrategy &&
176
+ putativeSpy.calls instanceof j$.CallTracker;
177
+ };
178
+
179
+ j$.createSpyObj = function(baseName, methodNames) {
180
+ if (!j$.isArray_(methodNames) || methodNames.length === 0) {
181
+ throw "createSpyObj requires a non-empty array of method names to create spies for";
182
+ }
183
+ var obj = {};
184
+ for (var i = 0; i < methodNames.length; i++) {
185
+ obj[methodNames[i]] = j$.createSpy(baseName + '.' + methodNames[i]);
186
+ }
187
+ return obj;
188
+ };
189
+ };
190
+
191
+ getJasmineRequireObj().util = function() {
192
+
193
+ var util = {};
194
+
195
+ util.inherit = function(childClass, parentClass) {
196
+ var Subclass = function() {
197
+ };
198
+ Subclass.prototype = parentClass.prototype;
199
+ childClass.prototype = new Subclass();
200
+ };
201
+
202
+ util.htmlEscape = function(str) {
203
+ if (!str) {
204
+ return str;
205
+ }
206
+ return str.replace(/&/g, '&amp;')
207
+ .replace(/</g, '&lt;')
208
+ .replace(/>/g, '&gt;');
209
+ };
210
+
211
+ util.argsToArray = function(args) {
212
+ var arrayOfArgs = [];
213
+ for (var i = 0; i < args.length; i++) {
214
+ arrayOfArgs.push(args[i]);
215
+ }
216
+ return arrayOfArgs;
217
+ };
218
+
219
+ util.isUndefined = function(obj) {
220
+ return obj === void 0;
221
+ };
222
+
223
+ return util;
224
+ };
225
+
226
+ getJasmineRequireObj().Spec = function(j$) {
227
+ function Spec(attrs) {
228
+ this.expectationFactory = attrs.expectationFactory;
229
+ this.resultCallback = attrs.resultCallback || function() {};
230
+ this.id = attrs.id;
231
+ this.description = attrs.description || '';
232
+ this.fn = attrs.fn;
233
+ this.beforeFns = attrs.beforeFns || function() { return []; };
234
+ this.afterFns = attrs.afterFns || function() { return []; };
235
+ this.onStart = attrs.onStart || function() {};
236
+ this.exceptionFormatter = attrs.exceptionFormatter || function() {};
237
+ this.getSpecName = attrs.getSpecName || function() { return ''; };
238
+ this.expectationResultFactory = attrs.expectationResultFactory || function() { };
239
+ this.queueRunnerFactory = attrs.queueRunnerFactory || function() {};
240
+ this.catchingExceptions = attrs.catchingExceptions || function() { return true; };
241
+
242
+ this.timer = attrs.timer || {setTimeout: setTimeout, clearTimeout: clearTimeout};
243
+
244
+ if (!this.fn) {
245
+ this.pend();
246
+ }
247
+
248
+ this.result = {
249
+ id: this.id,
250
+ description: this.description,
251
+ fullName: this.getFullName(),
252
+ failedExpectations: []
253
+ };
254
+ }
255
+
256
+ Spec.prototype.addExpectationResult = function(passed, data) {
257
+ if (passed) {
258
+ return;
259
+ }
260
+ this.result.failedExpectations.push(this.expectationResultFactory(data));
261
+ };
262
+
263
+ Spec.prototype.expect = function(actual) {
264
+ return this.expectationFactory(actual, this);
265
+ };
266
+
267
+ Spec.prototype.execute = function(onComplete) {
268
+ var self = this,
269
+ timeout;
270
+
271
+ this.onStart(this);
272
+
273
+ if (this.markedPending || this.disabled) {
274
+ complete();
275
+ return;
276
+ }
277
+
278
+ function timeoutable(fn) {
279
+ return function(done) {
280
+ timeout = Function.prototype.apply.apply(self.timer.setTimeout, [j$.getGlobal(), [function() {
281
+ onException(new Error('Timeout - Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL.'));
282
+ done();
283
+ }, j$.DEFAULT_TIMEOUT_INTERVAL]]);
284
+
285
+ var callDone = function() {
286
+ clearTimeoutable();
287
+ done();
288
+ };
289
+
290
+ fn.call(this, callDone); //TODO: do we care about more than 1 arg?
291
+ };
292
+ }
293
+
294
+ function clearTimeoutable() {
295
+ Function.prototype.apply.apply(self.timer.clearTimeout, [j$.getGlobal(), [timeout]]);
296
+ timeout = void 0;
297
+ }
298
+
299
+ var allFns = this.beforeFns().concat(this.fn).concat(this.afterFns()),
300
+ allTimeoutableFns = [];
301
+ for (var i = 0; i < allFns.length; i++) {
302
+ var fn = allFns[i];
303
+ allTimeoutableFns.push(fn.length > 0 ? timeoutable(fn) : fn);
304
+ }
305
+
306
+ this.queueRunnerFactory({
307
+ fns: allTimeoutableFns,
308
+ onException: onException,
309
+ onComplete: complete
310
+ });
311
+
312
+ function onException(e) {
313
+ clearTimeoutable();
314
+ if (Spec.isPendingSpecException(e)) {
315
+ self.pend();
316
+ return;
317
+ }
318
+
319
+ self.addExpectationResult(false, {
320
+ matcherName: "",
321
+ passed: false,
322
+ expected: "",
323
+ actual: "",
324
+ error: e
325
+ });
326
+ }
327
+
328
+ function complete() {
329
+ self.result.status = self.status();
330
+ self.resultCallback(self.result);
331
+
332
+ if (onComplete) {
333
+ onComplete();
334
+ }
335
+ }
336
+ };
337
+
338
+ Spec.prototype.disable = function() {
339
+ this.disabled = true;
340
+ };
341
+
342
+ Spec.prototype.pend = function() {
343
+ this.markedPending = true;
344
+ };
345
+
346
+ Spec.prototype.status = function() {
347
+ if (this.disabled) {
348
+ return 'disabled';
349
+ }
350
+
351
+ if (this.markedPending) {
352
+ return 'pending';
353
+ }
354
+
355
+ if (this.result.failedExpectations.length > 0) {
356
+ return 'failed';
357
+ } else {
358
+ return 'passed';
359
+ }
360
+ };
361
+
362
+ Spec.prototype.getFullName = function() {
363
+ return this.getSpecName(this);
364
+ };
365
+
366
+ Spec.pendingSpecExceptionMessage = "=> marked Pending";
367
+
368
+ Spec.isPendingSpecException = function(e) {
369
+ return !!(e && e.toString && e.toString().indexOf(Spec.pendingSpecExceptionMessage) !== -1);
370
+ };
371
+
372
+ return Spec;
373
+ };
374
+
375
+ if (typeof window == void 0 && typeof exports == "object") {
376
+ exports.Spec = jasmineRequire.Spec;
377
+ }
378
+
379
+ getJasmineRequireObj().Env = function(j$) {
380
+ function Env(options) {
381
+ options = options || {};
382
+
383
+ var self = this;
384
+ var global = options.global || j$.getGlobal();
385
+
386
+ var totalSpecsDefined = 0;
387
+
388
+ var catchExceptions = true;
389
+
390
+ var realSetTimeout = j$.getGlobal().setTimeout;
391
+ var realClearTimeout = j$.getGlobal().clearTimeout;
392
+ this.clock = new j$.Clock(global, new j$.DelayedFunctionScheduler());
393
+
394
+ var runnableLookupTable = {};
395
+
396
+ var spies = [];
397
+
398
+ var currentSpec = null;
399
+ var currentSuite = null;
400
+
401
+ var reporter = new j$.ReportDispatcher([
402
+ "jasmineStarted",
403
+ "jasmineDone",
404
+ "suiteStarted",
405
+ "suiteDone",
406
+ "specStarted",
407
+ "specDone"
408
+ ]);
409
+
410
+ this.specFilter = function() {
411
+ return true;
412
+ };
413
+
414
+ var equalityTesters = [];
415
+
416
+ var customEqualityTesters = [];
417
+ this.addCustomEqualityTester = function(tester) {
418
+ customEqualityTesters.push(tester);
419
+ };
420
+
421
+ j$.Expectation.addCoreMatchers(j$.matchers);
422
+
423
+ var nextSpecId = 0;
424
+ var getNextSpecId = function() {
425
+ return 'spec' + nextSpecId++;
426
+ };
427
+
428
+ var nextSuiteId = 0;
429
+ var getNextSuiteId = function() {
430
+ return 'suite' + nextSuiteId++;
431
+ };
432
+
433
+ var expectationFactory = function(actual, spec) {
434
+ return j$.Expectation.Factory({
435
+ util: j$.matchersUtil,
436
+ customEqualityTesters: customEqualityTesters,
437
+ actual: actual,
438
+ addExpectationResult: addExpectationResult
439
+ });
440
+
441
+ function addExpectationResult(passed, result) {
442
+ return spec.addExpectationResult(passed, result);
443
+ }
444
+ };
445
+
446
+ var specStarted = function(spec) {
447
+ currentSpec = spec;
448
+ reporter.specStarted(spec.result);
449
+ };
450
+
451
+ var beforeFns = function(suite) {
452
+ return function() {
453
+ var befores = [];
454
+ while(suite) {
455
+ befores = befores.concat(suite.beforeFns);
456
+ suite = suite.parentSuite;
457
+ }
458
+ return befores.reverse();
459
+ };
460
+ };
461
+
462
+ var afterFns = function(suite) {
463
+ return function() {
464
+ var afters = [];
465
+ while(suite) {
466
+ afters = afters.concat(suite.afterFns);
467
+ suite = suite.parentSuite;
468
+ }
469
+ return afters;
470
+ };
471
+ };
472
+
473
+ var getSpecName = function(spec, suite) {
474
+ return suite.getFullName() + ' ' + spec.description;
475
+ };
476
+
477
+ // TODO: we may just be able to pass in the fn instead of wrapping here
478
+ var buildExpectationResult = j$.buildExpectationResult,
479
+ exceptionFormatter = new j$.ExceptionFormatter(),
480
+ expectationResultFactory = function(attrs) {
481
+ attrs.messageFormatter = exceptionFormatter.message;
482
+ attrs.stackFormatter = exceptionFormatter.stack;
483
+
484
+ return buildExpectationResult(attrs);
485
+ };
486
+
487
+ // TODO: fix this naming, and here's where the value comes in
488
+ this.catchExceptions = function(value) {
489
+ catchExceptions = !!value;
490
+ return catchExceptions;
491
+ };
492
+
493
+ this.catchingExceptions = function() {
494
+ return catchExceptions;
495
+ };
496
+
497
+ var maximumSpecCallbackDepth = 20;
498
+ var currentSpecCallbackDepth = 0;
499
+
500
+ function clearStack(fn) {
501
+ currentSpecCallbackDepth++;
502
+ if (currentSpecCallbackDepth >= maximumSpecCallbackDepth) {
503
+ currentSpecCallbackDepth = 0;
504
+ realSetTimeout(fn, 0);
505
+ } else {
506
+ fn();
507
+ }
508
+ }
509
+
510
+ var catchException = function(e) {
511
+ return j$.Spec.isPendingSpecException(e) || catchExceptions;
512
+ };
513
+
514
+ var queueRunnerFactory = function(options) {
515
+ options.catchException = catchException;
516
+ options.clearStack = options.clearStack || clearStack;
517
+
518
+ new j$.QueueRunner(options).execute();
519
+ };
520
+
521
+ var topSuite = new j$.Suite({
522
+ env: this,
523
+ id: getNextSuiteId(),
524
+ description: 'Jasmine__TopLevel__Suite',
525
+ queueRunner: queueRunnerFactory,
526
+ resultCallback: function() {} // TODO - hook this up
527
+ });
528
+ runnableLookupTable[topSuite.id] = topSuite;
529
+ currentSuite = topSuite;
530
+
531
+ this.topSuite = function() {
532
+ return topSuite;
533
+ };
534
+
535
+ this.execute = function(runnablesToRun) {
536
+ runnablesToRun = runnablesToRun || [topSuite.id];
537
+
538
+ var allFns = [];
539
+ for(var i = 0; i < runnablesToRun.length; i++) {
540
+ var runnable = runnableLookupTable[runnablesToRun[i]];
541
+ allFns.push((function(runnable) { return function(done) { runnable.execute(done); }; })(runnable));
542
+ }
543
+
544
+ reporter.jasmineStarted({
545
+ totalSpecsDefined: totalSpecsDefined
546
+ });
547
+
548
+ queueRunnerFactory({fns: allFns, onComplete: reporter.jasmineDone});
549
+ };
550
+
551
+ this.addReporter = function(reporterToAdd) {
552
+ reporter.addReporter(reporterToAdd);
553
+ };
554
+
555
+ this.addMatchers = function(matchersToAdd) {
556
+ j$.Expectation.addMatchers(matchersToAdd);
557
+ };
558
+
559
+ this.spyOn = function(obj, methodName) {
560
+ if (j$.util.isUndefined(obj)) {
561
+ throw new Error("spyOn could not find an object to spy upon for " + methodName + "()");
562
+ }
563
+
564
+ if (j$.util.isUndefined(obj[methodName])) {
565
+ throw new Error(methodName + '() method does not exist');
566
+ }
567
+
568
+ if (obj[methodName] && j$.isSpy(obj[methodName])) {
569
+ //TODO?: should this return the current spy? Downside: may cause user confusion about spy state
570
+ throw new Error(methodName + ' has already been spied upon');
571
+ }
572
+
573
+ var spy = j$.createSpy(methodName, obj[methodName]);
574
+
575
+ spies.push({
576
+ spy: spy,
577
+ baseObj: obj,
578
+ methodName: methodName,
579
+ originalValue: obj[methodName]
580
+ });
581
+
582
+ obj[methodName] = spy;
583
+
584
+ return spy;
585
+ };
586
+
587
+ var suiteFactory = function(description) {
588
+ var suite = new j$.Suite({
589
+ env: self,
590
+ id: getNextSuiteId(),
591
+ description: description,
592
+ parentSuite: currentSuite,
593
+ queueRunner: queueRunnerFactory,
594
+ onStart: suiteStarted,
595
+ resultCallback: function(attrs) {
596
+ reporter.suiteDone(attrs);
597
+ }
598
+ });
599
+
600
+ runnableLookupTable[suite.id] = suite;
601
+ return suite;
602
+ };
603
+
604
+ this.describe = function(description, specDefinitions) {
605
+ var suite = suiteFactory(description);
606
+
607
+ var parentSuite = currentSuite;
608
+ parentSuite.addChild(suite);
609
+ currentSuite = suite;
610
+
611
+ var declarationError = null;
612
+ try {
613
+ specDefinitions.call(suite);
614
+ } catch (e) {
615
+ declarationError = e;
616
+ }
617
+
618
+ if (declarationError) {
619
+ this.it("encountered a declaration exception", function() {
620
+ throw declarationError;
621
+ });
622
+ }
623
+
624
+ currentSuite = parentSuite;
625
+
626
+ return suite;
627
+ };
628
+
629
+ this.xdescribe = function(description, specDefinitions) {
630
+ var suite = this.describe(description, specDefinitions);
631
+ suite.disable();
632
+ return suite;
633
+ };
634
+
635
+ var specFactory = function(description, fn, suite) {
636
+ totalSpecsDefined++;
637
+
638
+ var spec = new j$.Spec({
639
+ id: getNextSpecId(),
640
+ beforeFns: beforeFns(suite),
641
+ afterFns: afterFns(suite),
642
+ expectationFactory: expectationFactory,
643
+ exceptionFormatter: exceptionFormatter,
644
+ resultCallback: specResultCallback,
645
+ getSpecName: function(spec) {
646
+ return getSpecName(spec, suite);
647
+ },
648
+ onStart: specStarted,
649
+ description: description,
650
+ expectationResultFactory: expectationResultFactory,
651
+ queueRunnerFactory: queueRunnerFactory,
652
+ fn: fn,
653
+ timer: {setTimeout: realSetTimeout, clearTimeout: realClearTimeout}
654
+ });
655
+
656
+ runnableLookupTable[spec.id] = spec;
657
+
658
+ if (!self.specFilter(spec)) {
659
+ spec.disable();
660
+ }
661
+
662
+ return spec;
663
+
664
+ function removeAllSpies() {
665
+ for (var i = 0; i < spies.length; i++) {
666
+ var spyEntry = spies[i];
667
+ spyEntry.baseObj[spyEntry.methodName] = spyEntry.originalValue;
668
+ }
669
+ spies = [];
670
+ }
671
+
672
+ function specResultCallback(result) {
673
+ removeAllSpies();
674
+ j$.Expectation.resetMatchers();
675
+ customEqualityTesters = [];
676
+ currentSpec = null;
677
+ reporter.specDone(result);
678
+ }
679
+ };
680
+
681
+ var suiteStarted = function(suite) {
682
+ reporter.suiteStarted(suite.result);
683
+ };
684
+
685
+ this.it = function(description, fn) {
686
+ var spec = specFactory(description, fn, currentSuite);
687
+ currentSuite.addChild(spec);
688
+ return spec;
689
+ };
690
+
691
+ this.xit = function(description, fn) {
692
+ var spec = this.it(description, fn);
693
+ spec.pend();
694
+ return spec;
695
+ };
696
+
697
+ this.expect = function(actual) {
698
+ return currentSpec.expect(actual);
699
+ };
700
+
701
+ this.beforeEach = function(beforeEachFunction) {
702
+ currentSuite.beforeEach(beforeEachFunction);
703
+ };
704
+
705
+ this.afterEach = function(afterEachFunction) {
706
+ currentSuite.afterEach(afterEachFunction);
707
+ };
708
+
709
+ this.pending = function() {
710
+ throw j$.Spec.pendingSpecExceptionMessage;
711
+ };
712
+ }
713
+
714
+ return Env;
715
+ };
716
+
717
+ getJasmineRequireObj().JsApiReporter = function() {
718
+
719
+ var noopTimer = {
720
+ start: function(){},
721
+ elapsed: function(){ return 0; }
722
+ };
723
+
724
+ function JsApiReporter(options) {
725
+ var timer = options.timer || noopTimer,
726
+ status = "loaded";
727
+
728
+ this.started = false;
729
+ this.finished = false;
730
+
731
+ this.jasmineStarted = function() {
732
+ this.started = true;
733
+ status = 'started';
734
+ timer.start();
735
+ };
736
+
737
+ var executionTime;
738
+
739
+ this.jasmineDone = function() {
740
+ this.finished = true;
741
+ executionTime = timer.elapsed();
742
+ status = 'done';
743
+ };
744
+
745
+ this.status = function() {
746
+ return status;
747
+ };
748
+
749
+ var suites = {};
750
+
751
+ this.suiteStarted = function(result) {
752
+ storeSuite(result);
753
+ };
754
+
755
+ this.suiteDone = function(result) {
756
+ storeSuite(result);
757
+ };
758
+
759
+ function storeSuite(result) {
760
+ suites[result.id] = result;
761
+ }
762
+
763
+ this.suites = function() {
764
+ return suites;
765
+ };
766
+
767
+ var specs = [];
768
+ this.specStarted = function(result) { };
769
+
770
+ this.specDone = function(result) {
771
+ specs.push(result);
772
+ };
773
+
774
+ this.specResults = function(index, length) {
775
+ return specs.slice(index, index + length);
776
+ };
777
+
778
+ this.specs = function() {
779
+ return specs;
780
+ };
781
+
782
+ this.executionTime = function() {
783
+ return executionTime;
784
+ };
785
+
786
+ }
787
+
788
+ return JsApiReporter;
789
+ };
790
+
791
+ getJasmineRequireObj().Any = function() {
792
+
793
+ function Any(expectedObject) {
794
+ this.expectedObject = expectedObject;
795
+ }
796
+
797
+ Any.prototype.jasmineMatches = function(other) {
798
+ if (this.expectedObject == String) {
799
+ return typeof other == 'string' || other instanceof String;
800
+ }
801
+
802
+ if (this.expectedObject == Number) {
803
+ return typeof other == 'number' || other instanceof Number;
804
+ }
805
+
806
+ if (this.expectedObject == Function) {
807
+ return typeof other == 'function' || other instanceof Function;
808
+ }
809
+
810
+ if (this.expectedObject == Object) {
811
+ return typeof other == 'object';
812
+ }
813
+
814
+ if (this.expectedObject == Boolean) {
815
+ return typeof other == 'boolean';
816
+ }
817
+
818
+ return other instanceof this.expectedObject;
819
+ };
820
+
821
+ Any.prototype.jasmineToString = function() {
822
+ return '<jasmine.any(' + this.expectedObject + ')>';
823
+ };
824
+
825
+ return Any;
826
+ };
827
+
828
+ getJasmineRequireObj().CallTracker = function() {
829
+
830
+ function CallTracker() {
831
+ var calls = [];
832
+
833
+ this.track = function(context) {
834
+ calls.push(context);
835
+ };
836
+
837
+ this.any = function() {
838
+ return !!calls.length;
839
+ };
840
+
841
+ this.count = function() {
842
+ return calls.length;
843
+ };
844
+
845
+ this.argsFor = function(index) {
846
+ var call = calls[index];
847
+ return call ? call.args : [];
848
+ };
849
+
850
+ this.all = function() {
851
+ return calls;
852
+ };
853
+
854
+ this.allArgs = function() {
855
+ var callArgs = [];
856
+ for(var i = 0; i < calls.length; i++){
857
+ callArgs.push(calls[i].args);
858
+ }
859
+
860
+ return callArgs;
861
+ };
862
+
863
+ this.first = function() {
864
+ return calls[0];
865
+ };
866
+
867
+ this.mostRecent = function() {
868
+ return calls[calls.length - 1];
869
+ };
870
+
871
+ this.reset = function() {
872
+ calls = [];
873
+ };
874
+ }
875
+
876
+ return CallTracker;
877
+ };
878
+
879
+ getJasmineRequireObj().Clock = function() {
880
+ function Clock(global, delayedFunctionScheduler) {
881
+ var self = this,
882
+ realTimingFunctions = {
883
+ setTimeout: global.setTimeout,
884
+ clearTimeout: global.clearTimeout,
885
+ setInterval: global.setInterval,
886
+ clearInterval: global.clearInterval
887
+ },
888
+ fakeTimingFunctions = {
889
+ setTimeout: setTimeout,
890
+ clearTimeout: clearTimeout,
891
+ setInterval: setInterval,
892
+ clearInterval: clearInterval
893
+ },
894
+ installed = false,
895
+ timer;
896
+
897
+ self.install = function() {
898
+ replace(global, fakeTimingFunctions);
899
+ timer = fakeTimingFunctions;
900
+ installed = true;
901
+ };
902
+
903
+ self.uninstall = function() {
904
+ delayedFunctionScheduler.reset();
905
+ replace(global, realTimingFunctions);
906
+ timer = realTimingFunctions;
907
+ installed = false;
908
+ };
909
+
910
+ self.setTimeout = function(fn, delay, params) {
911
+ if (legacyIE()) {
912
+ if (arguments.length > 2) {
913
+ throw new Error("IE < 9 cannot support extra params to setTimeout without a polyfill");
914
+ }
915
+ return timer.setTimeout(fn, delay);
916
+ }
917
+ return Function.prototype.apply.apply(timer.setTimeout, [global, arguments]);
918
+ };
919
+
920
+ self.setInterval = function(fn, delay, params) {
921
+ if (legacyIE()) {
922
+ if (arguments.length > 2) {
923
+ throw new Error("IE < 9 cannot support extra params to setInterval without a polyfill");
924
+ }
925
+ return timer.setInterval(fn, delay);
926
+ }
927
+ return Function.prototype.apply.apply(timer.setInterval, [global, arguments]);
928
+ };
929
+
930
+ self.clearTimeout = function(id) {
931
+ return Function.prototype.call.apply(timer.clearTimeout, [global, id]);
932
+ };
933
+
934
+ self.clearInterval = function(id) {
935
+ return Function.prototype.call.apply(timer.clearInterval, [global, id]);
936
+ };
937
+
938
+ self.tick = function(millis) {
939
+ if (installed) {
940
+ delayedFunctionScheduler.tick(millis);
941
+ } else {
942
+ throw new Error("Mock clock is not installed, use jasmine.clock().install()");
943
+ }
944
+ };
945
+
946
+ return self;
947
+
948
+ function legacyIE() {
949
+ //if these methods are polyfilled, apply will be present
950
+ return !(realTimingFunctions.setTimeout || realTimingFunctions.setInterval).apply;
951
+ }
952
+
953
+ function replace(dest, source) {
954
+ for (var prop in source) {
955
+ dest[prop] = source[prop];
956
+ }
957
+ }
958
+
959
+ function setTimeout(fn, delay) {
960
+ return delayedFunctionScheduler.scheduleFunction(fn, delay, argSlice(arguments, 2));
961
+ }
962
+
963
+ function clearTimeout(id) {
964
+ return delayedFunctionScheduler.removeFunctionWithId(id);
965
+ }
966
+
967
+ function setInterval(fn, interval) {
968
+ return delayedFunctionScheduler.scheduleFunction(fn, interval, argSlice(arguments, 2), true);
969
+ }
970
+
971
+ function clearInterval(id) {
972
+ return delayedFunctionScheduler.removeFunctionWithId(id);
973
+ }
974
+
975
+ function argSlice(argsObj, n) {
976
+ return Array.prototype.slice.call(argsObj, 2);
977
+ }
978
+ }
979
+
980
+ return Clock;
981
+ };
982
+
983
+ getJasmineRequireObj().DelayedFunctionScheduler = function() {
984
+ function DelayedFunctionScheduler() {
985
+ var self = this;
986
+ var scheduledLookup = [];
987
+ var scheduledFunctions = {};
988
+ var currentTime = 0;
989
+ var delayedFnCount = 0;
990
+
991
+ self.tick = function(millis) {
992
+ millis = millis || 0;
993
+ var endTime = currentTime + millis;
994
+
995
+ runScheduledFunctions(endTime);
996
+ currentTime = endTime;
997
+ };
998
+
999
+ self.scheduleFunction = function(funcToCall, millis, params, recurring, timeoutKey, runAtMillis) {
1000
+ var f;
1001
+ if (typeof(funcToCall) === 'string') {
1002
+ /* jshint evil: true */
1003
+ f = function() { return eval(funcToCall); };
1004
+ /* jshint evil: false */
1005
+ } else {
1006
+ f = funcToCall;
1007
+ }
1008
+
1009
+ millis = millis || 0;
1010
+ timeoutKey = timeoutKey || ++delayedFnCount;
1011
+ runAtMillis = runAtMillis || (currentTime + millis);
1012
+
1013
+ var funcToSchedule = {
1014
+ runAtMillis: runAtMillis,
1015
+ funcToCall: f,
1016
+ recurring: recurring,
1017
+ params: params,
1018
+ timeoutKey: timeoutKey,
1019
+ millis: millis
1020
+ };
1021
+
1022
+ if (runAtMillis in scheduledFunctions) {
1023
+ scheduledFunctions[runAtMillis].push(funcToSchedule);
1024
+ } else {
1025
+ scheduledFunctions[runAtMillis] = [funcToSchedule];
1026
+ scheduledLookup.push(runAtMillis);
1027
+ scheduledLookup.sort(function (a, b) {
1028
+ return a - b;
1029
+ });
1030
+ }
1031
+
1032
+ return timeoutKey;
1033
+ };
1034
+
1035
+ self.removeFunctionWithId = function(timeoutKey) {
1036
+ for (var runAtMillis in scheduledFunctions) {
1037
+ var funcs = scheduledFunctions[runAtMillis];
1038
+ var i = indexOfFirstToPass(funcs, function (func) {
1039
+ return func.timeoutKey === timeoutKey;
1040
+ });
1041
+
1042
+ if (i > -1) {
1043
+ if (funcs.length === 1) {
1044
+ delete scheduledFunctions[runAtMillis];
1045
+ deleteFromLookup(runAtMillis);
1046
+ } else {
1047
+ funcs.splice(i, 1);
1048
+ }
1049
+
1050
+ // intervals get rescheduled when executed, so there's never more
1051
+ // than a single scheduled function with a given timeoutKey
1052
+ break;
1053
+ }
1054
+ }
1055
+ };
1056
+
1057
+ self.reset = function() {
1058
+ currentTime = 0;
1059
+ scheduledLookup = [];
1060
+ scheduledFunctions = {};
1061
+ delayedFnCount = 0;
1062
+ };
1063
+
1064
+ return self;
1065
+
1066
+ function indexOfFirstToPass(array, testFn) {
1067
+ var index = -1;
1068
+
1069
+ for (var i = 0; i < array.length; ++i) {
1070
+ if (testFn(array[i])) {
1071
+ index = i;
1072
+ break;
1073
+ }
1074
+ }
1075
+
1076
+ return index;
1077
+ }
1078
+
1079
+ function deleteFromLookup(key) {
1080
+ var value = Number(key);
1081
+ var i = indexOfFirstToPass(scheduledLookup, function (millis) {
1082
+ return millis === value;
1083
+ });
1084
+
1085
+ if (i > -1) {
1086
+ scheduledLookup.splice(i, 1);
1087
+ }
1088
+ }
1089
+
1090
+ function reschedule(scheduledFn) {
1091
+ self.scheduleFunction(scheduledFn.funcToCall,
1092
+ scheduledFn.millis,
1093
+ scheduledFn.params,
1094
+ true,
1095
+ scheduledFn.timeoutKey,
1096
+ scheduledFn.runAtMillis + scheduledFn.millis);
1097
+ }
1098
+
1099
+ function runScheduledFunctions(endTime) {
1100
+ if (scheduledLookup.length === 0 || scheduledLookup[0] > endTime) {
1101
+ return;
1102
+ }
1103
+
1104
+ do {
1105
+ currentTime = scheduledLookup.shift();
1106
+
1107
+ var funcsToRun = scheduledFunctions[currentTime];
1108
+ delete scheduledFunctions[currentTime];
1109
+
1110
+ for (var i = 0; i < funcsToRun.length; ++i) {
1111
+ var funcToRun = funcsToRun[i];
1112
+ funcToRun.funcToCall.apply(null, funcToRun.params || []);
1113
+
1114
+ if (funcToRun.recurring) {
1115
+ reschedule(funcToRun);
1116
+ }
1117
+ }
1118
+ } while (scheduledLookup.length > 0 &&
1119
+ // checking first if we're out of time prevents setTimeout(0)
1120
+ // scheduled in a funcToRun from forcing an extra iteration
1121
+ currentTime !== endTime &&
1122
+ scheduledLookup[0] <= endTime);
1123
+ }
1124
+ }
1125
+
1126
+ return DelayedFunctionScheduler;
1127
+ };
1128
+
1129
+ getJasmineRequireObj().ExceptionFormatter = function() {
1130
+ function ExceptionFormatter() {
1131
+ this.message = function(error) {
1132
+ var message = '';
1133
+
1134
+ if (error.name && error.message) {
1135
+ message += error.name + ': ' + error.message;
1136
+ } else {
1137
+ message += error.toString() + ' thrown';
1138
+ }
1139
+
1140
+ if (error.fileName || error.sourceURL) {
1141
+ message += " in " + (error.fileName || error.sourceURL);
1142
+ }
1143
+
1144
+ if (error.line || error.lineNumber) {
1145
+ message += " (line " + (error.line || error.lineNumber) + ")";
1146
+ }
1147
+
1148
+ return message;
1149
+ };
1150
+
1151
+ this.stack = function(error) {
1152
+ return error ? error.stack : null;
1153
+ };
1154
+ }
1155
+
1156
+ return ExceptionFormatter;
1157
+ };
1158
+
1159
+ getJasmineRequireObj().Expectation = function() {
1160
+
1161
+ var matchers = {};
1162
+
1163
+ function Expectation(options) {
1164
+ this.util = options.util || { buildFailureMessage: function() {} };
1165
+ this.customEqualityTesters = options.customEqualityTesters || [];
1166
+ this.actual = options.actual;
1167
+ this.addExpectationResult = options.addExpectationResult || function(){};
1168
+ this.isNot = options.isNot;
1169
+
1170
+ for (var matcherName in matchers) {
1171
+ this[matcherName] = matchers[matcherName];
1172
+ }
1173
+ }
1174
+
1175
+ Expectation.prototype.wrapCompare = function(name, matcherFactory) {
1176
+ return function() {
1177
+ var args = Array.prototype.slice.call(arguments, 0),
1178
+ expected = args.slice(0),
1179
+ message = "";
1180
+
1181
+ args.unshift(this.actual);
1182
+
1183
+ var matcher = matcherFactory(this.util, this.customEqualityTesters),
1184
+ matcherCompare = matcher.compare;
1185
+
1186
+ function defaultNegativeCompare() {
1187
+ var result = matcher.compare.apply(null, args);
1188
+ result.pass = !result.pass;
1189
+ return result;
1190
+ }
1191
+
1192
+ if (this.isNot) {
1193
+ matcherCompare = matcher.negativeCompare || defaultNegativeCompare;
1194
+ }
1195
+
1196
+ var result = matcherCompare.apply(null, args);
1197
+
1198
+ if (!result.pass) {
1199
+ if (!result.message) {
1200
+ args.unshift(this.isNot);
1201
+ args.unshift(name);
1202
+ message = this.util.buildFailureMessage.apply(null, args);
1203
+ } else {
1204
+ message = result.message;
1205
+ }
1206
+ }
1207
+
1208
+ if (expected.length == 1) {
1209
+ expected = expected[0];
1210
+ }
1211
+
1212
+ // TODO: how many of these params are needed?
1213
+ this.addExpectationResult(
1214
+ result.pass,
1215
+ {
1216
+ matcherName: name,
1217
+ passed: result.pass,
1218
+ message: message,
1219
+ actual: this.actual,
1220
+ expected: expected // TODO: this may need to be arrayified/sliced
1221
+ }
1222
+ );
1223
+ };
1224
+ };
1225
+
1226
+ Expectation.addCoreMatchers = function(matchers) {
1227
+ var prototype = Expectation.prototype;
1228
+ for (var matcherName in matchers) {
1229
+ var matcher = matchers[matcherName];
1230
+ prototype[matcherName] = prototype.wrapCompare(matcherName, matcher);
1231
+ }
1232
+ };
1233
+
1234
+ Expectation.addMatchers = function(matchersToAdd) {
1235
+ for (var name in matchersToAdd) {
1236
+ var matcher = matchersToAdd[name];
1237
+ matchers[name] = Expectation.prototype.wrapCompare(name, matcher);
1238
+ }
1239
+ };
1240
+
1241
+ Expectation.resetMatchers = function() {
1242
+ for (var name in matchers) {
1243
+ delete matchers[name];
1244
+ }
1245
+ };
1246
+
1247
+ Expectation.Factory = function(options) {
1248
+ options = options || {};
1249
+
1250
+ var expect = new Expectation(options);
1251
+
1252
+ // TODO: this would be nice as its own Object - NegativeExpectation
1253
+ // TODO: copy instead of mutate options
1254
+ options.isNot = true;
1255
+ expect.not = new Expectation(options);
1256
+
1257
+ return expect;
1258
+ };
1259
+
1260
+ return Expectation;
1261
+ };
1262
+
1263
+ //TODO: expectation result may make more sense as a presentation of an expectation.
1264
+ getJasmineRequireObj().buildExpectationResult = function() {
1265
+ function buildExpectationResult(options) {
1266
+ var messageFormatter = options.messageFormatter || function() {},
1267
+ stackFormatter = options.stackFormatter || function() {};
1268
+
1269
+ return {
1270
+ matcherName: options.matcherName,
1271
+ expected: options.expected,
1272
+ actual: options.actual,
1273
+ message: message(),
1274
+ stack: stack(),
1275
+ passed: options.passed
1276
+ };
1277
+
1278
+ function message() {
1279
+ if (options.passed) {
1280
+ return "Passed.";
1281
+ } else if (options.message) {
1282
+ return options.message;
1283
+ } else if (options.error) {
1284
+ return messageFormatter(options.error);
1285
+ }
1286
+ return "";
1287
+ }
1288
+
1289
+ function stack() {
1290
+ if (options.passed) {
1291
+ return "";
1292
+ }
1293
+
1294
+ var error = options.error;
1295
+ if (!error) {
1296
+ try {
1297
+ throw new Error(message());
1298
+ } catch (e) {
1299
+ error = e;
1300
+ }
1301
+ }
1302
+ return stackFormatter(error);
1303
+ }
1304
+ }
1305
+
1306
+ return buildExpectationResult;
1307
+ };
1308
+
1309
+ getJasmineRequireObj().ObjectContaining = function(j$) {
1310
+
1311
+ function ObjectContaining(sample) {
1312
+ this.sample = sample;
1313
+ }
1314
+
1315
+ ObjectContaining.prototype.jasmineMatches = function(other, mismatchKeys, mismatchValues) {
1316
+ if (typeof(this.sample) !== "object") { throw new Error("You must provide an object to objectContaining, not '"+this.sample+"'."); }
1317
+
1318
+ mismatchKeys = mismatchKeys || [];
1319
+ mismatchValues = mismatchValues || [];
1320
+
1321
+ var hasKey = function(obj, keyName) {
1322
+ return obj !== null && !j$.util.isUndefined(obj[keyName]);
1323
+ };
1324
+
1325
+ for (var property in this.sample) {
1326
+ if (!hasKey(other, property) && hasKey(this.sample, property)) {
1327
+ mismatchKeys.push("expected has key '" + property + "', but missing from actual.");
1328
+ }
1329
+ else if (!j$.matchersUtil.equals(this.sample[property], other[property])) {
1330
+ mismatchValues.push("'" + property + "' was '" + (other[property] ? j$.util.htmlEscape(other[property].toString()) : other[property]) + "' in actual, but was '" + (this.sample[property] ? j$.util.htmlEscape(this.sample[property].toString()) : this.sample[property]) + "' in expected.");
1331
+ }
1332
+ }
1333
+
1334
+ return (mismatchKeys.length === 0 && mismatchValues.length === 0);
1335
+ };
1336
+
1337
+ ObjectContaining.prototype.jasmineToString = function() {
1338
+ return "<jasmine.objectContaining(" + j$.pp(this.sample) + ")>";
1339
+ };
1340
+
1341
+ return ObjectContaining;
1342
+ };
1343
+
1344
+ getJasmineRequireObj().pp = function(j$) {
1345
+
1346
+ function PrettyPrinter() {
1347
+ this.ppNestLevel_ = 0;
1348
+ }
1349
+
1350
+ PrettyPrinter.prototype.format = function(value) {
1351
+ this.ppNestLevel_++;
1352
+ try {
1353
+ if (j$.util.isUndefined(value)) {
1354
+ this.emitScalar('undefined');
1355
+ } else if (value === null) {
1356
+ this.emitScalar('null');
1357
+ } else if (value === 0 && 1/value === -Infinity) {
1358
+ this.emitScalar('-0');
1359
+ } else if (value === j$.getGlobal()) {
1360
+ this.emitScalar('<global>');
1361
+ } else if (value.jasmineToString) {
1362
+ this.emitScalar(value.jasmineToString());
1363
+ } else if (typeof value === 'string') {
1364
+ this.emitString(value);
1365
+ } else if (j$.isSpy(value)) {
1366
+ this.emitScalar("spy on " + value.and.identity());
1367
+ } else if (value instanceof RegExp) {
1368
+ this.emitScalar(value.toString());
1369
+ } else if (typeof value === 'function') {
1370
+ this.emitScalar('Function');
1371
+ } else if (typeof value.nodeType === 'number') {
1372
+ this.emitScalar('HTMLNode');
1373
+ } else if (value instanceof Date) {
1374
+ this.emitScalar('Date(' + value + ')');
1375
+ } else if (value.__Jasmine_been_here_before__) {
1376
+ this.emitScalar('<circular reference: ' + (j$.isArray_(value) ? 'Array' : 'Object') + '>');
1377
+ } else if (j$.isArray_(value) || j$.isA_('Object', value)) {
1378
+ value.__Jasmine_been_here_before__ = true;
1379
+ if (j$.isArray_(value)) {
1380
+ this.emitArray(value);
1381
+ } else {
1382
+ this.emitObject(value);
1383
+ }
1384
+ delete value.__Jasmine_been_here_before__;
1385
+ } else {
1386
+ this.emitScalar(value.toString());
1387
+ }
1388
+ } finally {
1389
+ this.ppNestLevel_--;
1390
+ }
1391
+ };
1392
+
1393
+ PrettyPrinter.prototype.iterateObject = function(obj, fn) {
1394
+ for (var property in obj) {
1395
+ if (!Object.prototype.hasOwnProperty.call(obj, property)) { continue; }
1396
+ if (property == '__Jasmine_been_here_before__') { continue; }
1397
+ fn(property, obj.__lookupGetter__ ? (!j$.util.isUndefined(obj.__lookupGetter__(property)) &&
1398
+ obj.__lookupGetter__(property) !== null) : false);
1399
+ }
1400
+ };
1401
+
1402
+ PrettyPrinter.prototype.emitArray = j$.unimplementedMethod_;
1403
+ PrettyPrinter.prototype.emitObject = j$.unimplementedMethod_;
1404
+ PrettyPrinter.prototype.emitScalar = j$.unimplementedMethod_;
1405
+ PrettyPrinter.prototype.emitString = j$.unimplementedMethod_;
1406
+
1407
+ function StringPrettyPrinter() {
1408
+ PrettyPrinter.call(this);
1409
+
1410
+ this.string = '';
1411
+ }
1412
+
1413
+ j$.util.inherit(StringPrettyPrinter, PrettyPrinter);
1414
+
1415
+ StringPrettyPrinter.prototype.emitScalar = function(value) {
1416
+ this.append(value);
1417
+ };
1418
+
1419
+ StringPrettyPrinter.prototype.emitString = function(value) {
1420
+ this.append("'" + value + "'");
1421
+ };
1422
+
1423
+ StringPrettyPrinter.prototype.emitArray = function(array) {
1424
+ if (this.ppNestLevel_ > j$.MAX_PRETTY_PRINT_DEPTH) {
1425
+ this.append("Array");
1426
+ return;
1427
+ }
1428
+
1429
+ this.append('[ ');
1430
+ for (var i = 0; i < array.length; i++) {
1431
+ if (i > 0) {
1432
+ this.append(', ');
1433
+ }
1434
+ this.format(array[i]);
1435
+ }
1436
+ this.append(' ]');
1437
+ };
1438
+
1439
+ StringPrettyPrinter.prototype.emitObject = function(obj) {
1440
+ if (this.ppNestLevel_ > j$.MAX_PRETTY_PRINT_DEPTH) {
1441
+ this.append("Object");
1442
+ return;
1443
+ }
1444
+
1445
+ var self = this;
1446
+ this.append('{ ');
1447
+ var first = true;
1448
+
1449
+ this.iterateObject(obj, function(property, isGetter) {
1450
+ if (first) {
1451
+ first = false;
1452
+ } else {
1453
+ self.append(', ');
1454
+ }
1455
+
1456
+ self.append(property);
1457
+ self.append(' : ');
1458
+ if (isGetter) {
1459
+ self.append('<getter>');
1460
+ } else {
1461
+ self.format(obj[property]);
1462
+ }
1463
+ });
1464
+
1465
+ this.append(' }');
1466
+ };
1467
+
1468
+ StringPrettyPrinter.prototype.append = function(value) {
1469
+ this.string += value;
1470
+ };
1471
+
1472
+ return function(value) {
1473
+ var stringPrettyPrinter = new StringPrettyPrinter();
1474
+ stringPrettyPrinter.format(value);
1475
+ return stringPrettyPrinter.string;
1476
+ };
1477
+ };
1478
+
1479
+ getJasmineRequireObj().QueueRunner = function() {
1480
+
1481
+ function QueueRunner(attrs) {
1482
+ this.fns = attrs.fns || [];
1483
+ this.onComplete = attrs.onComplete || function() {};
1484
+ this.clearStack = attrs.clearStack || function(fn) {fn();};
1485
+ this.onException = attrs.onException || function() {};
1486
+ this.catchException = attrs.catchException || function() { return true; };
1487
+ this.userContext = {};
1488
+ }
1489
+
1490
+ QueueRunner.prototype.execute = function() {
1491
+ this.run(this.fns, 0);
1492
+ };
1493
+
1494
+ QueueRunner.prototype.run = function(fns, recursiveIndex) {
1495
+ var length = fns.length,
1496
+ self = this,
1497
+ iterativeIndex;
1498
+
1499
+ for(iterativeIndex = recursiveIndex; iterativeIndex < length; iterativeIndex++) {
1500
+ var fn = fns[iterativeIndex];
1501
+ if (fn.length > 0) {
1502
+ return attemptAsync(fn);
1503
+ } else {
1504
+ attemptSync(fn);
1505
+ }
1506
+ }
1507
+
1508
+ var runnerDone = iterativeIndex >= length;
1509
+
1510
+ if (runnerDone) {
1511
+ this.clearStack(this.onComplete);
1512
+ }
1513
+
1514
+ function attemptSync(fn) {
1515
+ try {
1516
+ fn.call(self.userContext);
1517
+ } catch (e) {
1518
+ handleException(e);
1519
+ }
1520
+ }
1521
+
1522
+ function attemptAsync(fn) {
1523
+ var next = function () { self.run(fns, iterativeIndex + 1); };
1524
+
1525
+ try {
1526
+ fn.call(self.userContext, next);
1527
+ } catch (e) {
1528
+ handleException(e);
1529
+ next();
1530
+ }
1531
+ }
1532
+
1533
+ function handleException(e) {
1534
+ self.onException(e);
1535
+ if (!self.catchException(e)) {
1536
+ //TODO: set a var when we catch an exception and
1537
+ //use a finally block to close the loop in a nice way..
1538
+ throw e;
1539
+ }
1540
+ }
1541
+ };
1542
+
1543
+ return QueueRunner;
1544
+ };
1545
+
1546
+ getJasmineRequireObj().ReportDispatcher = function() {
1547
+ function ReportDispatcher(methods) {
1548
+
1549
+ var dispatchedMethods = methods || [];
1550
+
1551
+ for (var i = 0; i < dispatchedMethods.length; i++) {
1552
+ var method = dispatchedMethods[i];
1553
+ this[method] = (function(m) {
1554
+ return function() {
1555
+ dispatch(m, arguments);
1556
+ };
1557
+ }(method));
1558
+ }
1559
+
1560
+ var reporters = [];
1561
+
1562
+ this.addReporter = function(reporter) {
1563
+ reporters.push(reporter);
1564
+ };
1565
+
1566
+ return this;
1567
+
1568
+ function dispatch(method, args) {
1569
+ for (var i = 0; i < reporters.length; i++) {
1570
+ var reporter = reporters[i];
1571
+ if (reporter[method]) {
1572
+ reporter[method].apply(reporter, args);
1573
+ }
1574
+ }
1575
+ }
1576
+ }
1577
+
1578
+ return ReportDispatcher;
1579
+ };
1580
+
1581
+
1582
+ getJasmineRequireObj().SpyStrategy = function() {
1583
+
1584
+ function SpyStrategy(options) {
1585
+ options = options || {};
1586
+
1587
+ var identity = options.name || "unknown",
1588
+ originalFn = options.fn || function() {},
1589
+ getSpy = options.getSpy || function() {},
1590
+ plan = function() {};
1591
+
1592
+ this.identity = function() {
1593
+ return identity;
1594
+ };
1595
+
1596
+ this.exec = function() {
1597
+ return plan.apply(this, arguments);
1598
+ };
1599
+
1600
+ this.callThrough = function() {
1601
+ plan = originalFn;
1602
+ return getSpy();
1603
+ };
1604
+
1605
+ this.returnValue = function(value) {
1606
+ plan = function() {
1607
+ return value;
1608
+ };
1609
+ return getSpy();
1610
+ };
1611
+
1612
+ this.throwError = function(something) {
1613
+ var error = (something instanceof Error) ? something : new Error(something);
1614
+ plan = function() {
1615
+ throw error;
1616
+ };
1617
+ return getSpy();
1618
+ };
1619
+
1620
+ this.callFake = function(fn) {
1621
+ plan = fn;
1622
+ return getSpy();
1623
+ };
1624
+
1625
+ this.stub = function(fn) {
1626
+ plan = function() {};
1627
+ return getSpy();
1628
+ };
1629
+ }
1630
+
1631
+ return SpyStrategy;
1632
+ };
1633
+
1634
+ getJasmineRequireObj().Suite = function() {
1635
+ function Suite(attrs) {
1636
+ this.env = attrs.env;
1637
+ this.id = attrs.id;
1638
+ this.parentSuite = attrs.parentSuite;
1639
+ this.description = attrs.description;
1640
+ this.onStart = attrs.onStart || function() {};
1641
+ this.resultCallback = attrs.resultCallback || function() {};
1642
+ this.clearStack = attrs.clearStack || function(fn) {fn();};
1643
+
1644
+ this.beforeFns = [];
1645
+ this.afterFns = [];
1646
+ this.queueRunner = attrs.queueRunner || function() {};
1647
+ this.disabled = false;
1648
+
1649
+ this.children = [];
1650
+
1651
+ this.result = {
1652
+ id: this.id,
1653
+ status: this.disabled ? 'disabled' : '',
1654
+ description: this.description,
1655
+ fullName: this.getFullName()
1656
+ };
1657
+ }
1658
+
1659
+ Suite.prototype.getFullName = function() {
1660
+ var fullName = this.description;
1661
+ for (var parentSuite = this.parentSuite; parentSuite; parentSuite = parentSuite.parentSuite) {
1662
+ if (parentSuite.parentSuite) {
1663
+ fullName = parentSuite.description + ' ' + fullName;
1664
+ }
1665
+ }
1666
+ return fullName;
1667
+ };
1668
+
1669
+ Suite.prototype.disable = function() {
1670
+ this.disabled = true;
1671
+ };
1672
+
1673
+ Suite.prototype.beforeEach = function(fn) {
1674
+ this.beforeFns.unshift(fn);
1675
+ };
1676
+
1677
+ Suite.prototype.afterEach = function(fn) {
1678
+ this.afterFns.unshift(fn);
1679
+ };
1680
+
1681
+ Suite.prototype.addChild = function(child) {
1682
+ this.children.push(child);
1683
+ };
1684
+
1685
+ Suite.prototype.execute = function(onComplete) {
1686
+ var self = this;
1687
+ if (this.disabled) {
1688
+ complete();
1689
+ return;
1690
+ }
1691
+
1692
+ var allFns = [];
1693
+
1694
+ for (var i = 0; i < this.children.length; i++) {
1695
+ allFns.push(wrapChildAsAsync(this.children[i]));
1696
+ }
1697
+
1698
+ this.onStart(this);
1699
+
1700
+ this.queueRunner({
1701
+ fns: allFns,
1702
+ onComplete: complete
1703
+ });
1704
+
1705
+ function complete() {
1706
+ self.resultCallback(self.result);
1707
+
1708
+ if (onComplete) {
1709
+ onComplete();
1710
+ }
1711
+ }
1712
+
1713
+ function wrapChildAsAsync(child) {
1714
+ return function(done) { child.execute(done); };
1715
+ }
1716
+ };
1717
+
1718
+ return Suite;
1719
+ };
1720
+
1721
+ if (typeof window == void 0 && typeof exports == "object") {
1722
+ exports.Suite = jasmineRequire.Suite;
1723
+ }
1724
+
1725
+ getJasmineRequireObj().Timer = function() {
1726
+ var defaultNow = (function(Date) {
1727
+ return function() { return new Date().getTime(); };
1728
+ })(Date);
1729
+
1730
+ function Timer(options) {
1731
+ options = options || {};
1732
+
1733
+ var now = options.now || defaultNow,
1734
+ startTime;
1735
+
1736
+ this.start = function() {
1737
+ startTime = now();
1738
+ };
1739
+
1740
+ this.elapsed = function() {
1741
+ return now() - startTime;
1742
+ };
1743
+ }
1744
+
1745
+ return Timer;
1746
+ };
1747
+
1748
+ getJasmineRequireObj().matchersUtil = function(j$) {
1749
+ // TODO: what to do about jasmine.pp not being inject? move to JSON.stringify? gut PrettyPrinter?
1750
+
1751
+ return {
1752
+ equals: function(a, b, customTesters) {
1753
+ customTesters = customTesters || [];
1754
+
1755
+ return eq(a, b, [], [], customTesters);
1756
+ },
1757
+
1758
+ contains: function(haystack, needle, customTesters) {
1759
+ customTesters = customTesters || [];
1760
+
1761
+ if (Object.prototype.toString.apply(haystack) === "[object Array]") {
1762
+ for (var i = 0; i < haystack.length; i++) {
1763
+ if (eq(haystack[i], needle, [], [], customTesters)) {
1764
+ return true;
1765
+ }
1766
+ }
1767
+ return false;
1768
+ }
1769
+ return haystack.indexOf(needle) >= 0;
1770
+ },
1771
+
1772
+ buildFailureMessage: function() {
1773
+ var args = Array.prototype.slice.call(arguments, 0),
1774
+ matcherName = args[0],
1775
+ isNot = args[1],
1776
+ actual = args[2],
1777
+ expected = args.slice(3),
1778
+ englishyPredicate = matcherName.replace(/[A-Z]/g, function(s) { return ' ' + s.toLowerCase(); });
1779
+
1780
+ var message = "Expected " +
1781
+ j$.pp(actual) +
1782
+ (isNot ? " not " : " ") +
1783
+ englishyPredicate;
1784
+
1785
+ if (expected.length > 0) {
1786
+ for (var i = 0; i < expected.length; i++) {
1787
+ if (i > 0) {
1788
+ message += ",";
1789
+ }
1790
+ message += " " + j$.pp(expected[i]);
1791
+ }
1792
+ }
1793
+
1794
+ return message + ".";
1795
+ }
1796
+ };
1797
+
1798
+ // Equality function lovingly adapted from isEqual in
1799
+ // [Underscore](http://underscorejs.org)
1800
+ function eq(a, b, aStack, bStack, customTesters) {
1801
+ var result = true;
1802
+
1803
+ for (var i = 0; i < customTesters.length; i++) {
1804
+ var customTesterResult = customTesters[i](a, b);
1805
+ if (!j$.util.isUndefined(customTesterResult)) {
1806
+ return customTesterResult;
1807
+ }
1808
+ }
1809
+
1810
+ if (a instanceof j$.Any) {
1811
+ result = a.jasmineMatches(b);
1812
+ if (result) {
1813
+ return true;
1814
+ }
1815
+ }
1816
+
1817
+ if (b instanceof j$.Any) {
1818
+ result = b.jasmineMatches(a);
1819
+ if (result) {
1820
+ return true;
1821
+ }
1822
+ }
1823
+
1824
+ if (b instanceof j$.ObjectContaining) {
1825
+ result = b.jasmineMatches(a);
1826
+ if (result) {
1827
+ return true;
1828
+ }
1829
+ }
1830
+
1831
+ if (a instanceof Error && b instanceof Error) {
1832
+ return a.message == b.message;
1833
+ }
1834
+
1835
+ // Identical objects are equal. `0 === -0`, but they aren't identical.
1836
+ // See the [Harmony `egal` proposal](http://wiki.ecmascript.org/doku.php?id=harmony:egal).
1837
+ if (a === b) { return a !== 0 || 1 / a == 1 / b; }
1838
+ // A strict comparison is necessary because `null == undefined`.
1839
+ if (a === null || b === null) { return a === b; }
1840
+ var className = Object.prototype.toString.call(a);
1841
+ if (className != Object.prototype.toString.call(b)) { return false; }
1842
+ switch (className) {
1843
+ // Strings, numbers, dates, and booleans are compared by value.
1844
+ case '[object String]':
1845
+ // Primitives and their corresponding object wrappers are equivalent; thus, `"5"` is
1846
+ // equivalent to `new String("5")`.
1847
+ return a == String(b);
1848
+ case '[object Number]':
1849
+ // `NaN`s are equivalent, but non-reflexive. An `egal` comparison is performed for
1850
+ // other numeric values.
1851
+ return a != +a ? b != +b : (a === 0 ? 1 / a == 1 / b : a == +b);
1852
+ case '[object Date]':
1853
+ case '[object Boolean]':
1854
+ // Coerce dates and booleans to numeric primitive values. Dates are compared by their
1855
+ // millisecond representations. Note that invalid dates with millisecond representations
1856
+ // of `NaN` are not equivalent.
1857
+ return +a == +b;
1858
+ // RegExps are compared by their source patterns and flags.
1859
+ case '[object RegExp]':
1860
+ return a.source == b.source &&
1861
+ a.global == b.global &&
1862
+ a.multiline == b.multiline &&
1863
+ a.ignoreCase == b.ignoreCase;
1864
+ }
1865
+ if (typeof a != 'object' || typeof b != 'object') { return false; }
1866
+ // Assume equality for cyclic structures. The algorithm for detecting cyclic
1867
+ // structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`.
1868
+ var length = aStack.length;
1869
+ while (length--) {
1870
+ // Linear search. Performance is inversely proportional to the number of
1871
+ // unique nested structures.
1872
+ if (aStack[length] == a) { return bStack[length] == b; }
1873
+ }
1874
+ // Add the first object to the stack of traversed objects.
1875
+ aStack.push(a);
1876
+ bStack.push(b);
1877
+ var size = 0;
1878
+ // Recursively compare objects and arrays.
1879
+ if (className == '[object Array]') {
1880
+ // Compare array lengths to determine if a deep comparison is necessary.
1881
+ size = a.length;
1882
+ result = size == b.length;
1883
+ if (result) {
1884
+ // Deep compare the contents, ignoring non-numeric properties.
1885
+ while (size--) {
1886
+ if (!(result = eq(a[size], b[size], aStack, bStack, customTesters))) { break; }
1887
+ }
1888
+ }
1889
+ } else {
1890
+ // Objects with different constructors are not equivalent, but `Object`s
1891
+ // from different frames are.
1892
+ var aCtor = a.constructor, bCtor = b.constructor;
1893
+ if (aCtor !== bCtor && !(isFunction(aCtor) && (aCtor instanceof aCtor) &&
1894
+ isFunction(bCtor) && (bCtor instanceof bCtor))) {
1895
+ return false;
1896
+ }
1897
+ // Deep compare objects.
1898
+ for (var key in a) {
1899
+ if (has(a, key)) {
1900
+ // Count the expected number of properties.
1901
+ size++;
1902
+ // Deep compare each member.
1903
+ if (!(result = has(b, key) && eq(a[key], b[key], aStack, bStack, customTesters))) { break; }
1904
+ }
1905
+ }
1906
+ // Ensure that both objects contain the same number of properties.
1907
+ if (result) {
1908
+ for (key in b) {
1909
+ if (has(b, key) && !(size--)) { break; }
1910
+ }
1911
+ result = !size;
1912
+ }
1913
+ }
1914
+ // Remove the first object from the stack of traversed objects.
1915
+ aStack.pop();
1916
+ bStack.pop();
1917
+
1918
+ return result;
1919
+
1920
+ function has(obj, key) {
1921
+ return obj.hasOwnProperty(key);
1922
+ }
1923
+
1924
+ function isFunction(obj) {
1925
+ return typeof obj === 'function';
1926
+ }
1927
+ }
1928
+ };
1929
+
1930
+ getJasmineRequireObj().toBe = function() {
1931
+ function toBe() {
1932
+ return {
1933
+ compare: function(actual, expected) {
1934
+ return {
1935
+ pass: actual === expected
1936
+ };
1937
+ }
1938
+ };
1939
+ }
1940
+
1941
+ return toBe;
1942
+ };
1943
+
1944
+ getJasmineRequireObj().toBeCloseTo = function() {
1945
+
1946
+ function toBeCloseTo() {
1947
+ return {
1948
+ compare: function(actual, expected, precision) {
1949
+ if (precision !== 0) {
1950
+ precision = precision || 2;
1951
+ }
1952
+
1953
+ return {
1954
+ pass: Math.abs(expected - actual) < (Math.pow(10, -precision) / 2)
1955
+ };
1956
+ }
1957
+ };
1958
+ }
1959
+
1960
+ return toBeCloseTo;
1961
+ };
1962
+
1963
+ getJasmineRequireObj().toBeDefined = function() {
1964
+ function toBeDefined() {
1965
+ return {
1966
+ compare: function(actual) {
1967
+ return {
1968
+ pass: (void 0 !== actual)
1969
+ };
1970
+ }
1971
+ };
1972
+ }
1973
+
1974
+ return toBeDefined;
1975
+ };
1976
+
1977
+ getJasmineRequireObj().toBeFalsy = function() {
1978
+ function toBeFalsy() {
1979
+ return {
1980
+ compare: function(actual) {
1981
+ return {
1982
+ pass: !!!actual
1983
+ };
1984
+ }
1985
+ };
1986
+ }
1987
+
1988
+ return toBeFalsy;
1989
+ };
1990
+
1991
+ getJasmineRequireObj().toBeGreaterThan = function() {
1992
+
1993
+ function toBeGreaterThan() {
1994
+ return {
1995
+ compare: function(actual, expected) {
1996
+ return {
1997
+ pass: actual > expected
1998
+ };
1999
+ }
2000
+ };
2001
+ }
2002
+
2003
+ return toBeGreaterThan;
2004
+ };
2005
+
2006
+
2007
+ getJasmineRequireObj().toBeLessThan = function() {
2008
+ function toBeLessThan() {
2009
+ return {
2010
+
2011
+ compare: function(actual, expected) {
2012
+ return {
2013
+ pass: actual < expected
2014
+ };
2015
+ }
2016
+ };
2017
+ }
2018
+
2019
+ return toBeLessThan;
2020
+ };
2021
+ getJasmineRequireObj().toBeNaN = function(j$) {
2022
+
2023
+ function toBeNaN() {
2024
+ return {
2025
+ compare: function(actual) {
2026
+ var result = {
2027
+ pass: (actual !== actual)
2028
+ };
2029
+
2030
+ if (result.pass) {
2031
+ result.message = "Expected actual not to be NaN.";
2032
+ } else {
2033
+ result.message = "Expected " + j$.pp(actual) + " to be NaN.";
2034
+ }
2035
+
2036
+ return result;
2037
+ }
2038
+ };
2039
+ }
2040
+
2041
+ return toBeNaN;
2042
+ };
2043
+
2044
+ getJasmineRequireObj().toBeNull = function() {
2045
+
2046
+ function toBeNull() {
2047
+ return {
2048
+ compare: function(actual) {
2049
+ return {
2050
+ pass: actual === null
2051
+ };
2052
+ }
2053
+ };
2054
+ }
2055
+
2056
+ return toBeNull;
2057
+ };
2058
+
2059
+ getJasmineRequireObj().toBeTruthy = function() {
2060
+
2061
+ function toBeTruthy() {
2062
+ return {
2063
+ compare: function(actual) {
2064
+ return {
2065
+ pass: !!actual
2066
+ };
2067
+ }
2068
+ };
2069
+ }
2070
+
2071
+ return toBeTruthy;
2072
+ };
2073
+
2074
+ getJasmineRequireObj().toBeUndefined = function() {
2075
+
2076
+ function toBeUndefined() {
2077
+ return {
2078
+ compare: function(actual) {
2079
+ return {
2080
+ pass: void 0 === actual
2081
+ };
2082
+ }
2083
+ };
2084
+ }
2085
+
2086
+ return toBeUndefined;
2087
+ };
2088
+
2089
+ getJasmineRequireObj().toContain = function() {
2090
+ function toContain(util, customEqualityTesters) {
2091
+ customEqualityTesters = customEqualityTesters || [];
2092
+
2093
+ return {
2094
+ compare: function(actual, expected) {
2095
+
2096
+ return {
2097
+ pass: util.contains(actual, expected, customEqualityTesters)
2098
+ };
2099
+ }
2100
+ };
2101
+ }
2102
+
2103
+ return toContain;
2104
+ };
2105
+
2106
+ getJasmineRequireObj().toEqual = function() {
2107
+
2108
+ function toEqual(util, customEqualityTesters) {
2109
+ customEqualityTesters = customEqualityTesters || [];
2110
+
2111
+ return {
2112
+ compare: function(actual, expected) {
2113
+ var result = {
2114
+ pass: false
2115
+ };
2116
+
2117
+ result.pass = util.equals(actual, expected, customEqualityTesters);
2118
+
2119
+ return result;
2120
+ }
2121
+ };
2122
+ }
2123
+
2124
+ return toEqual;
2125
+ };
2126
+
2127
+ getJasmineRequireObj().toHaveBeenCalled = function(j$) {
2128
+
2129
+ function toHaveBeenCalled() {
2130
+ return {
2131
+ compare: function(actual) {
2132
+ var result = {};
2133
+
2134
+ if (!j$.isSpy(actual)) {
2135
+ throw new Error('Expected a spy, but got ' + j$.pp(actual) + '.');
2136
+ }
2137
+
2138
+ if (arguments.length > 1) {
2139
+ throw new Error('toHaveBeenCalled does not take arguments, use toHaveBeenCalledWith');
2140
+ }
2141
+
2142
+ result.pass = actual.calls.any();
2143
+
2144
+ result.message = result.pass ?
2145
+ "Expected spy " + actual.and.identity() + " not to have been called." :
2146
+ "Expected spy " + actual.and.identity() + " to have been called.";
2147
+
2148
+ return result;
2149
+ }
2150
+ };
2151
+ }
2152
+
2153
+ return toHaveBeenCalled;
2154
+ };
2155
+
2156
+ getJasmineRequireObj().toHaveBeenCalledWith = function(j$) {
2157
+
2158
+ function toHaveBeenCalledWith(util) {
2159
+ return {
2160
+ compare: function() {
2161
+ var args = Array.prototype.slice.call(arguments, 0),
2162
+ actual = args[0],
2163
+ expectedArgs = args.slice(1),
2164
+ result = { pass: false };
2165
+
2166
+ if (!j$.isSpy(actual)) {
2167
+ throw new Error('Expected a spy, but got ' + j$.pp(actual) + '.');
2168
+ }
2169
+
2170
+ if (!actual.calls.any()) {
2171
+ result.message = "Expected spy " + actual.and.identity() + " to have been called with " + j$.pp(expectedArgs) + " but it was never called.";
2172
+ return result;
2173
+ }
2174
+
2175
+ if (util.contains(actual.calls.allArgs(), expectedArgs)) {
2176
+ result.pass = true;
2177
+ result.message = "Expected spy " + actual.and.identity() + " not to have been called with " + j$.pp(expectedArgs) + " but it was.";
2178
+ } else {
2179
+ result.message = "Expected spy " + actual.and.identity() + " to have been called with " + j$.pp(expectedArgs) + " but actual calls were " + j$.pp(actual.calls.allArgs()).replace(/^\[ | \]$/g, '') + ".";
2180
+ }
2181
+
2182
+ return result;
2183
+ }
2184
+ };
2185
+ }
2186
+
2187
+ return toHaveBeenCalledWith;
2188
+ };
2189
+
2190
+ getJasmineRequireObj().toMatch = function() {
2191
+
2192
+ function toMatch() {
2193
+ return {
2194
+ compare: function(actual, expected) {
2195
+ var regexp = new RegExp(expected);
2196
+
2197
+ return {
2198
+ pass: regexp.test(actual)
2199
+ };
2200
+ }
2201
+ };
2202
+ }
2203
+
2204
+ return toMatch;
2205
+ };
2206
+
2207
+ getJasmineRequireObj().toThrow = function(j$) {
2208
+
2209
+ function toThrow(util) {
2210
+ return {
2211
+ compare: function(actual, expected) {
2212
+ var result = { pass: false },
2213
+ threw = false,
2214
+ thrown;
2215
+
2216
+ if (typeof actual != "function") {
2217
+ throw new Error("Actual is not a Function");
2218
+ }
2219
+
2220
+ try {
2221
+ actual();
2222
+ } catch (e) {
2223
+ threw = true;
2224
+ thrown = e;
2225
+ }
2226
+
2227
+ if (!threw) {
2228
+ result.message = "Expected function to throw an exception.";
2229
+ return result;
2230
+ }
2231
+
2232
+ if (arguments.length == 1) {
2233
+ result.pass = true;
2234
+ result.message = "Expected function not to throw, but it threw " + j$.pp(thrown) + ".";
2235
+
2236
+ return result;
2237
+ }
2238
+
2239
+ if (util.equals(thrown, expected)) {
2240
+ result.pass = true;
2241
+ result.message = "Expected function not to throw " + j$.pp(expected) + ".";
2242
+ } else {
2243
+ result.message = "Expected function to throw " + j$.pp(expected) + ", but it threw " + j$.pp(thrown) + ".";
2244
+ }
2245
+
2246
+ return result;
2247
+ }
2248
+ };
2249
+ }
2250
+
2251
+ return toThrow;
2252
+ };
2253
+
2254
+ getJasmineRequireObj().toThrowError = function(j$) {
2255
+ function toThrowError (util) {
2256
+ return {
2257
+ compare: function(actual) {
2258
+ var threw = false,
2259
+ thrown,
2260
+ errorType,
2261
+ message,
2262
+ regexp,
2263
+ name,
2264
+ constructorName;
2265
+
2266
+ if (typeof actual != "function") {
2267
+ throw new Error("Actual is not a Function");
2268
+ }
2269
+
2270
+ extractExpectedParams.apply(null, arguments);
2271
+
2272
+ try {
2273
+ actual();
2274
+ } catch (e) {
2275
+ threw = true;
2276
+ thrown = e;
2277
+ }
2278
+
2279
+ if (!threw) {
2280
+ return fail("Expected function to throw an Error.");
2281
+ }
2282
+
2283
+ if (!(thrown instanceof Error)) {
2284
+ return fail("Expected function to throw an Error, but it threw " + thrown + ".");
2285
+ }
2286
+
2287
+ if (arguments.length == 1) {
2288
+ return pass("Expected function not to throw an Error, but it threw " + fnNameFor(thrown) + ".");
2289
+ }
2290
+
2291
+ if (errorType) {
2292
+ name = fnNameFor(errorType);
2293
+ constructorName = fnNameFor(thrown.constructor);
2294
+ }
2295
+
2296
+ if (errorType && message) {
2297
+ if (thrown.constructor == errorType && util.equals(thrown.message, message)) {
2298
+ return pass("Expected function not to throw " + name + " with message \"" + message + "\".");
2299
+ } else {
2300
+ return fail("Expected function to throw " + name + " with message \"" + message +
2301
+ "\", but it threw " + constructorName + " with message \"" + thrown.message + "\".");
2302
+ }
2303
+ }
2304
+
2305
+ if (errorType && regexp) {
2306
+ if (thrown.constructor == errorType && regexp.test(thrown.message)) {
2307
+ return pass("Expected function not to throw " + name + " with message matching " + regexp + ".");
2308
+ } else {
2309
+ return fail("Expected function to throw " + name + " with message matching " + regexp +
2310
+ ", but it threw " + constructorName + " with message \"" + thrown.message + "\".");
2311
+ }
2312
+ }
2313
+
2314
+ if (errorType) {
2315
+ if (thrown.constructor == errorType) {
2316
+ return pass("Expected function not to throw " + name + ".");
2317
+ } else {
2318
+ return fail("Expected function to throw " + name + ", but it threw " + constructorName + ".");
2319
+ }
2320
+ }
2321
+
2322
+ if (message) {
2323
+ if (thrown.message == message) {
2324
+ return pass("Expected function not to throw an exception with message " + j$.pp(message) + ".");
2325
+ } else {
2326
+ return fail("Expected function to throw an exception with message " + j$.pp(message) +
2327
+ ", but it threw an exception with message " + j$.pp(thrown.message) + ".");
2328
+ }
2329
+ }
2330
+
2331
+ if (regexp) {
2332
+ if (regexp.test(thrown.message)) {
2333
+ return pass("Expected function not to throw an exception with a message matching " + j$.pp(regexp) + ".");
2334
+ } else {
2335
+ return fail("Expected function to throw an exception with a message matching " + j$.pp(regexp) +
2336
+ ", but it threw an exception with message " + j$.pp(thrown.message) + ".");
2337
+ }
2338
+ }
2339
+
2340
+ function fnNameFor(func) {
2341
+ return func.name || func.toString().match(/^\s*function\s*(\w*)\s*\(/)[1];
2342
+ }
2343
+
2344
+ function pass(notMessage) {
2345
+ return {
2346
+ pass: true,
2347
+ message: notMessage
2348
+ };
2349
+ }
2350
+
2351
+ function fail(message) {
2352
+ return {
2353
+ pass: false,
2354
+ message: message
2355
+ };
2356
+ }
2357
+
2358
+ function extractExpectedParams() {
2359
+ if (arguments.length == 1) {
2360
+ return;
2361
+ }
2362
+
2363
+ if (arguments.length == 2) {
2364
+ var expected = arguments[1];
2365
+
2366
+ if (expected instanceof RegExp) {
2367
+ regexp = expected;
2368
+ } else if (typeof expected == "string") {
2369
+ message = expected;
2370
+ } else if (checkForAnErrorType(expected)) {
2371
+ errorType = expected;
2372
+ }
2373
+
2374
+ if (!(errorType || message || regexp)) {
2375
+ throw new Error("Expected is not an Error, string, or RegExp.");
2376
+ }
2377
+ } else {
2378
+ if (checkForAnErrorType(arguments[1])) {
2379
+ errorType = arguments[1];
2380
+ } else {
2381
+ throw new Error("Expected error type is not an Error.");
2382
+ }
2383
+
2384
+ if (arguments[2] instanceof RegExp) {
2385
+ regexp = arguments[2];
2386
+ } else if (typeof arguments[2] == "string") {
2387
+ message = arguments[2];
2388
+ } else {
2389
+ throw new Error("Expected error message is not a string or RegExp.");
2390
+ }
2391
+ }
2392
+ }
2393
+
2394
+ function checkForAnErrorType(type) {
2395
+ if (typeof type !== "function") {
2396
+ return false;
2397
+ }
2398
+
2399
+ var Surrogate = function() {};
2400
+ Surrogate.prototype = type.prototype;
2401
+ return (new Surrogate()) instanceof Error;
2402
+ }
2403
+ }
2404
+ };
2405
+ }
2406
+
2407
+ return toThrowError;
2408
+ };
2409
+
2410
+ getJasmineRequireObj().version = function() {
2411
+ return "2.0.0";
2412
+ };