evergreen 1.1.0 → 1.1.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (42) hide show
  1. data/README.rdoc +3 -3
  2. data/lib/evergreen/resources/evergreen.css +4 -0
  3. data/lib/evergreen/server.rb +1 -1
  4. data/lib/evergreen/version.rb +1 -1
  5. data/lib/jasmine/Gemfile +8 -0
  6. data/lib/jasmine/README.markdown +2 -1
  7. data/lib/jasmine/Rakefile +37 -1
  8. data/lib/jasmine/jasmine-core.gemspec +4 -1
  9. data/lib/jasmine/lib/jasmine-core/jasmine-html.js +77 -12
  10. data/lib/jasmine/lib/jasmine-core/jasmine.css +1 -0
  11. data/lib/jasmine/lib/jasmine-core/jasmine.js +107 -36
  12. data/lib/jasmine/lib/jasmine-core/version.rb +1 -1
  13. data/lib/jasmine/spec/core/ExceptionsSpec.js +113 -87
  14. data/lib/jasmine/spec/core/MatchersSpec.js +48 -2
  15. data/lib/jasmine/spec/core/PrettyPrintSpec.js +30 -0
  16. data/lib/jasmine/spec/core/RunnerSpec.js +13 -0
  17. data/lib/jasmine/spec/core/SpecRunningSpec.js +117 -84
  18. data/lib/jasmine/spec/core/SpySpec.js +15 -0
  19. data/lib/jasmine/spec/jasmine.yml +39 -0
  20. data/lib/jasmine/spec/jasmine_self_test_spec.rb +23 -0
  21. data/lib/jasmine/spec/tasks/build_github_pages_spec.rb +14 -23
  22. data/lib/jasmine/src/core/Block.js +9 -4
  23. data/lib/jasmine/src/core/Env.js +23 -0
  24. data/lib/jasmine/src/core/Matchers.js +19 -15
  25. data/lib/jasmine/src/core/PrettyPrinter.js +11 -4
  26. data/lib/jasmine/src/core/Queue.js +23 -4
  27. data/lib/jasmine/src/core/Spec.js +4 -4
  28. data/lib/jasmine/src/core/base.js +15 -2
  29. data/lib/jasmine/src/html/HtmlReporter.js +67 -3
  30. data/lib/jasmine/src/html/ReporterView.js +3 -3
  31. data/lib/jasmine/src/html/SpecView.js +5 -5
  32. data/lib/jasmine/src/html/SuiteView.js +1 -1
  33. data/lib/jasmine/src/html/_HTMLReporter.scss +49 -42
  34. data/lib/jasmine/src/html/jasmine.css +1 -0
  35. data/lib/jasmine/src/version.js +3 -3
  36. data/lib/jasmine/src/version.json +2 -2
  37. data/lib/jasmine/tasks/jasmine_dev/build_github_pages.rb +11 -14
  38. data/lib/jasmine/tasks/jasmine_dev/build_standalone_distribution.rb +3 -2
  39. data/lib/jasmine/tasks/jasmine_dev/build_standalone_runner.rb +3 -3
  40. data/spec/runner_spec.rb +0 -2
  41. data/spec/suite_spec.rb +7 -4
  42. metadata +4 -3
@@ -1,7 +1,7 @@
1
1
  = Evergreen
2
2
 
