teaspoon 0.7.9 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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
@@ -1,2606 +1,7 @@
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
- } else {
871
- spec.pending = true
872
- }
873
-
874
- return spec;
875
- };
876
-
877
- jasmine.Env.prototype.xit = function(desc, func) {
878
- return {
879
- id: this.nextSpecId(),
880
- runs: function() {
881
- }
882
- };
883
- };
884
-
885
- jasmine.Env.prototype.compareRegExps_ = function(a, b, mismatchKeys, mismatchValues) {
886
- if (a.source != b.source)
887
- mismatchValues.push("expected pattern /" + b.source + "/ is not equal to the pattern /" + a.source + "/");
888
-
889
- if (a.ignoreCase != b.ignoreCase)
890
- mismatchValues.push("expected modifier i was" + (b.ignoreCase ? " " : " not ") + "set and does not equal the origin modifier");
891
-
892
- if (a.global != b.global)
893
- mismatchValues.push("expected modifier g was" + (b.global ? " " : " not ") + "set and does not equal the origin modifier");
894
-
895
- if (a.multiline != b.multiline)
896
- mismatchValues.push("expected modifier m was" + (b.multiline ? " " : " not ") + "set and does not equal the origin modifier");
897
-
898
- if (a.sticky != b.sticky)
899
- mismatchValues.push("expected modifier y was" + (b.sticky ? " " : " not ") + "set and does not equal the origin modifier");
900
-
901
- return (mismatchValues.length === 0);
902
- };
903
-
904
- jasmine.Env.prototype.compareObjects_ = function(a, b, mismatchKeys, mismatchValues) {
905
- if (a.__Jasmine_been_here_before__ === b && b.__Jasmine_been_here_before__ === a) {
906
- return true;
907
- }
908
-
909
- a.__Jasmine_been_here_before__ = b;
910
- b.__Jasmine_been_here_before__ = a;
911
-
912
- var hasKey = function(obj, keyName) {
913
- return obj !== null && obj[keyName] !== jasmine.undefined;
914
- };
915
-
916
- for (var property in b) {
917
- if (!hasKey(a, property) && hasKey(b, property)) {
918
- mismatchKeys.push("expected has key '" + property + "', but missing from actual.");
919
- }
920
- }
921
- for (property in a) {
922
- if (!hasKey(b, property) && hasKey(a, property)) {
923
- mismatchKeys.push("expected missing key '" + property + "', but present in actual.");
924
- }
925
- }
926
- for (property in b) {
927
- if (property == '__Jasmine_been_here_before__') continue;
928
- if (!this.equals_(a[property], b[property], mismatchKeys, mismatchValues)) {
929
- 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.");
930
- }
931
- }
932
-
933
- if (jasmine.isArray_(a) && jasmine.isArray_(b) && a.length != b.length) {
934
- mismatchValues.push("arrays were not the same length");
935
- }
936
-
937
- delete a.__Jasmine_been_here_before__;
938
- delete b.__Jasmine_been_here_before__;
939
- return (mismatchKeys.length === 0 && mismatchValues.length === 0);
940
- };
941
-
942
- jasmine.Env.prototype.equals_ = function(a, b, mismatchKeys, mismatchValues) {
943
- mismatchKeys = mismatchKeys || [];
944
- mismatchValues = mismatchValues || [];
945
-
946
- for (var i = 0; i < this.equalityTesters_.length; i++) {
947
- var equalityTester = this.equalityTesters_[i];
948
- var result = equalityTester(a, b, this, mismatchKeys, mismatchValues);
949
- if (result !== jasmine.undefined) return result;
950
- }
951
-
952
- if (a === b) return true;
953
-
954
- if (a === jasmine.undefined || a === null || b === jasmine.undefined || b === null) {
955
- return (a == jasmine.undefined && b == jasmine.undefined);
956
- }
957
-
958
- if (jasmine.isDomNode(a) && jasmine.isDomNode(b)) {
959
- return a === b;
960
- }
961
-
962
- if (a instanceof Date && b instanceof Date) {
963
- return a.getTime() == b.getTime();
964
- }
965
-
966
- if (a.jasmineMatches) {
967
- return a.jasmineMatches(b);
968
- }
969
-
970
- if (b.jasmineMatches) {
971
- return b.jasmineMatches(a);
972
- }
973
-
974
- if (a instanceof jasmine.Matchers.ObjectContaining) {
975
- return a.matches(b);
976
- }
977
-
978
- if (b instanceof jasmine.Matchers.ObjectContaining) {
979
- return b.matches(a);
980
- }
981
-
982
- if (jasmine.isString_(a) && jasmine.isString_(b)) {
983
- return (a == b);
984
- }
985
-
986
- if (jasmine.isNumber_(a) && jasmine.isNumber_(b)) {
987
- return (a == b);
988
- }
989
-
990
- if (a instanceof RegExp && b instanceof RegExp) {
991
- return this.compareRegExps_(a, b, mismatchKeys, mismatchValues);
992
- }
993
-
994
- if (typeof a === "object" && typeof b === "object") {
995
- return this.compareObjects_(a, b, mismatchKeys, mismatchValues);
996
- }
997
-
998
- //Straight check
999
- return (a === b);
1000
- };
1001
-
1002
- jasmine.Env.prototype.contains_ = function(haystack, needle) {
1003
- if (jasmine.isArray_(haystack)) {
1004
- for (var i = 0; i < haystack.length; i++) {
1005
- if (this.equals_(haystack[i], needle)) return true;
1006
- }
1007
- return false;
1008
- }
1009
- return haystack.indexOf(needle) >= 0;
1010
- };
1011
-
1012
- jasmine.Env.prototype.addEqualityTester = function(equalityTester) {
1013
- this.equalityTesters_.push(equalityTester);
1014
- };
1015
- /** No-op base class for Jasmine reporters.
1016
- *
1017
- * @constructor
1018
- */
1019
- jasmine.Reporter = function() {
1020
- };
1021
-
1022
- //noinspection JSUnusedLocalSymbols
1023
- jasmine.Reporter.prototype.reportRunnerStarting = function(runner) {
1024
- };
1025
-
1026
- //noinspection JSUnusedLocalSymbols
1027
- jasmine.Reporter.prototype.reportRunnerResults = function(runner) {
1028
- };
1029
-
1030
- //noinspection JSUnusedLocalSymbols
1031
- jasmine.Reporter.prototype.reportSuiteResults = function(suite) {
1032
- };
1033
-
1034
- //noinspection JSUnusedLocalSymbols
1035
- jasmine.Reporter.prototype.reportSpecStarting = function(spec) {
1036
- };
1037
-
1038
- //noinspection JSUnusedLocalSymbols
1039
- jasmine.Reporter.prototype.reportSpecResults = function(spec) {
1040
- };
1041
-
1042
- //noinspection JSUnusedLocalSymbols
1043
- jasmine.Reporter.prototype.log = function(str) {
1044
- };
1045
-
1046
- /**
1047
- * Blocks are functions with executable code that make up a spec.
1048
- *
1049
- * @constructor
1050
- * @param {jasmine.Env} env
1051
- * @param {Function} func
1052
- * @param {jasmine.Spec} spec
1053
- */
1054
- jasmine.Block = function(env, func, spec) {
1055
- this.env = env;
1056
- this.func = func;
1057
- this.spec = spec;
1058
- };
1059
-
1060
- jasmine.Block.prototype.execute = function(onComplete) {
1061
- if (!jasmine.CATCH_EXCEPTIONS) {
1062
- this.func.apply(this.spec);
1063
- }
1064
- else {
1065
- try {
1066
- this.func.apply(this.spec);
1067
- } catch (e) {
1068
- this.spec.fail(e);
1069
- }
1070
- }
1071
- onComplete();
1072
- };
1073
- /** JavaScript API reporter.
1074
- *
1075
- * @constructor
1076
- */
1077
- jasmine.JsApiReporter = function() {
1078
- this.started = false;
1079
- this.finished = false;
1080
- this.suites_ = [];
1081
- this.results_ = {};
1082
- };
1083
-
1084
- jasmine.JsApiReporter.prototype.reportRunnerStarting = function(runner) {
1085
- this.started = true;
1086
- var suites = runner.topLevelSuites();
1087
- for (var i = 0; i < suites.length; i++) {
1088
- var suite = suites[i];
1089
- this.suites_.push(this.summarize_(suite));
1090
- }
1091
- };
1092
-
1093
- jasmine.JsApiReporter.prototype.suites = function() {
1094
- return this.suites_;
1095
- };
1096
-
1097
- jasmine.JsApiReporter.prototype.summarize_ = function(suiteOrSpec) {
1098
- var isSuite = suiteOrSpec instanceof jasmine.Suite;
1099
- var summary = {
1100
- id: suiteOrSpec.id,
1101
- name: suiteOrSpec.description,
1102
- type: isSuite ? 'suite' : 'spec',
1103
- children: []
1104
- };
1105
-
1106
- if (isSuite) {
1107
- var children = suiteOrSpec.children();
1108
- for (var i = 0; i < children.length; i++) {
1109
- summary.children.push(this.summarize_(children[i]));
1110
- }
1111
- }
1112
- return summary;
1113
- };
1114
-
1115
- jasmine.JsApiReporter.prototype.results = function() {
1116
- return this.results_;
1117
- };
1118
-
1119
- jasmine.JsApiReporter.prototype.resultsForSpec = function(specId) {
1120
- return this.results_[specId];
1121
- };
1122
-
1123
- //noinspection JSUnusedLocalSymbols
1124
- jasmine.JsApiReporter.prototype.reportRunnerResults = function(runner) {
1125
- this.finished = true;
1126
- };
1127
-
1128
- //noinspection JSUnusedLocalSymbols
1129
- jasmine.JsApiReporter.prototype.reportSuiteResults = function(suite) {
1130
- };
1131
-
1132
- //noinspection JSUnusedLocalSymbols
1133
- jasmine.JsApiReporter.prototype.reportSpecResults = function(spec) {
1134
- this.results_[spec.id] = {
1135
- messages: spec.results().getItems(),
1136
- result: spec.results().failedCount > 0 ? "failed" : "passed"
1137
- };
1138
- };
1139
-
1140
- //noinspection JSUnusedLocalSymbols
1141
- jasmine.JsApiReporter.prototype.log = function(str) {
1142
- };
1143
-
1144
- jasmine.JsApiReporter.prototype.resultsForSpecs = function(specIds){
1145
- var results = {};
1146
- for (var i = 0; i < specIds.length; i++) {
1147
- var specId = specIds[i];
1148
- results[specId] = this.summarizeResult_(this.results_[specId]);
1149
- }
1150
- return results;
1151
- };
1152
-
1153
- jasmine.JsApiReporter.prototype.summarizeResult_ = function(result){
1154
- var summaryMessages = [];
1155
- var messagesLength = result.messages.length;
1156
- for (var messageIndex = 0; messageIndex < messagesLength; messageIndex++) {
1157
- var resultMessage = result.messages[messageIndex];
1158
- summaryMessages.push({
1159
- text: resultMessage.type == 'log' ? resultMessage.toString() : jasmine.undefined,
1160
- passed: resultMessage.passed ? resultMessage.passed() : true,
1161
- type: resultMessage.type,
1162
- message: resultMessage.message,
1163
- trace: {
1164
- stack: resultMessage.passed && !resultMessage.passed() ? resultMessage.trace.stack : jasmine.undefined
1165
- }
1166
- });
1167
- }
1168
-
1169
- return {
1170
- result : result.result,
1171
- messages : summaryMessages
1172
- };
1173
- };
1174
-
1175
- /**
1176
- * @constructor
1177
- * @param {jasmine.Env} env
1178
- * @param actual
1179
- * @param {jasmine.Spec} spec
1180
- */
1181
- jasmine.Matchers = function(env, actual, spec, opt_isNot) {
1182
- this.env = env;
1183
- this.actual = actual;
1184
- this.spec = spec;
1185
- this.isNot = opt_isNot || false;
1186
- this.reportWasCalled_ = false;
1187
- };
1188
-
1189
- // todo: @deprecated as of Jasmine 0.11, remove soon [xw]
1190
- jasmine.Matchers.pp = function(str) {
1191
- throw new Error("jasmine.Matchers.pp() is no longer supported, please use jasmine.pp() instead!");
1192
- };
1193
-
1194
- // todo: @deprecated Deprecated as of Jasmine 0.10. Rewrite your custom matchers to return true or false. [xw]
1195
- jasmine.Matchers.prototype.report = function(result, failing_message, details) {
1196
- throw new Error("As of jasmine 0.11, custom matchers must be implemented differently -- please see jasmine docs");
1197
- };
1198
-
1199
- jasmine.Matchers.wrapInto_ = function(prototype, matchersClass) {
1200
- for (var methodName in prototype) {
1201
- if (methodName == 'report') continue;
1202
- var orig = prototype[methodName];
1203
- matchersClass.prototype[methodName] = jasmine.Matchers.matcherFn_(methodName, orig);
1204
- }
1205
- };
1206
-
1207
- jasmine.Matchers.matcherFn_ = function(matcherName, matcherFunction) {
1208
- return function() {
1209
- var matcherArgs = jasmine.util.argsToArray(arguments);
1210
- var result = matcherFunction.apply(this, arguments);
1211
-
1212
- if (this.isNot) {
1213
- result = !result;
1214
- }
1215
-
1216
- if (this.reportWasCalled_) return result;
1217
-
1218
- var message;
1219
- if (!result) {
1220
- if (this.message) {
1221
- message = this.message.apply(this, arguments);
1222
- if (jasmine.isArray_(message)) {
1223
- message = message[this.isNot ? 1 : 0];
1224
- }
1225
- } else {
1226
- var englishyPredicate = matcherName.replace(/[A-Z]/g, function(s) { return ' ' + s.toLowerCase(); });
1227
- message = "Expected " + jasmine.pp(this.actual) + (this.isNot ? " not " : " ") + englishyPredicate;
1228
- if (matcherArgs.length > 0) {
1229
- for (var i = 0; i < matcherArgs.length; i++) {
1230
- if (i > 0) message += ",";
1231
- message += " " + jasmine.pp(matcherArgs[i]);
1232
- }
1233
- }
1234
- message += ".";
1235
- }
1236
- }
1237
- var expectationResult = new jasmine.ExpectationResult({
1238
- matcherName: matcherName,
1239
- passed: result,
1240
- expected: matcherArgs.length > 1 ? matcherArgs : matcherArgs[0],
1241
- actual: this.actual,
1242
- message: message
1243
- });
1244
- this.spec.addMatcherResult(expectationResult);
1245
- return jasmine.undefined;
1246
- };
1247
- };
1248
-
1249
-
1250
-
1251
-
1252
- /**
1253
- * toBe: compares the actual to the expected using ===
1254
- * @param expected
1255
- */
1256
- jasmine.Matchers.prototype.toBe = function(expected) {
1257
- return this.actual === expected;
1258
- };
1259
-
1260
- /**
1261
- * toNotBe: compares the actual to the expected using !==
1262
- * @param expected
1263
- * @deprecated as of 1.0. Use not.toBe() instead.
1264
- */
1265
- jasmine.Matchers.prototype.toNotBe = function(expected) {
1266
- return this.actual !== expected;
1267
- };
1268
-
1269
- /**
1270
- * toEqual: compares the actual to the expected using common sense equality. Handles Objects, Arrays, etc.
1271
- *
1272
- * @param expected
1273
- */
1274
- jasmine.Matchers.prototype.toEqual = function(expected) {
1275
- return this.env.equals_(this.actual, expected);
1276
- };
1277
-
1278
- /**
1279
- * toNotEqual: compares the actual to the expected using the ! of jasmine.Matchers.toEqual
1280
- * @param expected
1281
- * @deprecated as of 1.0. Use not.toEqual() instead.
1282
- */
1283
- jasmine.Matchers.prototype.toNotEqual = function(expected) {
1284
- return !this.env.equals_(this.actual, expected);
1285
- };
1286
-
1287
- /**
1288
- * Matcher that compares the actual to the expected using a regular expression. Constructs a RegExp, so takes
1289
- * a pattern or a String.
1290
- *
1291
- * @param expected
1292
- */
1293
- jasmine.Matchers.prototype.toMatch = function(expected) {
1294
- return new RegExp(expected).test(this.actual);
1295
- };
1296
-
1297
- /**
1298
- * Matcher that compares the actual to the expected using the boolean inverse of jasmine.Matchers.toMatch
1299
- * @param expected
1300
- * @deprecated as of 1.0. Use not.toMatch() instead.
1301
- */
1302
- jasmine.Matchers.prototype.toNotMatch = function(expected) {
1303
- return !(new RegExp(expected).test(this.actual));
1304
- };
1305
-
1306
- /**
1307
- * Matcher that compares the actual to jasmine.undefined.
1308
- */
1309
- jasmine.Matchers.prototype.toBeDefined = function() {
1310
- return (this.actual !== jasmine.undefined);
1311
- };
1312
-
1313
- /**
1314
- * Matcher that compares the actual to jasmine.undefined.
1315
- */
1316
- jasmine.Matchers.prototype.toBeUndefined = function() {
1317
- return (this.actual === jasmine.undefined);
1318
- };
1319
-
1320
- /**
1321
- * Matcher that compares the actual to null.
1322
- */
1323
- jasmine.Matchers.prototype.toBeNull = function() {
1324
- return (this.actual === null);
1325
- };
1326
-
1327
- /**
1328
- * Matcher that compares the actual to NaN.
1329
- */
1330
- jasmine.Matchers.prototype.toBeNaN = function() {
1331
- this.message = function() {
1332
- return [ "Expected " + jasmine.pp(this.actual) + " to be NaN." ];
1333
- };
1334
-
1335
- return (this.actual !== this.actual);
1336
- };
1337
-
1338
- /**
1339
- * Matcher that boolean not-nots the actual.
1340
- */
1341
- jasmine.Matchers.prototype.toBeTruthy = function() {
1342
- return !!this.actual;
1343
- };
1344
-
1345
-
1346
- /**
1347
- * Matcher that boolean nots the actual.
1348
- */
1349
- jasmine.Matchers.prototype.toBeFalsy = function() {
1350
- return !this.actual;
1351
- };
1352
-
1353
-
1354
- /**
1355
- * Matcher that checks to see if the actual, a Jasmine spy, was called.
1356
- */
1357
- jasmine.Matchers.prototype.toHaveBeenCalled = function() {
1358
- if (arguments.length > 0) {
1359
- throw new Error('toHaveBeenCalled does not take arguments, use toHaveBeenCalledWith');
1360
- }
1361
-
1362
- if (!jasmine.isSpy(this.actual)) {
1363
- throw new Error('Expected a spy, but got ' + jasmine.pp(this.actual) + '.');
1364
- }
1365
-
1366
- this.message = function() {
1367
- return [
1368
- "Expected spy " + this.actual.identity + " to have been called.",
1369
- "Expected spy " + this.actual.identity + " not to have been called."
1370
- ];
1371
- };
1372
-
1373
- return this.actual.wasCalled;
1374
- };
1375
-
1376
- /** @deprecated Use expect(xxx).toHaveBeenCalled() instead */
1377
- jasmine.Matchers.prototype.wasCalled = jasmine.Matchers.prototype.toHaveBeenCalled;
1378
-
1379
- /**
1380
- * Matcher that checks to see if the actual, a Jasmine spy, was not called.
1381
- *
1382
- * @deprecated Use expect(xxx).not.toHaveBeenCalled() instead
1383
- */
1384
- jasmine.Matchers.prototype.wasNotCalled = function() {
1385
- if (arguments.length > 0) {
1386
- throw new Error('wasNotCalled does not take arguments');
1387
- }
1388
-
1389
- if (!jasmine.isSpy(this.actual)) {
1390
- throw new Error('Expected a spy, but got ' + jasmine.pp(this.actual) + '.');
1391
- }
1392
-
1393
- this.message = function() {
1394
- return [
1395
- "Expected spy " + this.actual.identity + " to not have been called.",
1396
- "Expected spy " + this.actual.identity + " to have been called."
1397
- ];
1398
- };
1399
-
1400
- return !this.actual.wasCalled;
1401
- };
1402
-
1403
- /**
1404
- * Matcher that checks to see if the actual, a Jasmine spy, was called with a set of parameters.
1405
- *
1406
- * @example
1407
- *
1408
- */
1409
- jasmine.Matchers.prototype.toHaveBeenCalledWith = function() {
1410
- var expectedArgs = jasmine.util.argsToArray(arguments);
1411
- if (!jasmine.isSpy(this.actual)) {
1412
- throw new Error('Expected a spy, but got ' + jasmine.pp(this.actual) + '.');
1413
- }
1414
- this.message = function() {
1415
- var invertedMessage = "Expected spy " + this.actual.identity + " not to have been called with " + jasmine.pp(expectedArgs) + " but it was.";
1416
- var positiveMessage = "";
1417
- if (this.actual.callCount === 0) {
1418
- positiveMessage = "Expected spy " + this.actual.identity + " to have been called with " + jasmine.pp(expectedArgs) + " but it was never called.";
1419
- } else {
1420
- 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, '')
1421
- }
1422
- return [positiveMessage, invertedMessage];
1423
- };
1424
-
1425
- return this.env.contains_(this.actual.argsForCall, expectedArgs);
1426
- };
1427
-
1428
- /** @deprecated Use expect(xxx).toHaveBeenCalledWith() instead */
1429
- jasmine.Matchers.prototype.wasCalledWith = jasmine.Matchers.prototype.toHaveBeenCalledWith;
1430
-
1431
- /** @deprecated Use expect(xxx).not.toHaveBeenCalledWith() instead */
1432
- jasmine.Matchers.prototype.wasNotCalledWith = function() {
1433
- var expectedArgs = jasmine.util.argsToArray(arguments);
1434
- if (!jasmine.isSpy(this.actual)) {
1435
- throw new Error('Expected a spy, but got ' + jasmine.pp(this.actual) + '.');
1436
- }
1437
-
1438
- this.message = function() {
1439
- return [
1440
- "Expected spy not to have been called with " + jasmine.pp(expectedArgs) + " but it was",
1441
- "Expected spy to have been called with " + jasmine.pp(expectedArgs) + " but it was"
1442
- ];
1443
- };
1444
-
1445
- return !this.env.contains_(this.actual.argsForCall, expectedArgs);
1446
- };
1447
-
1448
- /**
1449
- * Matcher that checks that the expected item is an element in the actual Array.
1450
- *
1451
- * @param {Object} expected
1452
- */
1453
- jasmine.Matchers.prototype.toContain = function(expected) {
1454
- return this.env.contains_(this.actual, expected);
1455
- };
1456
-
1457
- /**
1458
- * Matcher that checks that the expected item is NOT an element in the actual Array.
1459
- *
1460
- * @param {Object} expected
1461
- * @deprecated as of 1.0. Use not.toContain() instead.
1462
- */
1463
- jasmine.Matchers.prototype.toNotContain = function(expected) {
1464
- return !this.env.contains_(this.actual, expected);
1465
- };
1466
-
1467
- jasmine.Matchers.prototype.toBeLessThan = function(expected) {
1468
- return this.actual < expected;
1469
- };
1470
-
1471
- jasmine.Matchers.prototype.toBeGreaterThan = function(expected) {
1472
- return this.actual > expected;
1473
- };
1474
-
1475
- /**
1476
- * Matcher that checks that the expected item is equal to the actual item
1477
- * up to a given level of decimal precision (default 2).
1478
- *
1479
- * @param {Number} expected
1480
- * @param {Number} precision, as number of decimal places
1481
- */
1482
- jasmine.Matchers.prototype.toBeCloseTo = function(expected, precision) {
1483
- if (!(precision === 0)) {
1484
- precision = precision || 2;
1485
- }
1486
- return Math.abs(expected - this.actual) < (Math.pow(10, -precision) / 2);
1487
- };
1488
-
1489
- /**
1490
- * Matcher that checks that the expected exception was thrown by the actual.
1491
- *
1492
- * @param {String} [expected]
1493
- */
1494
- jasmine.Matchers.prototype.toThrow = function(expected) {
1495
- var result = false;
1496
- var exception;
1497
- if (typeof this.actual != 'function') {
1498
- throw new Error('Actual is not a function');
1499
- }
1500
- try {
1501
- this.actual();
1502
- } catch (e) {
1503
- exception = e;
1504
- }
1505
- if (exception) {
1506
- result = (expected === jasmine.undefined || this.env.equals_(exception.message || exception, expected.message || expected));
1507
- }
1508
-
1509
- var not = this.isNot ? "not " : "";
1510
-
1511
- this.message = function() {
1512
- if (exception && (expected === jasmine.undefined || !this.env.equals_(exception.message || exception, expected.message || expected))) {
1513
- return ["Expected function " + not + "to throw", expected ? expected.message || expected : "an exception", ", but it threw", exception.message || exception].join(' ');
1514
- } else {
1515
- return "Expected function to throw an exception.";
1516
- }
1517
- };
1518
-
1519
- return result;
1520
- };
1521
-
1522
- jasmine.Matchers.Any = function(expectedClass) {
1523
- this.expectedClass = expectedClass;
1524
- };
1525
-
1526
- jasmine.Matchers.Any.prototype.jasmineMatches = function(other) {
1527
- if (this.expectedClass == String) {
1528
- return typeof other == 'string' || other instanceof String;
1529
- }
1530
-
1531
- if (this.expectedClass == Number) {
1532
- return typeof other == 'number' || other instanceof Number;
1533
- }
1534
-
1535
- if (this.expectedClass == Function) {
1536
- return typeof other == 'function' || other instanceof Function;
1537
- }
1538
-
1539
- if (this.expectedClass == Object) {
1540
- return typeof other == 'object';
1541
- }
1542
-
1543
- return other instanceof this.expectedClass;
1544
- };
1545
-
1546
- jasmine.Matchers.Any.prototype.jasmineToString = function() {
1547
- return '<jasmine.any(' + this.expectedClass + ')>';
1548
- };
1549
-
1550
- jasmine.Matchers.ObjectContaining = function (sample) {
1551
- this.sample = sample;
1552
- };
1553
-
1554
- jasmine.Matchers.ObjectContaining.prototype.jasmineMatches = function(other, mismatchKeys, mismatchValues) {
1555
- mismatchKeys = mismatchKeys || [];
1556
- mismatchValues = mismatchValues || [];
1557
-
1558
- var env = jasmine.getEnv();
1559
-
1560
- var hasKey = function(obj, keyName) {
1561
- return obj != null && obj[keyName] !== jasmine.undefined;
1562
- };
1563
-
1564
- for (var property in this.sample) {
1565
- if (!hasKey(other, property) && hasKey(this.sample, property)) {
1566
- mismatchKeys.push("expected has key '" + property + "', but missing from actual.");
1567
- }
1568
- else if (!env.equals_(this.sample[property], other[property], mismatchKeys, mismatchValues)) {
1569
- 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.");
1570
- }
1571
- }
1572
-
1573
- return (mismatchKeys.length === 0 && mismatchValues.length === 0);
1574
- };
1575
-
1576
- jasmine.Matchers.ObjectContaining.prototype.jasmineToString = function () {
1577
- return "<jasmine.objectContaining(" + jasmine.pp(this.sample) + ")>";
1578
- };
1579
- // Mock setTimeout, clearTimeout
1580
- // Contributed by Pivotal Computer Systems, www.pivotalsf.com
1581
-
1582
- jasmine.FakeTimer = function() {
1583
- this.reset();
1584
-
1585
- var self = this;
1586
- self.setTimeout = function(funcToCall, millis) {
1587
- self.timeoutsMade++;
1588
- self.scheduleFunction(self.timeoutsMade, funcToCall, millis, false);
1589
- return self.timeoutsMade;
1590
- };
1591
-
1592
- self.setInterval = function(funcToCall, millis) {
1593
- self.timeoutsMade++;
1594
- self.scheduleFunction(self.timeoutsMade, funcToCall, millis, true);
1595
- return self.timeoutsMade;
1596
- };
1597
-
1598
- self.clearTimeout = function(timeoutKey) {
1599
- self.scheduledFunctions[timeoutKey] = jasmine.undefined;
1600
- };
1601
-
1602
- self.clearInterval = function(timeoutKey) {
1603
- self.scheduledFunctions[timeoutKey] = jasmine.undefined;
1604
- };
1605
-
1606
- };
1607
-
1608
- jasmine.FakeTimer.prototype.reset = function() {
1609
- this.timeoutsMade = 0;
1610
- this.scheduledFunctions = {};
1611
- this.nowMillis = 0;
1612
- };
1613
-
1614
- jasmine.FakeTimer.prototype.tick = function(millis) {
1615
- var oldMillis = this.nowMillis;
1616
- var newMillis = oldMillis + millis;
1617
- this.runFunctionsWithinRange(oldMillis, newMillis);
1618
- this.nowMillis = newMillis;
1619
- };
1620
-
1621
- jasmine.FakeTimer.prototype.runFunctionsWithinRange = function(oldMillis, nowMillis) {
1622
- var scheduledFunc;
1623
- var funcsToRun = [];
1624
- for (var timeoutKey in this.scheduledFunctions) {
1625
- scheduledFunc = this.scheduledFunctions[timeoutKey];
1626
- if (scheduledFunc != jasmine.undefined &&
1627
- scheduledFunc.runAtMillis >= oldMillis &&
1628
- scheduledFunc.runAtMillis <= nowMillis) {
1629
- funcsToRun.push(scheduledFunc);
1630
- this.scheduledFunctions[timeoutKey] = jasmine.undefined;
1631
- }
1632
- }
1633
-
1634
- if (funcsToRun.length > 0) {
1635
- funcsToRun.sort(function(a, b) {
1636
- return a.runAtMillis - b.runAtMillis;
1637
- });
1638
- for (var i = 0; i < funcsToRun.length; ++i) {
1639
- try {
1640
- var funcToRun = funcsToRun[i];
1641
- this.nowMillis = funcToRun.runAtMillis;
1642
- funcToRun.funcToCall();
1643
- if (funcToRun.recurring) {
1644
- this.scheduleFunction(funcToRun.timeoutKey,
1645
- funcToRun.funcToCall,
1646
- funcToRun.millis,
1647
- true);
1648
- }
1649
- } catch(e) {
1650
- }
1651
- }
1652
- this.runFunctionsWithinRange(oldMillis, nowMillis);
1653
- }
1654
- };
1655
-
1656
- jasmine.FakeTimer.prototype.scheduleFunction = function(timeoutKey, funcToCall, millis, recurring) {
1657
- this.scheduledFunctions[timeoutKey] = {
1658
- runAtMillis: this.nowMillis + millis,
1659
- funcToCall: funcToCall,
1660
- recurring: recurring,
1661
- timeoutKey: timeoutKey,
1662
- millis: millis
1663
- };
1664
- };
1665
-
1666
- /**
1667
- * @namespace
1668
- */
1669
- jasmine.Clock = {
1670
- defaultFakeTimer: new jasmine.FakeTimer(),
1671
-
1672
- reset: function() {
1673
- jasmine.Clock.assertInstalled();
1674
- jasmine.Clock.defaultFakeTimer.reset();
1675
- },
1676
-
1677
- tick: function(millis) {
1678
- jasmine.Clock.assertInstalled();
1679
- jasmine.Clock.defaultFakeTimer.tick(millis);
1680
- },
1681
-
1682
- runFunctionsWithinRange: function(oldMillis, nowMillis) {
1683
- jasmine.Clock.defaultFakeTimer.runFunctionsWithinRange(oldMillis, nowMillis);
1684
- },
1685
-
1686
- scheduleFunction: function(timeoutKey, funcToCall, millis, recurring) {
1687
- jasmine.Clock.defaultFakeTimer.scheduleFunction(timeoutKey, funcToCall, millis, recurring);
1688
- },
1689
-
1690
- useMock: function() {
1691
- if (!jasmine.Clock.isInstalled()) {
1692
- var spec = jasmine.getEnv().currentSpec;
1693
- spec.after(jasmine.Clock.uninstallMock);
1694
-
1695
- jasmine.Clock.installMock();
1696
- }
1697
- },
1698
-
1699
- installMock: function() {
1700
- jasmine.Clock.installed = jasmine.Clock.defaultFakeTimer;
1701
- },
1702
-
1703
- uninstallMock: function() {
1704
- jasmine.Clock.assertInstalled();
1705
- jasmine.Clock.installed = jasmine.Clock.real;
1706
- },
1707
-
1708
- real: {
1709
- setTimeout: jasmine.getGlobal().setTimeout,
1710
- clearTimeout: jasmine.getGlobal().clearTimeout,
1711
- setInterval: jasmine.getGlobal().setInterval,
1712
- clearInterval: jasmine.getGlobal().clearInterval
1713
- },
1714
-
1715
- assertInstalled: function() {
1716
- if (!jasmine.Clock.isInstalled()) {
1717
- throw new Error("Mock clock is not installed, use jasmine.Clock.useMock()");
1718
- }
1719
- },
1720
-
1721
- isInstalled: function() {
1722
- return jasmine.Clock.installed == jasmine.Clock.defaultFakeTimer;
1723
- },
1724
-
1725
- installed: null
1726
- };
1727
- jasmine.Clock.installed = jasmine.Clock.real;
1728
-
1729
- //else for IE support
1730
- jasmine.getGlobal().setTimeout = function(funcToCall, millis) {
1731
- if (jasmine.Clock.installed.setTimeout.apply) {
1732
- return jasmine.Clock.installed.setTimeout.apply(this, arguments);
1733
- } else {
1734
- return jasmine.Clock.installed.setTimeout(funcToCall, millis);
1735
- }
1736
- };
1737
-
1738
- jasmine.getGlobal().setInterval = function(funcToCall, millis) {
1739
- if (jasmine.Clock.installed.setInterval.apply) {
1740
- return jasmine.Clock.installed.setInterval.apply(this, arguments);
1741
- } else {
1742
- return jasmine.Clock.installed.setInterval(funcToCall, millis);
1743
- }
1744
- };
1745
-
1746
- jasmine.getGlobal().clearTimeout = function(timeoutKey) {
1747
- if (jasmine.Clock.installed.clearTimeout.apply) {
1748
- return jasmine.Clock.installed.clearTimeout.apply(this, arguments);
1749
- } else {
1750
- return jasmine.Clock.installed.clearTimeout(timeoutKey);
1751
- }
1752
- };
1753
-
1754
- jasmine.getGlobal().clearInterval = function(timeoutKey) {
1755
- if (jasmine.Clock.installed.clearTimeout.apply) {
1756
- return jasmine.Clock.installed.clearInterval.apply(this, arguments);
1757
- } else {
1758
- return jasmine.Clock.installed.clearInterval(timeoutKey);
1759
- }
1760
- };
1761
-
1762
- /**
1763
- * @constructor
1764
- */
1765
- jasmine.MultiReporter = function() {
1766
- this.subReporters_ = [];
1767
- };
1768
- jasmine.util.inherit(jasmine.MultiReporter, jasmine.Reporter);
1769
-
1770
- jasmine.MultiReporter.prototype.addReporter = function(reporter) {
1771
- this.subReporters_.push(reporter);
1772
- };
1773
-
1774
1
  (function() {
1775
- var functionNames = [
1776
- "reportRunnerStarting",
1777
- "reportRunnerResults",
1778
- "reportSuiteResults",
1779
- "reportSpecStarting",
1780
- "reportSpecResults",
1781
- "log"
1782
- ];
1783
- for (var i = 0; i < functionNames.length; i++) {
1784
- var functionName = functionNames[i];
1785
- jasmine.MultiReporter.prototype[functionName] = (function(functionName) {
1786
- return function() {
1787
- for (var j = 0; j < this.subReporters_.length; j++) {
1788
- var subReporter = this.subReporters_[j];
1789
- if (subReporter[functionName]) {
1790
- subReporter[functionName].apply(subReporter, arguments);
1791
- }
1792
- }
1793
- };
1794
- })(functionName);
1795
- }
1796
- })();
1797
- /**
1798
- * Holds results for a set of Jasmine spec. Allows for the results array to hold another jasmine.NestedResults
1799
- *
1800
- * @constructor
1801
- */
1802
- jasmine.NestedResults = function() {
1803
- /**
1804
- * The total count of results
1805
- */
1806
- this.totalCount = 0;
1807
- /**
1808
- * Number of passed results
1809
- */
1810
- this.passedCount = 0;
1811
- /**
1812
- * Number of failed results
1813
- */
1814
- this.failedCount = 0;
1815
- /**
1816
- * Was this suite/spec skipped?
1817
- */
1818
- this.skipped = false;
1819
- /**
1820
- * @ignore
1821
- */
1822
- this.items_ = [];
1823
- };
1824
-
1825
- /**
1826
- * Roll up the result counts.
1827
- *
1828
- * @param result
1829
- */
1830
- jasmine.NestedResults.prototype.rollupCounts = function(result) {
1831
- this.totalCount += result.totalCount;
1832
- this.passedCount += result.passedCount;
1833
- this.failedCount += result.failedCount;
1834
- };
1835
-
1836
- /**
1837
- * Adds a log message.
1838
- * @param values Array of message parts which will be concatenated later.
1839
- */
1840
- jasmine.NestedResults.prototype.log = function(values) {
1841
- this.items_.push(new jasmine.MessageResult(values));
1842
- };
1843
-
1844
- /**
1845
- * Getter for the results: message & results.
1846
- */
1847
- jasmine.NestedResults.prototype.getItems = function() {
1848
- return this.items_;
1849
- };
1850
-
1851
- /**
1852
- * Adds a result, tracking counts (total, passed, & failed)
1853
- * @param {jasmine.ExpectationResult|jasmine.NestedResults} result
1854
- */
1855
- jasmine.NestedResults.prototype.addResult = function(result) {
1856
- if (result.type != 'log') {
1857
- if (result.items_) {
1858
- this.rollupCounts(result);
1859
- } else {
1860
- this.totalCount++;
1861
- if (result.passed()) {
1862
- this.passedCount++;
1863
- } else {
1864
- this.failedCount++;
1865
- }
1866
- }
1867
- }
1868
- this.items_.push(result);
1869
- };
1870
-
1871
- /**
1872
- * @returns {Boolean} True if <b>everything</b> below passed
1873
- */
1874
- jasmine.NestedResults.prototype.passed = function() {
1875
- return this.passedCount === this.totalCount;
1876
- };
1877
- /**
1878
- * Base class for pretty printing for expectation results.
1879
- */
1880
- jasmine.PrettyPrinter = function() {
1881
- this.ppNestLevel_ = 0;
1882
- };
1883
-
1884
- /**
1885
- * Formats a value in a nice, human-readable string.
1886
- *
1887
- * @param value
1888
- */
1889
- jasmine.PrettyPrinter.prototype.format = function(value) {
1890
- this.ppNestLevel_++;
1891
- try {
1892
- if (value === jasmine.undefined) {
1893
- this.emitScalar('undefined');
1894
- } else if (value === null) {
1895
- this.emitScalar('null');
1896
- } else if (value === jasmine.getGlobal()) {
1897
- this.emitScalar('<global>');
1898
- } else if (value.jasmineToString) {
1899
- this.emitScalar(value.jasmineToString());
1900
- } else if (typeof value === 'string') {
1901
- this.emitString(value);
1902
- } else if (jasmine.isSpy(value)) {
1903
- this.emitScalar("spy on " + value.identity);
1904
- } else if (value instanceof RegExp) {
1905
- this.emitScalar(value.toString());
1906
- } else if (typeof value === 'function') {
1907
- this.emitScalar('Function');
1908
- } else if (typeof value.nodeType === 'number') {
1909
- this.emitScalar('HTMLNode');
1910
- } else if (value instanceof Date) {
1911
- this.emitScalar('Date(' + value + ')');
1912
- } else if (value.__Jasmine_been_here_before__) {
1913
- this.emitScalar('<circular reference: ' + (jasmine.isArray_(value) ? 'Array' : 'Object') + '>');
1914
- } else if (jasmine.isArray_(value) || typeof value == 'object') {
1915
- value.__Jasmine_been_here_before__ = true;
1916
- if (jasmine.isArray_(value)) {
1917
- this.emitArray(value);
1918
- } else {
1919
- this.emitObject(value);
1920
- }
1921
- delete value.__Jasmine_been_here_before__;
1922
- } else {
1923
- this.emitScalar(value.toString());
1924
- }
1925
- } finally {
1926
- this.ppNestLevel_--;
1927
- }
1928
- };
1929
-
1930
- jasmine.PrettyPrinter.prototype.iterateObject = function(obj, fn) {
1931
- for (var property in obj) {
1932
- if (!obj.hasOwnProperty(property)) continue;
1933
- if (property == '__Jasmine_been_here_before__') continue;
1934
- fn(property, obj.__lookupGetter__ ? (obj.__lookupGetter__(property) !== jasmine.undefined &&
1935
- obj.__lookupGetter__(property) !== null) : false);
1936
- }
1937
- };
1938
-
1939
- jasmine.PrettyPrinter.prototype.emitArray = jasmine.unimplementedMethod_;
1940
- jasmine.PrettyPrinter.prototype.emitObject = jasmine.unimplementedMethod_;
1941
- jasmine.PrettyPrinter.prototype.emitScalar = jasmine.unimplementedMethod_;
1942
- jasmine.PrettyPrinter.prototype.emitString = jasmine.unimplementedMethod_;
1943
-
1944
- jasmine.StringPrettyPrinter = function() {
1945
- jasmine.PrettyPrinter.call(this);
1946
-
1947
- this.string = '';
1948
- };
1949
- jasmine.util.inherit(jasmine.StringPrettyPrinter, jasmine.PrettyPrinter);
1950
-
1951
- jasmine.StringPrettyPrinter.prototype.emitScalar = function(value) {
1952
- this.append(value);
1953
- };
1954
-
1955
- jasmine.StringPrettyPrinter.prototype.emitString = function(value) {
1956
- this.append("'" + value + "'");
1957
- };
1958
-
1959
- jasmine.StringPrettyPrinter.prototype.emitArray = function(array) {
1960
- if (this.ppNestLevel_ > jasmine.MAX_PRETTY_PRINT_DEPTH) {
1961
- this.append("Array");
1962
- return;
1963
- }
1964
-
1965
- this.append('[ ');
1966
- for (var i = 0; i < array.length; i++) {
1967
- if (i > 0) {
1968
- this.append(', ');
1969
- }
1970
- this.format(array[i]);
1971
- }
1972
- this.append(' ]');
1973
- };
1974
-
1975
- jasmine.StringPrettyPrinter.prototype.emitObject = function(obj) {
1976
- if (this.ppNestLevel_ > jasmine.MAX_PRETTY_PRINT_DEPTH) {
1977
- this.append("Object");
1978
- return;
1979
- }
1980
-
1981
- var self = this;
1982
- this.append('{ ');
1983
- var first = true;
1984
-
1985
- this.iterateObject(obj, function(property, isGetter) {
1986
- if (first) {
1987
- first = false;
1988
- } else {
1989
- self.append(', ');
1990
- }
1991
-
1992
- self.append(property);
1993
- self.append(' : ');
1994
- if (isGetter) {
1995
- self.append('<getter>');
1996
- } else {
1997
- self.format(obj[property]);
1998
- }
1999
- });
2000
-
2001
- this.append(' }');
2002
- };
2003
-
2004
- jasmine.StringPrettyPrinter.prototype.append = function(value) {
2005
- this.string += value;
2006
- };
2007
- jasmine.Queue = function(env) {
2008
- this.env = env;
2009
-
2010
- // parallel to blocks. each true value in this array means the block will
2011
- // get executed even if we abort
2012
- this.ensured = [];
2013
- this.blocks = [];
2014
- this.running = false;
2015
- this.index = 0;
2016
- this.offset = 0;
2017
- this.abort = false;
2018
- };
2019
-
2020
- jasmine.Queue.prototype.addBefore = function(block, ensure) {
2021
- if (ensure === jasmine.undefined) {
2022
- ensure = false;
2023
- }
2024
-
2025
- this.blocks.unshift(block);
2026
- this.ensured.unshift(ensure);
2027
- };
2028
-
2029
- jasmine.Queue.prototype.add = function(block, ensure) {
2030
- if (ensure === jasmine.undefined) {
2031
- ensure = false;
2032
- }
2033
-
2034
- this.blocks.push(block);
2035
- this.ensured.push(ensure);
2036
- };
2037
-
2038
- jasmine.Queue.prototype.insertNext = function(block, ensure) {
2039
- if (ensure === jasmine.undefined) {
2040
- ensure = false;
2041
- }
2042
-
2043
- this.ensured.splice((this.index + this.offset + 1), 0, ensure);
2044
- this.blocks.splice((this.index + this.offset + 1), 0, block);
2045
- this.offset++;
2046
- };
2047
-
2048
- jasmine.Queue.prototype.start = function(onComplete) {
2049
- this.running = true;
2050
- this.onComplete = onComplete;
2051
- this.next_();
2052
- };
2053
-
2054
- jasmine.Queue.prototype.isRunning = function() {
2055
- return this.running;
2056
- };
2057
-
2058
- jasmine.Queue.LOOP_DONT_RECURSE = true;
2059
-
2060
- jasmine.Queue.prototype.next_ = function() {
2061
- var self = this;
2062
- var goAgain = true;
2063
-
2064
- while (goAgain) {
2065
- goAgain = false;
2066
-
2067
- if (self.index < self.blocks.length && !(this.abort && !this.ensured[self.index])) {
2068
- var calledSynchronously = true;
2069
- var completedSynchronously = false;
2070
-
2071
- var onComplete = function () {
2072
- if (jasmine.Queue.LOOP_DONT_RECURSE && calledSynchronously) {
2073
- completedSynchronously = true;
2074
- return;
2075
- }
2076
-
2077
- if (self.blocks[self.index].abort) {
2078
- self.abort = true;
2079
- }
2080
-
2081
- self.offset = 0;
2082
- self.index++;
2083
-
2084
- var now = new Date().getTime();
2085
- if (self.env.updateInterval && now - self.env.lastUpdate > self.env.updateInterval) {
2086
- self.env.lastUpdate = now;
2087
- self.env.setTimeout(function() {
2088
- self.next_();
2089
- }, 0);
2090
- } else {
2091
- if (jasmine.Queue.LOOP_DONT_RECURSE && completedSynchronously) {
2092
- goAgain = true;
2093
- } else {
2094
- self.next_();
2095
- }
2096
- }
2097
- };
2098
- self.blocks[self.index].execute(onComplete);
2099
-
2100
- calledSynchronously = false;
2101
- if (completedSynchronously) {
2102
- onComplete();
2103
- }
2104
-
2105
- } else {
2106
- self.running = false;
2107
- if (self.onComplete) {
2108
- self.onComplete();
2109
- }
2110
- }
2111
- }
2112
- };
2113
-
2114
- jasmine.Queue.prototype.results = function() {
2115
- var results = new jasmine.NestedResults();
2116
- for (var i = 0; i < this.blocks.length; i++) {
2117
- if (this.blocks[i].results) {
2118
- results.addResult(this.blocks[i].results());
2119
- }
2120
- }
2121
- return results;
2122
- };
2123
-
2124
-
2125
- /**
2126
- * Runner
2127
- *
2128
- * @constructor
2129
- * @param {jasmine.Env} env
2130
- */
2131
- jasmine.Runner = function(env) {
2132
- var self = this;
2133
- self.env = env;
2134
- self.queue = new jasmine.Queue(env);
2135
- self.before_ = [];
2136
- self.after_ = [];
2137
- self.suites_ = [];
2138
- };
2139
-
2140
- jasmine.Runner.prototype.execute = function() {
2141
- var self = this;
2142
- if (self.env.reporter.reportRunnerStarting) {
2143
- self.env.reporter.reportRunnerStarting(this);
2144
- }
2145
- self.queue.start(function () {
2146
- self.finishCallback();
2147
- });
2148
- };
2149
-
2150
- jasmine.Runner.prototype.beforeEach = function(beforeEachFunction) {
2151
- beforeEachFunction.typeName = 'beforeEach';
2152
- this.before_.splice(0,0,beforeEachFunction);
2153
- };
2154
-
2155
- jasmine.Runner.prototype.afterEach = function(afterEachFunction) {
2156
- afterEachFunction.typeName = 'afterEach';
2157
- this.after_.splice(0,0,afterEachFunction);
2158
- };
2159
-
2160
-
2161
- jasmine.Runner.prototype.finishCallback = function() {
2162
- this.env.reporter.reportRunnerResults(this);
2163
- };
2164
-
2165
- jasmine.Runner.prototype.addSuite = function(suite) {
2166
- this.suites_.push(suite);
2167
- };
2168
-
2169
- jasmine.Runner.prototype.add = function(block) {
2170
- if (block instanceof jasmine.Suite) {
2171
- this.addSuite(block);
2172
- }
2173
- this.queue.add(block);
2174
- };
2175
-
2176
- jasmine.Runner.prototype.specs = function () {
2177
- var suites = this.suites();
2178
- var specs = [];
2179
- for (var i = 0; i < suites.length; i++) {
2180
- specs = specs.concat(suites[i].specs());
2181
- }
2182
- return specs;
2183
- };
2184
-
2185
- jasmine.Runner.prototype.suites = function() {
2186
- return this.suites_;
2187
- };
2188
-
2189
- jasmine.Runner.prototype.topLevelSuites = function() {
2190
- var topLevelSuites = [];
2191
- for (var i = 0; i < this.suites_.length; i++) {
2192
- if (!this.suites_[i].parentSuite) {
2193
- topLevelSuites.push(this.suites_[i]);
2194
- }
2195
- }
2196
- return topLevelSuites;
2197
- };
2198
-
2199
- jasmine.Runner.prototype.results = function() {
2200
- return this.queue.results();
2201
- };
2202
- /**
2203
- * Internal representation of a Jasmine specification, or test.
2204
- *
2205
- * @constructor
2206
- * @param {jasmine.Env} env
2207
- * @param {jasmine.Suite} suite
2208
- * @param {String} description
2209
- */
2210
- jasmine.Spec = function(env, suite, description) {
2211
- if (!env) {
2212
- throw new Error('jasmine.Env() required');
2213
- }
2214
- if (!suite) {
2215
- throw new Error('jasmine.Suite() required');
2216
- }
2217
- var spec = this;
2218
- spec.id = env.nextSpecId ? env.nextSpecId() : null;
2219
- spec.env = env;
2220
- spec.suite = suite;
2221
- spec.description = description;
2222
- spec.queue = new jasmine.Queue(env);
2223
-
2224
- spec.afterCallbacks = [];
2225
- spec.spies_ = [];
2226
-
2227
- spec.results_ = new jasmine.NestedResults();
2228
- spec.results_.description = description;
2229
- spec.matchersClass = null;
2230
- };
2231
-
2232
- jasmine.Spec.prototype.getFullName = function() {
2233
- return this.suite.getFullName() + ' ' + this.description + '.';
2234
- };
2235
-
2236
-
2237
- jasmine.Spec.prototype.results = function() {
2238
- return this.results_;
2239
- };
2240
-
2241
- /**
2242
- * All parameters are pretty-printed and concatenated together, then written to the spec's output.
2243
- *
2244
- * Be careful not to leave calls to <code>jasmine.log</code> in production code.
2245
- */
2246
- jasmine.Spec.prototype.log = function() {
2247
- return this.results_.log(arguments);
2248
- };
2249
-
2250
- jasmine.Spec.prototype.runs = function (func) {
2251
- var block = new jasmine.Block(this.env, func, this);
2252
- this.addToQueue(block);
2253
- return this;
2254
- };
2255
-
2256
- jasmine.Spec.prototype.addToQueue = function (block) {
2257
- if (this.queue.isRunning()) {
2258
- this.queue.insertNext(block);
2259
- } else {
2260
- this.queue.add(block);
2261
- }
2262
- };
2263
-
2264
- /**
2265
- * @param {jasmine.ExpectationResult} result
2266
- */
2267
- jasmine.Spec.prototype.addMatcherResult = function(result) {
2268
- this.results_.addResult(result);
2269
- };
2270
-
2271
- jasmine.Spec.prototype.expect = function(actual) {
2272
- var positive = new (this.getMatchersClass_())(this.env, actual, this);
2273
- positive.not = new (this.getMatchersClass_())(this.env, actual, this, true);
2274
- return positive;
2275
- };
2276
-
2277
- /**
2278
- * Waits a fixed time period before moving to the next block.
2279
- *
2280
- * @deprecated Use waitsFor() instead
2281
- * @param {Number} timeout milliseconds to wait
2282
- */
2283
- jasmine.Spec.prototype.waits = function(timeout) {
2284
- var waitsFunc = new jasmine.WaitsBlock(this.env, timeout, this);
2285
- this.addToQueue(waitsFunc);
2286
- return this;
2287
- };
2288
-
2289
- /**
2290
- * Waits for the latchFunction to return true before proceeding to the next block.
2291
- *
2292
- * @param {Function} latchFunction
2293
- * @param {String} optional_timeoutMessage
2294
- * @param {Number} optional_timeout
2295
- */
2296
- jasmine.Spec.prototype.waitsFor = function(latchFunction, optional_timeoutMessage, optional_timeout) {
2297
- var latchFunction_ = null;
2298
- var optional_timeoutMessage_ = null;
2299
- var optional_timeout_ = null;
2300
-
2301
- for (var i = 0; i < arguments.length; i++) {
2302
- var arg = arguments[i];
2303
- switch (typeof arg) {
2304
- case 'function':
2305
- latchFunction_ = arg;
2306
- break;
2307
- case 'string':
2308
- optional_timeoutMessage_ = arg;
2309
- break;
2310
- case 'number':
2311
- optional_timeout_ = arg;
2312
- break;
2313
- }
2314
- }
2315
-
2316
- var waitsForFunc = new jasmine.WaitsForBlock(this.env, optional_timeout_, latchFunction_, optional_timeoutMessage_, this);
2317
- this.addToQueue(waitsForFunc);
2318
- return this;
2319
- };
2320
-
2321
- jasmine.Spec.prototype.fail = function (e) {
2322
- var expectationResult = new jasmine.ExpectationResult({
2323
- passed: false,
2324
- message: e ? jasmine.util.formatException(e) : 'Exception',
2325
- trace: { stack: e.stack }
2326
- });
2327
- this.results_.addResult(expectationResult);
2328
- };
2329
-
2330
- jasmine.Spec.prototype.getMatchersClass_ = function() {
2331
- return this.matchersClass || this.env.matchersClass;
2332
- };
2333
-
2334
- jasmine.Spec.prototype.addMatchers = function(matchersPrototype) {
2335
- var parent = this.getMatchersClass_();
2336
- var newMatchersClass = function() {
2337
- parent.apply(this, arguments);
2338
- };
2339
- jasmine.util.inherit(newMatchersClass, parent);
2340
- jasmine.Matchers.wrapInto_(matchersPrototype, newMatchersClass);
2341
- this.matchersClass = newMatchersClass;
2342
- };
2343
-
2344
- jasmine.Spec.prototype.finishCallback = function() {
2345
- this.env.reporter.reportSpecResults(this);
2346
- };
2347
-
2348
- jasmine.Spec.prototype.finish = function(onComplete) {
2349
- this.removeAllSpies();
2350
- this.finishCallback();
2351
- if (onComplete) {
2352
- onComplete();
2353
- }
2354
- };
2355
-
2356
- jasmine.Spec.prototype.after = function(doAfter) {
2357
- if (this.queue.isRunning()) {
2358
- this.queue.add(new jasmine.Block(this.env, doAfter, this), true);
2359
- } else {
2360
- this.afterCallbacks.unshift(doAfter);
2361
- }
2362
- };
2363
-
2364
- jasmine.Spec.prototype.execute = function(onComplete) {
2365
- var spec = this;
2366
- if (!spec.env.specFilter(spec)) {
2367
- spec.results_.skipped = true;
2368
- spec.finish(onComplete);
2369
- return;
2370
- }
2371
-
2372
- this.env.reporter.reportSpecStarting(this);
2373
-
2374
- spec.env.currentSpec = spec;
2375
-
2376
- spec.addBeforesAndAftersToQueue();
2377
-
2378
- spec.queue.start(function () {
2379
- spec.finish(onComplete);
2380
- });
2381
- };
2382
-
2383
- jasmine.Spec.prototype.addBeforesAndAftersToQueue = function() {
2384
- var runner = this.env.currentRunner();
2385
- var i;
2386
-
2387
- for (var suite = this.suite; suite; suite = suite.parentSuite) {
2388
- for (i = 0; i < suite.before_.length; i++) {
2389
- this.queue.addBefore(new jasmine.Block(this.env, suite.before_[i], this));
2390
- }
2391
- }
2392
- for (i = 0; i < runner.before_.length; i++) {
2393
- this.queue.addBefore(new jasmine.Block(this.env, runner.before_[i], this));
2394
- }
2395
- for (i = 0; i < this.afterCallbacks.length; i++) {
2396
- this.queue.add(new jasmine.Block(this.env, this.afterCallbacks[i], this), true);
2397
- }
2398
- for (suite = this.suite; suite; suite = suite.parentSuite) {
2399
- for (i = 0; i < suite.after_.length; i++) {
2400
- this.queue.add(new jasmine.Block(this.env, suite.after_[i], this), true);
2401
- }
2402
- }
2403
- for (i = 0; i < runner.after_.length; i++) {
2404
- this.queue.add(new jasmine.Block(this.env, runner.after_[i], this), true);
2405
- }
2406
- };
2407
-
2408
- jasmine.Spec.prototype.explodes = function() {
2409
- throw 'explodes function should not have been called';
2410
- };
2411
-
2412
- jasmine.Spec.prototype.spyOn = function(obj, methodName, ignoreMethodDoesntExist) {
2413
- if (obj == jasmine.undefined) {
2414
- throw "spyOn could not find an object to spy upon for " + methodName + "()";
2415
- }
2416
-
2417
- if (!ignoreMethodDoesntExist && obj[methodName] === jasmine.undefined) {
2418
- throw methodName + '() method does not exist';
2419
- }
2420
-
2421
- if (!ignoreMethodDoesntExist && obj[methodName] && obj[methodName].isSpy) {
2422
- throw new Error(methodName + ' has already been spied upon');
2423
- }
2424
-
2425
- var spyObj = jasmine.createSpy(methodName);
2426
-
2427
- this.spies_.push(spyObj);
2428
- spyObj.baseObj = obj;
2429
- spyObj.methodName = methodName;
2430
- spyObj.originalValue = obj[methodName];
2431
-
2432
- obj[methodName] = spyObj;
2433
-
2434
- return spyObj;
2435
- };
2436
-
2437
- jasmine.Spec.prototype.removeAllSpies = function() {
2438
- for (var i = 0; i < this.spies_.length; i++) {
2439
- var spy = this.spies_[i];
2440
- spy.baseObj[spy.methodName] = spy.originalValue;
2441
- }
2442
- this.spies_ = [];
2443
- };
2444
-
2445
- /**
2446
- * Internal representation of a Jasmine suite.
2447
- *
2448
- * @constructor
2449
- * @param {jasmine.Env} env
2450
- * @param {String} description
2451
- * @param {Function} specDefinitions
2452
- * @param {jasmine.Suite} parentSuite
2453
- */
2454
- jasmine.Suite = function(env, description, specDefinitions, parentSuite) {
2455
- var self = this;
2456
- self.id = env.nextSuiteId ? env.nextSuiteId() : null;
2457
- self.description = description;
2458
- self.queue = new jasmine.Queue(env);
2459
- self.parentSuite = parentSuite;
2460
- self.env = env;
2461
- self.before_ = [];
2462
- self.after_ = [];
2463
- self.children_ = [];
2464
- self.suites_ = [];
2465
- self.specs_ = [];
2466
- };
2467
-
2468
- jasmine.Suite.prototype.getFullName = function() {
2469
- var fullName = this.description;
2470
- for (var parentSuite = this.parentSuite; parentSuite; parentSuite = parentSuite.parentSuite) {
2471
- fullName = parentSuite.description + ' ' + fullName;
2472
- }
2473
- return fullName;
2474
- };
2475
-
2476
- jasmine.Suite.prototype.finish = function(onComplete) {
2477
- this.env.reporter.reportSuiteResults(this);
2478
- this.finished = true;
2479
- if (typeof(onComplete) == 'function') {
2480
- onComplete();
2481
- }
2482
- };
2483
-
2484
- jasmine.Suite.prototype.beforeEach = function(beforeEachFunction) {
2485
- beforeEachFunction.typeName = 'beforeEach';
2486
- this.before_.unshift(beforeEachFunction);
2487
- };
2488
-
2489
- jasmine.Suite.prototype.afterEach = function(afterEachFunction) {
2490
- afterEachFunction.typeName = 'afterEach';
2491
- this.after_.unshift(afterEachFunction);
2492
- };
2493
-
2494
- jasmine.Suite.prototype.results = function() {
2495
- return this.queue.results();
2496
- };
2497
-
2498
- jasmine.Suite.prototype.add = function(suiteOrSpec) {
2499
- this.children_.push(suiteOrSpec);
2500
- if (suiteOrSpec instanceof jasmine.Suite) {
2501
- this.suites_.push(suiteOrSpec);
2502
- this.env.currentRunner().addSuite(suiteOrSpec);
2503
- } else {
2504
- this.specs_.push(suiteOrSpec);
2505
- }
2506
- this.queue.add(suiteOrSpec);
2507
- };
2508
-
2509
- jasmine.Suite.prototype.specs = function() {
2510
- return this.specs_;
2511
- };
2512
-
2513
- jasmine.Suite.prototype.suites = function() {
2514
- return this.suites_;
2515
- };
2516
-
2517
- jasmine.Suite.prototype.children = function() {
2518
- return this.children_;
2519
- };
2520
-
2521
- jasmine.Suite.prototype.execute = function(onComplete) {
2522
- var self = this;
2523
- this.queue.start(function () {
2524
- self.finish(onComplete);
2525
- });
2526
- };
2527
- jasmine.WaitsBlock = function(env, timeout, spec) {
2528
- this.timeout = timeout;
2529
- jasmine.Block.call(this, env, null, spec);
2530
- };
2531
-
2532
- jasmine.util.inherit(jasmine.WaitsBlock, jasmine.Block);
2533
-
2534
- jasmine.WaitsBlock.prototype.execute = function (onComplete) {
2535
- if (jasmine.VERBOSE) {
2536
- this.env.reporter.log('>> Jasmine waiting for ' + this.timeout + ' ms...');
2537
- }
2538
- this.env.setTimeout(function () {
2539
- onComplete();
2540
- }, this.timeout);
2541
- };
2542
- /**
2543
- * A block which waits for some condition to become true, with timeout.
2544
- *
2545
- * @constructor
2546
- * @extends jasmine.Block
2547
- * @param {jasmine.Env} env The Jasmine environment.
2548
- * @param {Number} timeout The maximum time in milliseconds to wait for the condition to become true.
2549
- * @param {Function} latchFunction A function which returns true when the desired condition has been met.
2550
- * @param {String} message The message to display if the desired condition hasn't been met within the given time period.
2551
- * @param {jasmine.Spec} spec The Jasmine spec.
2552
- */
2553
- jasmine.WaitsForBlock = function(env, timeout, latchFunction, message, spec) {
2554
- this.timeout = timeout || env.defaultTimeoutInterval;
2555
- this.latchFunction = latchFunction;
2556
- this.message = message;
2557
- this.totalTimeSpentWaitingForLatch = 0;
2558
- jasmine.Block.call(this, env, null, spec);
2559
- };
2560
- jasmine.util.inherit(jasmine.WaitsForBlock, jasmine.Block);
2561
-
2562
- jasmine.WaitsForBlock.TIMEOUT_INCREMENT = 10;
2563
-
2564
- jasmine.WaitsForBlock.prototype.execute = function(onComplete) {
2565
- if (jasmine.VERBOSE) {
2566
- this.env.reporter.log('>> Jasmine waiting for ' + (this.message || 'something to happen'));
2567
- }
2568
- var latchFunctionResult;
2569
- try {
2570
- latchFunctionResult = this.latchFunction.apply(this.spec);
2571
- } catch (e) {
2572
- this.spec.fail(e);
2573
- onComplete();
2574
- return;
2575
- }
2576
-
2577
- if (latchFunctionResult) {
2578
- onComplete();
2579
- } else if (this.totalTimeSpentWaitingForLatch >= this.timeout) {
2580
- var message = 'timed out after ' + this.timeout + ' msec waiting for ' + (this.message || 'something to happen');
2581
- this.spec.fail({
2582
- name: 'timeout',
2583
- message: message
2584
- });
2
+ var __hasProp = {}.hasOwnProperty,
3
+ __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
2585
4
 
2586
- this.abort = true;
2587
- onComplete();
2588
- } else {
2589
- this.totalTimeSpentWaitingForLatch += jasmine.WaitsForBlock.TIMEOUT_INCREMENT;
2590
- var self = this;
2591
- this.env.setTimeout(function() {
2592
- self.execute(onComplete);
2593
- }, jasmine.WaitsForBlock.TIMEOUT_INCREMENT);
2594
- }
2595
- };
2596
-
2597
- jasmine.version_= {
2598
- "major": 1,
2599
- "minor": 3,
2600
- "build": 1,
2601
- "revision": 1354556913
2602
- };
2603
- (function() {
2604
5
  this.Teaspoon = (function() {
2605
6
  function Teaspoon() {}
2606
7
 
@@ -2608,7 +9,7 @@ jasmine.version_= {
2608
9
 
2609
10
  Teaspoon.slow = 75;
2610
11
 
2611
- Teaspoon.root = null;
12
+ Teaspoon.root = window.location.pathname.replace(/\/+(index\.html)?$/, "").replace(/\/[^\/]*$/, "");
2612
13
 
2613
14
  Teaspoon.started = false;
2614
15
 
@@ -2697,6 +98,18 @@ jasmine.version_= {
2697
98
 
2698
99
  })();
2699
100
 
101
+ Teaspoon.Error = (function(_super) {
102
+ __extends(Error, _super);
103
+
104
+ function Error(message) {
105
+ this.name = "TeaspoonError";
106
+ this.message = message || "";
107
+ }
108
+
109
+ return Error;
110
+
111
+ })(Error);
112
+
2700
113
  }).call(this);
2701
114
  (function() {
2702
115
  Teaspoon.Runner = (function() {
@@ -2714,7 +127,6 @@ jasmine.version_= {
2714
127
 
2715
128
  Runner.prototype.getParams = function() {
2716
129
  var name, param, params, value, _i, _len, _ref, _ref1;
2717
-
2718
130
  params = {};
2719
131
  _ref = Teaspoon.location.search.substring(1).split("&");
2720
132
  for (_i = 0, _len = _ref.length; _i < _len; _i++) {
@@ -2761,7 +173,6 @@ jasmine.version_= {
2761
173
 
2762
174
  fixture.preload = function() {
2763
175
  var url, urls, _i, _len, _results;
2764
-
2765
176
  urls = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
2766
177
  _results = [];
2767
178
  for (_i = 0, _len = urls.length; _i < _len; _i++) {
@@ -2773,7 +184,6 @@ jasmine.version_= {
2773
184
 
2774
185
  fixture.load = function() {
2775
186
  var append, index, url, urls, _i, _j, _len, _results;
2776
-
2777
187
  urls = 2 <= arguments.length ? __slice.call(arguments, 0, _i = arguments.length - 1) : (_i = 0, []), append = arguments[_i++];
2778
188
  if (append == null) {
2779
189
  append = false;
@@ -2792,7 +202,6 @@ jasmine.version_= {
2792
202
 
2793
203
  fixture.set = function() {
2794
204
  var append, html, htmls, index, _i, _j, _len, _results;
2795
-
2796
205
  htmls = 2 <= arguments.length ? __slice.call(arguments, 0, _i = arguments.length - 1) : (_i = 0, []), append = arguments[_i++];
2797
206
  if (append == null) {
2798
207
  append = false;
@@ -2825,7 +234,6 @@ jasmine.version_= {
2825
234
 
2826
235
  load = function(url, append, preload) {
2827
236
  var cached, value;
2828
-
2829
237
  if (preload == null) {
2830
238
  preload = false;
2831
239
  }
@@ -2887,7 +295,6 @@ jasmine.version_= {
2887
295
 
2888
296
  create = function() {
2889
297
  var _ref;
2890
-
2891
298
  Teaspoon.fixture.el = document.createElement("div");
2892
299
  if (typeof window.$ === 'function') {
2893
300
  Teaspoon.fixture.$el = $(Teaspoon.fixture.el);
@@ -2898,7 +305,6 @@ jasmine.version_= {
2898
305
 
2899
306
  cleanup = function() {
2900
307
  var _base, _ref, _ref1;
2901
-
2902
308
  (_base = Teaspoon.fixture).el || (_base.el = document.getElementById("teaspoon-fixtures"));
2903
309
  if ((_ref = Teaspoon.fixture.el) != null) {
2904
310
  if ((_ref1 = _ref.parentNode) != null) {
@@ -2910,7 +316,6 @@ jasmine.version_= {
2910
316
 
2911
317
  xhrRequest = function(url, callback) {
2912
318
  var e;
2913
-
2914
319
  if (window.XMLHttpRequest) {
2915
320
  xhr = new XMLHttpRequest();
2916
321
  } else if (window.ActiveXObject) {
@@ -2937,6 +342,47 @@ jasmine.version_= {
2937
342
 
2938
343
  }).call(this);
2939
344
 
345
+ }).call(this);
346
+ (function() {
347
+ Teaspoon.hook = function(name, options) {
348
+ var xhr, xhrRequest;
349
+ if (options == null) {
350
+ options = {};
351
+ }
352
+ xhr = null;
353
+ xhrRequest = function(url, options, callback) {
354
+ var e;
355
+ if (window.XMLHttpRequest) {
356
+ xhr = new XMLHttpRequest();
357
+ } else if (window.ActiveXObject) {
358
+ try {
359
+ xhr = new ActiveXObject("Msxml2.XMLHTTP");
360
+ } catch (_error) {
361
+ e = _error;
362
+ try {
363
+ xhr = new ActiveXObject("Microsoft.XMLHTTP");
364
+ } catch (_error) {
365
+ e = _error;
366
+ }
367
+ }
368
+ }
369
+ if (!xhr) {
370
+ throw "Unable to make Ajax Request";
371
+ }
372
+ xhr.onreadystatechange = callback;
373
+ xhr.open(options['method'] || "GET", "" + Teaspoon.root + "/" + url, false);
374
+ return xhr.send(options['payload']);
375
+ };
376
+ return xhrRequest("" + Teaspoon.suites.active + "/" + name, options, function() {
377
+ if (xhr.readyState !== 4) {
378
+ return;
379
+ }
380
+ if (xhr.status !== 200) {
381
+ throw "Unable to call hook \"" + url + "\".";
382
+ }
383
+ });
384
+ };
385
+
2940
386
  }).call(this);
2941
387
  (function() {
2942
388
  Teaspoon.Reporters.BaseView = (function() {
@@ -2959,7 +405,6 @@ jasmine.version_= {
2959
405
 
2960
406
  BaseView.prototype.createEl = function(type, className) {
2961
407
  var el;
2962
-
2963
408
  if (className == null) {
2964
409
  className = "";
2965
410
  }
@@ -2970,21 +415,18 @@ jasmine.version_= {
2970
415
 
2971
416
  BaseView.prototype.findEl = function(id) {
2972
417
  var _base;
2973
-
2974
418
  this.elements || (this.elements = {});
2975
419
  return (_base = this.elements)[id] || (_base[id] = document.getElementById("teaspoon-" + id));
2976
420
  };
2977
421
 
2978
422
  BaseView.prototype.setText = function(id, value) {
2979
423
  var el;
2980
-
2981
424
  el = this.findEl(id);
2982
425
  return el.innerHTML = value;
2983
426
  };
2984
427
 
2985
428
  BaseView.prototype.setHtml = function(id, value, add) {
2986
429
  var el;
2987
-
2988
430
  if (add == null) {
2989
431
  add = false;
2990
432
  }
@@ -2998,14 +440,12 @@ jasmine.version_= {
2998
440
 
2999
441
  BaseView.prototype.setClass = function(id, value) {
3000
442
  var el;
3001
-
3002
443
  el = this.findEl(id);
3003
444
  return el.className = value;
3004
445
  };
3005
446
 
3006
447
  BaseView.prototype.htmlSafe = function(str) {
3007
448
  var el;
3008
-
3009
449
  el = document.createElement("div");
3010
450
  el.appendChild(document.createTextNode(str));
3011
451
  return el.innerHTML;
@@ -3025,6 +465,7 @@ jasmine.version_= {
3025
465
  __extends(HTML, _super);
3026
466
 
3027
467
  function HTML() {
468
+ this.changeSuite = __bind(this.changeSuite, this);
3028
469
  this.toggleConfig = __bind(this.toggleConfig, this);
3029
470
  this.reportRunnerResults = __bind(this.reportRunnerResults, this);
3030
471
  this.start = new Teaspoon.Date().getTime();
@@ -3060,7 +501,6 @@ jasmine.version_= {
3060
501
  if ((_ref = this.findEl("suite-select")) != null) {
3061
502
  _ref.onchange = this.changeSuite;
3062
503
  }
3063
- this.findEl("root-link").href = Teaspoon.root;
3064
504
  this.el = this.findEl("report-all");
3065
505
  this.showConfiguration();
3066
506
  this.buildProgress();
@@ -3071,20 +511,26 @@ jasmine.version_= {
3071
511
  var el;
3072
512
  el = this.createEl("div");
3073
513
  el.id = "teaspoon-interface";
3074
- el.innerHTML = Teaspoon.Reporters.HTML.template;
514
+ el.innerHTML = Teaspoon.Reporters.HTML.template();
3075
515
  return document.body.appendChild(el);
3076
516
  };
3077
517
 
3078
518
  HTML.prototype.buildSuiteSelect = function() {
3079
- var options, suite, _i, _len, _ref;
519
+ var filename, options, path, selected, suite, _i, _len, _ref;
3080
520
  if (Teaspoon.suites.all.length === 1) {
3081
521
  return "";
3082
522
  }
523
+ filename = "";
524
+ if (/index\.html$/.test(window.location.pathname)) {
525
+ filename = "/index.html";
526
+ }
3083
527
  options = [];
3084
528
  _ref = Teaspoon.suites.all;
3085
529
  for (_i = 0, _len = _ref.length; _i < _len; _i++) {
3086
530
  suite = _ref[_i];
3087
- options.push("<option" + (Teaspoon.suites.active === suite ? " selected='selected'" : "") + " value=\"" + suite + "\">" + suite + "</option>");
531
+ path = [Teaspoon.root, suite].join("/");
532
+ selected = Teaspoon.suites.active === suite ? " selected" : "";
533
+ options.push("<option" + selected + " value=\"" + path + filename + "\">" + suite + "</option>");
3088
534
  }
3089
535
  return "<select id=\"teaspoon-suite-select\">" + (options.join("")) + "</select>";
3090
536
  };
@@ -3195,19 +641,17 @@ jasmine.version_= {
3195
641
  };
3196
642
 
3197
643
  HTML.prototype.setFilters = function() {
3198
- var link;
3199
- link = [Teaspoon.root, Teaspoon.suites.active].join('/');
3200
644
  if (Teaspoon.params["file"]) {
3201
- this.filters.push("by file: " + Teaspoon.params["file"] + " <a href='" + link + "'>remove</a>");
645
+ this.filters.push("by file: " + Teaspoon.params["file"]);
3202
646
  }
3203
647
  if (Teaspoon.params["grep"]) {
3204
- return this.filters.push("by match: " + Teaspoon.params["grep"] + " <a href='" + link + "'>remove</a>");
648
+ return this.filters.push("by match: " + Teaspoon.params["grep"]);
3205
649
  }
3206
650
  };
3207
651
 
3208
652
  HTML.prototype.readConfig = function() {
3209
653
  var config;
3210
- if (config = this.cookie("teaspoon")) {
654
+ if (config = this.store("teaspoon")) {
3211
655
  return this.config = config;
3212
656
  }
3213
657
  };
@@ -3220,16 +664,23 @@ jasmine.version_= {
3220
664
  }
3221
665
  name = button.getAttribute("id").replace(/^teaspoon-/, "");
3222
666
  this.config[name] = !this.config[name];
3223
- this.cookie("teaspoon", this.config);
3224
- return this.refresh();
667
+ this.store("teaspoon", this.config);
668
+ return Teaspoon.reload();
3225
669
  };
3226
670
 
3227
- HTML.prototype.changeSuite = function() {
3228
- return window.location.href = [Teaspoon.root, this.options[this.options.selectedIndex].value].join('/');
671
+ HTML.prototype.changeSuite = function(e) {
672
+ var options;
673
+ options = e.target.options;
674
+ return window.location.href = options[options.selectedIndex].value;
3229
675
  };
3230
676
 
3231
- HTML.prototype.refresh = function() {
3232
- return window.location.href = window.location.href;
677
+ HTML.prototype.store = function(name, value) {
678
+ var _ref;
679
+ if (((_ref = window.localStorage) != null ? _ref.setItem : void 0) != null) {
680
+ return this.localstore(name, value);
681
+ } else {
682
+ return this.cookie(name, value);
683
+ }
3233
684
  };
3234
685
 
3235
686
  HTML.prototype.cookie = function(name, value) {
@@ -3248,6 +699,17 @@ jasmine.version_= {
3248
699
  }
3249
700
  };
3250
701
 
702
+ HTML.prototype.localstore = function(name, value) {
703
+ if (value == null) {
704
+ value = void 0;
705
+ }
706
+ if (value === void 0) {
707
+ return JSON.parse(unescape(localStorage.getItem(name)));
708
+ } else {
709
+ return localStorage.setItem(name, escape(JSON.stringify(value)));
710
+ }
711
+ };
712
+
3251
713
  return HTML;
3252
714
 
3253
715
  })(Teaspoon.Reporters.BaseView);
@@ -3281,7 +743,7 @@ jasmine.version_= {
3281
743
  };
3282
744
 
3283
745
  ProgressView.prototype.build = function() {
3284
- return this.el = this.createEl("div", "teaspoon-indicator modeset-logo");
746
+ return this.el = this.createEl("div", "teaspoon-indicator teaspoon-logo");
3285
747
  };
3286
748
 
3287
749
  ProgressView.prototype.update = function() {};
@@ -3305,7 +767,6 @@ jasmine.version_= {
3305
767
 
3306
768
  SimpleProgressView.prototype.update = function(total, run) {
3307
769
  var percent;
3308
-
3309
770
  percent = total ? Math.ceil((run * 100) / total) : 0;
3310
771
  return this.setHtml("progress-percent", "" + percent + "%");
3311
772
  };
@@ -3331,7 +792,6 @@ jasmine.version_= {
3331
792
 
3332
793
  RadialProgressView.prototype.appendTo = function() {
3333
794
  var canvas, e;
3334
-
3335
795
  RadialProgressView.__super__.appendTo.apply(this, arguments);
3336
796
  this.size = 80;
3337
797
  try {
@@ -3347,7 +807,6 @@ jasmine.version_= {
3347
807
 
3348
808
  RadialProgressView.prototype.update = function(total, run) {
3349
809
  var half, percent;
3350
-
3351
810
  percent = total ? Math.ceil((run * 100) / total) : 0;
3352
811
  this.setHtml("progress-percent", "" + percent + "%");
3353
812
  if (!this.ctx) {
@@ -3539,7 +998,9 @@ jasmine.version_= {
3539
998
 
3540
999
  }).call(this);
3541
1000
  (function() {
3542
- Teaspoon.Reporters.HTML.template = "<div class=\"teaspoon-clearfix\">\n <div id=\"teaspoon-title\">\n <h1><a href=\"\" id=\"teaspoon-root-link\">Teaspoon</a></h1>\n <ul>\n <li>version: <b id=\"teaspoon-version\"></b></li>\n <li id=\"teaspoon-env-info\"></li>\n </ul>\n </div>\n <div id=\"teaspoon-progress\"></div>\n <ul id=\"teaspoon-stats\">\n <li>passes: <b id=\"teaspoon-stats-passes\">0</b></li>\n <li>failures: <b id=\"teaspoon-stats-failures\">0</b></li>\n <li>skipped: <b id=\"teaspoon-stats-skipped\">0</b></li>\n <li>duration: <b id=\"teaspoon-stats-duration\">&infin;</b></li>\n </ul>\n</div>\n\n<div id=\"teaspoon-controls\" class=\"teaspoon-clearfix\">\n <div id=\"teaspoon-toggles\">\n <button id=\"teaspoon-use-catch\" title=\"Toggle using try/catch wrappers when possible\">Try/Catch</button>\n <button id=\"teaspoon-build-full-report\" title=\"Toggle building the full report\">Full Report</button>\n <button id=\"teaspoon-display-progress\" title=\"Toggle displaying progress as tests run\">Progress</button>\n </div>\n <div id=\"teaspoon-suites\"></div>\n</div>\n\n<hr/>\n\n<div id=\"teaspoon-filter\">\n <h1>Filtering</h1>\n <ul id=\"teaspoon-filter-list\"></ul>\n</div>\n\n<div id=\"teaspoon-report\">\n <ol id=\"teaspoon-report-failures\"></ol>\n <ol id=\"teaspoon-report-all\"></ol>\n</div>";
1001
+ Teaspoon.Reporters.HTML.template = function() {
1002
+ return "<div class=\"teaspoon-clearfix\">\n <div id=\"teaspoon-title\">\n <h1><a href=\"" + Teaspoon.root + "\" id=\"teaspoon-root-link\">Teaspoon</a></h1>\n <ul>\n <li>version: <b id=\"teaspoon-version\"></b></li>\n <li id=\"teaspoon-env-info\"></li>\n </ul>\n </div>\n <div id=\"teaspoon-progress\"></div>\n <ul id=\"teaspoon-stats\">\n <li>passes: <b id=\"teaspoon-stats-passes\">0</b></li>\n <li>failures: <b id=\"teaspoon-stats-failures\">0</b></li>\n <li>skipped: <b id=\"teaspoon-stats-skipped\">0</b></li>\n <li>duration: <b id=\"teaspoon-stats-duration\">&infin;</b></li>\n </ul>\n</div>\n\n<div id=\"teaspoon-controls\" class=\"teaspoon-clearfix\">\n <div id=\"teaspoon-toggles\">\n <button id=\"teaspoon-use-catch\" title=\"Toggle using try/catch wrappers when possible\">Try/Catch</button>\n <button id=\"teaspoon-build-full-report\" title=\"Toggle building the full report\">Full Report</button>\n <button id=\"teaspoon-display-progress\" title=\"Toggle displaying progress as tests run\">Progress</button>\n </div>\n <div id=\"teaspoon-suites\"></div>\n</div>\n\n<hr/>\n\n<div id=\"teaspoon-filter\">\n <h1>Applied Filters [<a href=\"" + window.location.pathname + "\" id=\"teaspoon-filter-clear\">remove</a>]</h1>\n <ul id=\"teaspoon-filter-list\"></ul>\n</div>\n\n<div id=\"teaspoon-report\">\n <ol id=\"teaspoon-report-failures\"></ol>\n <ol id=\"teaspoon-report-all\"></ol>\n</div>";
1003
+ };
3543
1004
 
3544
1005
  }).call(this);
3545
1006
  (function() {
@@ -3547,7 +1008,8 @@ jasmine.version_= {
3547
1008
 
3548
1009
  Teaspoon.Reporters.Console = (function() {
3549
1010
  function Console() {
3550
- this.reportRunnerResults = __bind(this.reportRunnerResults, this); this.start = new Teaspoon.Date();
1011
+ this.reportRunnerResults = __bind(this.reportRunnerResults, this);
1012
+ this.start = new Teaspoon.Date();
3551
1013
  this.suites = {};
3552
1014
  }
3553
1015
 
@@ -3561,7 +1023,6 @@ jasmine.version_= {
3561
1023
 
3562
1024
  Console.prototype.reportSuites = function() {
3563
1025
  var index, suite, _i, _len, _ref, _results;
3564
-
3565
1026
  _ref = this.spec.getParents();
3566
1027
  _results = [];
3567
1028
  for (index = _i = 0, _len = _ref.length; _i < _len; index = ++_i) {
@@ -3581,7 +1042,6 @@ jasmine.version_= {
3581
1042
 
3582
1043
  Console.prototype.reportSpecResults = function(spec) {
3583
1044
  var result;
3584
-
3585
1045
  this.spec = new Teaspoon.Spec(spec);
3586
1046
  result = this.spec.result();
3587
1047
  if (result.skipped) {
@@ -3606,7 +1066,6 @@ jasmine.version_= {
3606
1066
 
3607
1067
  Console.prototype.trackPending = function() {
3608
1068
  var result;
3609
-
3610
1069
  result = this.spec.result();
3611
1070
  return this.log({
3612
1071
  type: "spec",
@@ -3619,7 +1078,6 @@ jasmine.version_= {
3619
1078
 
3620
1079
  Console.prototype.trackFailure = function() {
3621
1080
  var error, result, _i, _len, _ref, _results;
3622
-
3623
1081
  result = this.spec.result();
3624
1082
  _ref = this.spec.errors();
3625
1083
  _results = [];
@@ -3681,7 +1139,6 @@ jasmine.version_= {
3681
1139
 
3682
1140
  HTML.prototype.envInfo = function() {
3683
1141
  var ver, verString;
3684
-
3685
1142
  ver = jasmine.getEnv().version();
3686
1143
  verString = [ver.major, ver.minor, ver.build].join(".");
3687
1144
  return "jasmine " + verString + " revision " + ver.revision;
@@ -3697,6 +1154,10 @@ jasmine.version_= {
3697
1154
  __hasProp = {}.hasOwnProperty,
3698
1155
  __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
3699
1156
 
1157
+ if (typeof jasmine === "undefined" || jasmine === null) {
1158
+ throw new Teaspoon.Error('Jasmine not found -- use `suite.use_framework :jasmine` and adjust or remove the `suite.javascripts` directive.');
1159
+ }
1160
+
3700
1161
  Teaspoon.Runner = (function(_super) {
3701
1162
  __extends(Runner, _super);
3702
1163