3
- {<img src="https://travis-ci.org/jnicklas/evergreen.png" />}[http://travis-ci.org/jnicklas/evergreen]
4
- {<img src="https://coveralls.io/repos/jnicklas/evergreen/badge.png" alt="Coverage Status" />}[https://coveralls.io/r/jnicklas/evergreen]
3
+ {<img src="https://travis-ci.org/abepetrillo/evergreen.png" />}[http://travis-ci.org/abepetrillo/evergreen]
4
+ {<img src="https://coveralls.io/repos/abepetrillo/evergreen/badge.png" alt="Coverage Status" />}[https://coveralls.io/r/abepetrillo/evergreen]
5
5
 
6
6
  "Because green is the new Blue(Ridge)"
7
7
 
@@ -10,7 +10,7 @@ combines a server which allows you to serve up and run your specs in a browser,
10
10
  as well as a runner which uses Capybara and any of its drivers to run your
11
11
  specs. Evergreen uses the Jasmine unit testing framework for JavaScript.
12
12
 
13
- http://github.com/jnicklas/evergreen
13
+ http://github.com/abepetrillo/evergreen
14
14
 
15
15
  == Philosophy
16
16
 
@@ -7,6 +7,10 @@ a {
7
7
  color: #4DA524;
8
8
  }
9
9
 
10
+ #TrivialReporter {
11
+ position: relative !important;
12
+ }
13
+
10
14
  #page, #test, .jasmine_reporter {
11
15
  width: 800px;
12
16
  background: white;
@@ -4,7 +4,7 @@ module Evergreen
4
4
 
5
5
  def serve
6
6
  server.boot
7
- Launchy.open(server.url(Evergreen.mounted_at.to_s + '/'))
7
+ Launchy.open("http://#{server.host}:#{server.port}/#{Evergreen.mounted_at.to_s}")
8
8
  trap('SIGINT') { puts 'Shutting down...' ; exit 0 }
9
9
  sleep
10
10
  end
@@ -1,3 +1,3 @@
1
1
  module Evergreen
2
- VERSION = '1.1.0'
2
+ VERSION = '1.1.2'
3
3
  end
@@ -1,3 +1,11 @@
1
1
  source :rubygems
2
2
  gem "rake"
3
+ gem "jasmine", git: 'https://github.com/pivotal/jasmine-gem.git'
4
+
5
+ unless ENV["TRAVIS"]
6
+ group :debug do
7
+ gem 'debugger'
8
+ end
9
+ end
10
+
3
11
  gemspec
@@ -1,4 +1,5 @@
1
- <a name="README">[Jasmine](http://pivotal.github.com/jasmine/)</a>
1
+ <a name="README">[Jasmine](http://pivotal.github.com/jasmine/)</a> <a title="Build at Travis CI" href="http://travis-ci.org/#!/pivotal/jasmine"><img src="https://secure.travis-ci.org/pivotal/jasmine.png" /></a>
2
+
2
3
  =======
3
4
  **A JavaScript Testing Framework**
4
5
 
@@ -41,4 +41,40 @@ desc "View full development tasks"
41
41
  task :list_dev_tasks do
42
42
  puts "Jasmine uses Thor for command line tasks for development. Here is the command set:"
43
43
  system "thor list"
44
- end
44
+ end
45
+
46
+ require "jasmine"
47
+ require 'rspec'
48
+ require 'rspec/core/rake_task'
49
+
50
+ desc "Run all examples"
51
+ RSpec::Core::RakeTask.new(:jasmine_core_spec) do |t|
52
+ t.pattern = 'spec/jasmine_self_test_spec.rb'
53
+ end
54
+
55
+ namespace :jasmine do
56
+ task :server do
57
+ port = ENV['JASMINE_PORT'] || 8888
58
+ Jasmine.load_configuration_from_yaml(File.join(Dir.pwd, 'spec', 'jasmine.yml'))
59
+ config = Jasmine.config
60
+ server = Jasmine::Server.new(8888, Jasmine::Application.app(config))
61
+ server.start
62
+
63
+ puts "your tests are here:"
64
+ puts " http://localhost:#{port}/"
65
+ end
66
+
67
+ desc "Copy examples from Jasmine JS to the gem"
68
+ task :copy_examples_to_gem do
69
+ require "fileutils"
70
+
71
+ # copy jasmine's example tree into our generator templates dir
72
+ FileUtils.rm_r('generators/jasmine/templates/jasmine-example', :force => true)
73
+ FileUtils.cp_r(File.join(Jasmine::Core.path, 'example'), 'generators/jasmine/templates/jasmine-example', :preserve => true)
74
+ end
75
+ end
76
+
77
+ desc "Run specs via server"
78
+ task :jasmine => ['jasmine:server']
79
+
80
+
@@ -17,7 +17,7 @@ Gem::Specification.new do |s|
17
17
  s.files = Dir.glob("./lib/**/*") + Dir.glob("./lib/jasmine-core/spec/**/*.js")
18
18
  s.require_paths = ["lib"]
19
19
  s.add_development_dependency "json_pure", ">= 1.4.3"
20
- s.add_development_dependency "frank"
20
+ s.add_development_dependency "tilt"
21
21
  s.add_development_dependency "sass"
22
22
  s.add_development_dependency "compass"
23
23
  s.add_development_dependency "ragaskar-jsdoc_helper"
@@ -26,4 +26,7 @@ Gem::Specification.new do |s|
26
26
  s.add_development_dependency "awesome_print"
27
27
  s.add_development_dependency "thor"
28
28
  s.add_development_dependency "nokogiri"
29
+ s.add_development_dependency "redcarpet", "1.7"
30
+ s.add_development_dependency "rocco"
31
+ s.add_development_dependency "rdiscount"
29
32
  end
@@ -78,6 +78,7 @@ jasmine.HtmlReporter = function(_doc) {
78
78
 
79
79
  createReporterDom(runner.env.versionString());
80
80
  doc.body.appendChild(dom.reporter);
81
+ setExceptionHandling();
81
82
 
82
83
  reporterView = new jasmine.HtmlReporter.ReporterView(dom);
83
84
  reporterView.addSpecs(specs, self.specFilter);
@@ -131,7 +132,7 @@ jasmine.HtmlReporter = function(_doc) {
131
132
  }
132
133
 
133
134
  var paramMap = [];
134
- var params = doc.location.search.substring(1).split('&');
135
+ var params = jasmine.HtmlReporter.parameters(doc);
135
136
 
136
137
  for (var i = 0; i < params.length; i++) {
137
138
  var p = params[i].split('=');
@@ -151,14 +152,78 @@ jasmine.HtmlReporter = function(_doc) {
151
152
  self.createDom('span', { className: 'version' }, version)),
152
153
 
153
154
  dom.symbolSummary = self.createDom('ul', {className: 'symbolSummary'}),
154
- dom.alert = self.createDom('div', {className: 'alert'}),
155
+ dom.alert = self.createDom('div', {className: 'alert'},
156
+ self.createDom('span', { className: 'exceptions' },
157
+ self.createDom('label', { className: 'label', 'for': 'no_try_catch' }, 'No try/catch'),
158
+ self.createDom('input', { id: 'no_try_catch', type: 'checkbox' }))),
155
159
  dom.results = self.createDom('div', {className: 'results'},
156
160
  dom.summary = self.createDom('div', { className: 'summary' }),
157
161
  dom.details = self.createDom('div', { id: 'details' }))
158
162
  );
159
163
  }
164
+
165
+ function noTryCatch() {
166
+ return window.location.search.match(/catch=false/);
167
+ }
168
+
169
+ function searchWithCatch() {
170
+ var params = jasmine.HtmlReporter.parameters(window.document);
171
+ var removed = false;
172
+ var i = 0;
173
+
174
+ while (!removed && i < params.length) {
175
+ if (params[i].match(/catch=/)) {
176
+ params.splice(i, 1);
177
+ removed = true;
178
+ }
179
+ i++;
180
+ }
181
+ if (jasmine.CATCH_EXCEPTIONS) {
182
+ params.push("catch=false");
183
+ }
184
+
185
+ return params.join("&");
186
+ }
187
+
188
+ function setExceptionHandling() {
189
+ var chxCatch = document.getElementById('no_try_catch');
190
+
191
+ if (noTryCatch()) {
192
+ chxCatch.setAttribute('checked', true);
193
+ jasmine.CATCH_EXCEPTIONS = false;
194
+ }
195
+ chxCatch.onclick = function() {
196
+ window.location.search = searchWithCatch();
197
+ };
198
+ }
199
+ };
200
+ jasmine.HtmlReporter.parameters = function(doc) {
201
+ var paramStr = doc.location.search.substring(1);
202
+ var params = [];
203
+
204
+ if (paramStr.length > 0) {
205
+ params = paramStr.split('&');
206
+ }
207
+ return params;
208
+ }
209
+ jasmine.HtmlReporter.sectionLink = function(sectionName) {
210
+ var link = '?';
211
+ var params = [];
212
+
213
+ if (sectionName) {
214
+ params.push('spec=' + encodeURIComponent(sectionName));
215
+ }
216
+ if (!jasmine.CATCH_EXCEPTIONS) {
217
+ params.push("catch=false");
218
+ }
219
+ if (params.length > 0) {
220
+ link += params.join("&");
221
+ }
222
+
223
+ return link;
160
224
  };
161
- jasmine.HtmlReporterHelpers.addHelpers(jasmine.HtmlReporter);jasmine.HtmlReporter.ReporterView = function(dom) {
225
+ jasmine.HtmlReporterHelpers.addHelpers(jasmine.HtmlReporter);
226
+ jasmine.HtmlReporter.ReporterView = function(dom) {
162
227
  this.startedAt = new Date();
163
228
  this.runningSpecCount = 0;
164
229
  this.completeSpecCount = 0;
@@ -241,14 +306,14 @@ jasmine.HtmlReporterHelpers.addHelpers(jasmine.HtmlReporter);jasmine.HtmlReporte
241
306
 
242
307
  // currently running UI
243
308
  if (isUndefined(this.runningAlert)) {
244
- this.runningAlert = this.createDom('a', {href: "?", className: "runningAlert bar"});
309
+ this.runningAlert = this.createDom('a', { href: jasmine.HtmlReporter.sectionLink(), className: "runningAlert bar" });
245
310
  dom.alert.appendChild(this.runningAlert);
246
311
  }
247
312
  this.runningAlert.innerHTML = "Running " + this.completeSpecCount + " of " + specPluralizedFor(this.totalSpecCount);
248
313
 
249
314
  // skipped specs UI
250
315
  if (isUndefined(this.skippedAlert)) {
251
- this.skippedAlert = this.createDom('a', {href: "?", className: "skippedAlert bar"});
316
+ this.skippedAlert = this.createDom('a', { href: jasmine.HtmlReporter.sectionLink(), className: "skippedAlert bar" });
252
317
  }
253
318
 
254
319
  this.skippedAlert.innerHTML = "Skipping " + this.skippedCount + " of " + specPluralizedFor(this.totalSpecCount) + " - run all";
@@ -259,7 +324,7 @@ jasmine.HtmlReporterHelpers.addHelpers(jasmine.HtmlReporter);jasmine.HtmlReporte
259
324
 
260
325
  // passing specs UI
261
326
  if (isUndefined(this.passedAlert)) {
262
- this.passedAlert = this.createDom('span', {href: "?", className: "passingAlert bar"});
327
+ this.passedAlert = this.createDom('span', { href: jasmine.HtmlReporter.sectionLink(), className: "passingAlert bar" });
263
328
  }
264
329
  this.passedAlert.innerHTML = "Passing " + specPluralizedFor(this.passedCount);
265
330
 
@@ -331,11 +396,11 @@ jasmine.HtmlReporter.SpecView = function(spec, dom, views) {
331
396
  this.dom.symbolSummary.appendChild(this.symbol);
332
397
 
333
398
  this.summary = this.createDom('div', { className: 'specSummary' },
334
- this.createDom('a', {
335
- className: 'description',
336
- href: '?spec=' + encodeURIComponent(this.spec.getFullName()),
337
- title: this.spec.getFullName()
338
- }, this.spec.description)
399
+ this.createDom('a', {
400
+ className: 'description',
401
+ href: jasmine.HtmlReporter.sectionLink(this.spec.getFullName()),
402
+ title: this.spec.getFullName()
403
+ }, this.spec.description)
339
404
  );
340
405
 
341
406
  this.detail = this.createDom('div', { className: 'specDetail' },
@@ -406,7 +471,7 @@ jasmine.HtmlReporterHelpers.addHelpers(jasmine.HtmlReporter.SpecView);jasmine.Ht
406
471
  this.views = views;
407
472
 
408
473
  this.element = this.createDom('div', { className: 'suite' },
409
- this.createDom('a', { className: 'description', href: '?spec=' + encodeURIComponent(this.suite.getFullName()) }, this.suite.description)
474
+ this.createDom('a', { className: 'description', href: jasmine.HtmlReporter.sectionLink(this.suite.getFullName()) }, this.suite.description)
410
475
  );
411
476
 
412
477
  this.appendToSummary(this.suite, this.element);
@@ -19,6 +19,7 @@ body { background-color: #eeeeee; padding: 0; margin: 5px; overflow-y: scroll; }
19
19
  #HTMLReporter .symbolSummary li.skipped:before { color: #bababa; content: "\02022"; }
20
20
  #HTMLReporter .symbolSummary li.pending { line-height: 11px; }
21
21
  #HTMLReporter .symbolSummary li.pending:before { color: #aaaaaa; content: "-"; }
22
+ #HTMLReporter .exceptions { color: #fff; float: right; margin-top: 5px; margin-right: 5px; }
22
23
  #HTMLReporter .bar { line-height: 28px; font-size: 14px; display: block; color: #eee; }
23
24
  #HTMLReporter .runningAlert { background-color: #666666; }
24
25
  #HTMLReporter .skippedAlert { background-color: #aaaaaa; }
@@ -1,4 +1,4 @@
1
- var isCommonJS = typeof window == "undefined";
1
+ var isCommonJS = typeof window == "undefined" && typeof exports == "object";
2
2
 
3
3
  /**
4
4
  * Top level namespace for Jasmine, a lightweight JavaScript BDD/spec/testing framework.
@@ -34,11 +34,23 @@ jasmine.VERBOSE = false;
34
34
  */
35
35
  jasmine.DEFAULT_UPDATE_INTERVAL = 250;
36
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
+
37
42
  /**
38
43
  * Default timeout interval in milliseconds for waitsFor() blocks.
39
44
  */
40
45
  jasmine.DEFAULT_TIMEOUT_INTERVAL = 5000;
41
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
+
42
54
  jasmine.getGlobal = function() {
43
55
  function getGlobal() {
44
56
  return this;
@@ -463,7 +475,7 @@ jasmine.log = function() {
463
475
  * @see jasmine.createSpy
464
476
  * @param obj
465
477
  * @param methodName
466
- * @returns a Jasmine spy that can be chained with all spy methods
478
+ * @return {jasmine.Spy} a Jasmine spy that can be chained with all spy methods
467
479
  */
468
480
  var spyOn = function(obj, methodName) {
469
481
  return jasmine.getEnv().currentSpec.spyOn(obj, methodName);
@@ -508,6 +520,7 @@ if (isCommonJS) exports.xit = xit;
508
520
  * jasmine.Matchers functions.
509
521
  *
510
522
  * @param {Object} actual Actual value to test against and expected value
523
+ * @return {jasmine.Matchers}
511
524
  */
512
525
  var expect = function(actual) {
513
526
  return jasmine.getEnv().currentSpec.expect(actual);
@@ -867,6 +880,25 @@ jasmine.Env.prototype.xit = function(desc, func) {
867
880
  };
868
881
  };
869
882
 
883
+ jasmine.Env.prototype.compareRegExps_ = function(a, b, mismatchKeys, mismatchValues) {
884
+ if (a.source != b.source)
885
+ mismatchValues.push("expected pattern /" + b.source + "/ is not equal to the pattern /" + a.source + "/");
886
+
887
+ if (a.ignoreCase != b.ignoreCase)
888
+ mismatchValues.push("expected modifier i was" + (b.ignoreCase ? " " : " not ") + "set and does not equal the origin modifier");
889
+
890
+ if (a.global != b.global)
891
+ mismatchValues.push("expected modifier g was" + (b.global ? " " : " not ") + "set and does not equal the origin modifier");
892
+
893
+ if (a.multiline != b.multiline)
894
+ mismatchValues.push("expected modifier m was" + (b.multiline ? " " : " not ") + "set and does not equal the origin modifier");
895
+
896
+ if (a.sticky != b.sticky)
897
+ mismatchValues.push("expected modifier y was" + (b.sticky ? " " : " not ") + "set and does not equal the origin modifier");
898
+
899
+ return (mismatchValues.length === 0);
900
+ };
901
+
870
902
  jasmine.Env.prototype.compareObjects_ = function(a, b, mismatchKeys, mismatchValues) {
871
903
  if (a.__Jasmine_been_here_before__ === b && b.__Jasmine_been_here_before__ === a) {
872
904
  return true;
@@ -953,6 +985,10 @@ jasmine.Env.prototype.equals_ = function(a, b, mismatchKeys, mismatchValues) {
953
985
  return (a == b);
954
986
  }
955
987
 
988
+ if (a instanceof RegExp && b instanceof RegExp) {
989
+ return this.compareRegExps_(a, b, mismatchKeys, mismatchValues);
990
+ }
991
+
956
992
  if (typeof a === "object" && typeof b === "object") {
957
993
  return this.compareObjects_(a, b, mismatchKeys, mismatchValues);
958
994
  }
@@ -1019,11 +1055,16 @@ jasmine.Block = function(env, func, spec) {
1019
1055
  this.spec = spec;
1020
1056
  };
1021
1057
 
1022
- jasmine.Block.prototype.execute = function(onComplete) {
1023
- try {
1058
+ jasmine.Block.prototype.execute = function(onComplete) {
1059
+ if (!jasmine.CATCH_EXCEPTIONS) {
1024
1060
  this.func.apply(this.spec);
1025
- } catch (e) {
1026
- this.spec.fail(e);
1061
+ }
1062
+ else {
1063
+ try {
1064
+ this.func.apply(this.spec);
1065
+ } catch (e) {
1066
+ this.spec.fail(e);
1067
+ }
1027
1068
  }
1028
1069
  onComplete();
1029
1070
  };
@@ -1281,6 +1322,17 @@ jasmine.Matchers.prototype.toBeNull = function() {
1281
1322
  return (this.actual === null);
1282
1323
  };
1283
1324
 
1325
+ /**
1326
+ * Matcher that compares the actual to NaN.
1327
+ */
1328
+ jasmine.Matchers.prototype.toBeNaN = function() {
1329
+ this.message = function() {
1330
+ return [ "Expected " + jasmine.pp(this.actual) + " to be NaN." ];
1331
+ };
1332
+
1333
+ return (this.actual !== this.actual);
1334
+ };
1335
+
1284
1336
  /**
1285
1337
  * Matcher that boolean not-nots the actual.
1286
1338
  */
@@ -1358,18 +1410,14 @@ jasmine.Matchers.prototype.toHaveBeenCalledWith = function() {
1358
1410
  throw new Error('Expected a spy, but got ' + jasmine.pp(this.actual) + '.');
1359
1411
  }
1360
1412
  this.message = function() {
1413
+ var invertedMessage = "Expected spy " + this.actual.identity + " not to have been called with " + jasmine.pp(expectedArgs) + " but it was.";
1414
+ var positiveMessage = "";
1361
1415
  if (this.actual.callCount === 0) {
1362
- // todo: what should the failure message for .not.toHaveBeenCalledWith() be? is this right? test better. [xw]
1363
- return [
1364
- "Expected spy " + this.actual.identity + " to have been called with " + jasmine.pp(expectedArgs) + " but it was never called.",
1365
- "Expected spy " + this.actual.identity + " not to have been called with " + jasmine.pp(expectedArgs) + " but it was."
1366
- ];
1416
+ positiveMessage = "Expected spy " + this.actual.identity + " to have been called with " + jasmine.pp(expectedArgs) + " but it was never called.";
1367
1417
  } else {
1368
- return [
1369
- "Expected spy " + this.actual.identity + " to have been called with " + jasmine.pp(expectedArgs) + " but was called with " + jasmine.pp(this.actual.argsForCall),
1370
- "Expected spy " + this.actual.identity + " not to have been called with " + jasmine.pp(expectedArgs) + " but was called with " + jasmine.pp(this.actual.argsForCall)
1371
- ];
1418
+ positiveMessage = "Expected spy " + this.actual.identity + " to have been called with " + jasmine.pp(expectedArgs) + " but actual calls were " + jasmine.pp(this.actual.argsForCall).replace(/^\[ | \]$/g, '')
1372
1419
  }
1420
+ return [positiveMessage, invertedMessage];
1373
1421
  };
1374
1422
 
1375
1423
  return this.env.contains_(this.actual.argsForCall, expectedArgs);
@@ -1427,22 +1475,19 @@ jasmine.Matchers.prototype.toBeGreaterThan = function(expected) {
1427
1475
  * up to a given level of decimal precision (default 2).
1428
1476
  *
1429
1477
  * @param {Number} expected
1430
- * @param {Number} precision
1478
+ * @param {Number} precision, as number of decimal places
1431
1479
  */
1432
1480
  jasmine.Matchers.prototype.toBeCloseTo = function(expected, precision) {
1433
1481
  if (!(precision === 0)) {
1434
1482
  precision = precision || 2;
1435
1483
  }
1436
- var multiplier = Math.pow(10, precision);
1437
- var actual = Math.round(this.actual * multiplier);
1438
- expected = Math.round(expected * multiplier);
1439
- return expected == actual;
1484
+ return Math.abs(expected - this.actual) < (Math.pow(10, -precision) / 2);
1440
1485
  };
1441
1486
 
1442
1487
  /**
1443
1488
  * Matcher that checks that the expected exception was thrown by the actual.
1444
1489
  *
1445
- * @param {String} expected
1490
+ * @param {String} [expected]
1446
1491
  */
1447
1492
  jasmine.Matchers.prototype.toThrow = function(expected) {
1448
1493
  var result = false;
@@ -1840,10 +1885,6 @@ jasmine.PrettyPrinter = function() {
1840
1885
  * @param value
1841
1886
  */
1842
1887
  jasmine.PrettyPrinter.prototype.format = function(value) {
1843
- if (this.ppNestLevel_ > 40) {
1844
- throw new Error('jasmine.PrettyPrinter: format() nested too deeply!');
1845
- }
1846
-
1847
1888
  this.ppNestLevel_++;
1848
1889
  try {
1849
1890
  if (value === jasmine.undefined) {
@@ -1886,6 +1927,7 @@ jasmine.PrettyPrinter.prototype.format = function(value) {
1886
1927
 
1887
1928
  jasmine.PrettyPrinter.prototype.iterateObject = function(obj, fn) {
1888
1929
  for (var property in obj) {
1930
+ if (!obj.hasOwnProperty(property)) continue;
1889
1931
  if (property == '__Jasmine_been_here_before__') continue;
1890
1932
  fn(property, obj.__lookupGetter__ ? (obj.__lookupGetter__(property) !== jasmine.undefined &&
1891
1933
  obj.__lookupGetter__(property) !== null) : false);
@@ -1913,6 +1955,11 @@ jasmine.StringPrettyPrinter.prototype.emitString = function(value) {
1913
1955
  };
1914
1956
 
1915
1957
  jasmine.StringPrettyPrinter.prototype.emitArray = function(array) {
1958
+ if (this.ppNestLevel_ > jasmine.MAX_PRETTY_PRINT_DEPTH) {
1959
+ this.append("Array");
1960
+ return;
1961
+ }
1962
+
1916
1963
  this.append('[ ');
1917
1964
  for (var i = 0; i < array.length; i++) {
1918
1965
  if (i > 0) {
@@ -1924,6 +1971,11 @@ jasmine.StringPrettyPrinter.prototype.emitArray = function(array) {
1924
1971
  };
1925
1972
 
1926
1973
  jasmine.StringPrettyPrinter.prototype.emitObject = function(obj) {
1974
+ if (this.ppNestLevel_ > jasmine.MAX_PRETTY_PRINT_DEPTH) {
1975
+ this.append("Object");
1976
+ return;
1977
+ }
1978
+
1927
1979
  var self = this;
1928
1980
  this.append('{ ');
1929
1981
  var first = true;
@@ -1952,6 +2004,10 @@ jasmine.StringPrettyPrinter.prototype.append = function(value) {
1952
2004
  };
1953
2005
  jasmine.Queue = function(env) {
1954
2006
  this.env = env;
2007
+
2008
+ // parallel to blocks. each true value in this array means the block will
2009
+ // get executed even if we abort
2010
+ this.ensured = [];
1955
2011
  this.blocks = [];
1956
2012
  this.running = false;
1957
2013
  this.index = 0;
@@ -1959,15 +2015,30 @@ jasmine.Queue = function(env) {
1959
2015
  this.abort = false;
1960
2016
  };
1961
2017
 
1962
- jasmine.Queue.prototype.addBefore = function(block) {
2018
+ jasmine.Queue.prototype.addBefore = function(block, ensure) {
2019
+ if (ensure === jasmine.undefined) {
2020
+ ensure = false;
2021
+ }
2022
+
1963
2023
  this.blocks.unshift(block);
2024
+ this.ensured.unshift(ensure);
1964
2025
  };
1965
2026
 
1966
- jasmine.Queue.prototype.add = function(block) {
2027
+ jasmine.Queue.prototype.add = function(block, ensure) {
2028
+ if (ensure === jasmine.undefined) {
2029
+ ensure = false;
2030
+ }
2031
+
1967
2032
  this.blocks.push(block);
2033
+ this.ensured.push(ensure);
1968
2034
  };
1969
2035
 
1970
- jasmine.Queue.prototype.insertNext = function(block) {
2036
+ jasmine.Queue.prototype.insertNext = function(block, ensure) {
2037
+ if (ensure === jasmine.undefined) {
2038
+ ensure = false;
2039
+ }
2040
+
2041
+ this.ensured.splice((this.index + this.offset + 1), 0, ensure);
1971
2042
  this.blocks.splice((this.index + this.offset + 1), 0, block);
1972
2043
  this.offset++;
1973
2044
  };
@@ -1991,7 +2062,7 @@ jasmine.Queue.prototype.next_ = function() {
1991
2062
  while (goAgain) {
1992
2063
  goAgain = false;
1993
2064
 
1994
- if (self.index < self.blocks.length && !this.abort) {
2065
+ if (self.index < self.blocks.length && !(this.abort && !this.ensured[self.index])) {
1995
2066
  var calledSynchronously = true;
1996
2067
  var completedSynchronously = false;
1997
2068
 
@@ -2282,7 +2353,7 @@ jasmine.Spec.prototype.finish = function(onComplete) {
2282
2353
 
2283
2354
  jasmine.Spec.prototype.after = function(doAfter) {
2284
2355
  if (this.queue.isRunning()) {
2285
- this.queue.add(new jasmine.Block(this.env, doAfter, this));
2356
+ this.queue.add(new jasmine.Block(this.env, doAfter, this), true);
2286
2357
  } else {
2287
2358
  this.afterCallbacks.unshift(doAfter);
2288
2359
  }
@@ -2320,15 +2391,15 @@ jasmine.Spec.prototype.addBeforesAndAftersToQueue = function() {
2320
2391
  this.queue.addBefore(new jasmine.Block(this.env, runner.before_[i], this));
2321
2392
  }
2322
2393
  for (i = 0; i < this.afterCallbacks.length; i++) {
2323
- this.queue.add(new jasmine.Block(this.env, this.afterCallbacks[i], this));
2394
+ this.queue.add(new jasmine.Block(this.env, this.afterCallbacks[i], this), true);
2324
2395
  }
2325
2396
  for (suite = this.suite; suite; suite = suite.parentSuite) {
2326
2397
  for (i = 0; i < suite.after_.length; i++) {
2327
- this.queue.add(new jasmine.Block(this.env, suite.after_[i], this));
2398
+ this.queue.add(new jasmine.Block(this.env, suite.after_[i], this), true);
2328
2399
  }
2329
2400
  }
2330
2401
  for (i = 0; i < runner.after_.length; i++) {
2331
- this.queue.add(new jasmine.Block(this.env, runner.after_[i], this));
2402
+ this.queue.add(new jasmine.Block(this.env, runner.after_[i], this), true);
2332
2403
  }
2333
2404
  };
2334
2405
 
@@ -2523,7 +2594,7 @@ jasmine.WaitsForBlock.prototype.execute = function(onComplete) {
2523
2594
 
2524
2595
  jasmine.version_= {
2525
2596
  "major": 1,
2526
- "minor": 2,
2527
- "build": 0,
2528
- "revision": 1337005947
2597
+ "minor": 3,
2598
+ "build": 1,
2599
+ "revision": 1354556913
2529
2600
  };