jasmine-core 2.4.1 → 2.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (71) hide show
  1. checksums.yaml +4 -4
  2. data/lib/console/console.js +1 -1
  3. data/lib/jasmine-core/boot.js +1 -1
  4. data/lib/jasmine-core/jasmine-html.js +15 -7
  5. data/lib/jasmine-core/jasmine.js +261 -82
  6. data/lib/jasmine-core/node_boot.js +1 -1
  7. data/lib/jasmine-core/spec/console/ConsoleReporterSpec.js +16 -16
  8. data/lib/jasmine-core/spec/core/CallTrackerSpec.js +26 -11
  9. data/lib/jasmine-core/spec/core/ClockSpec.js +61 -42
  10. data/lib/jasmine-core/spec/core/DelayedFunctionSchedulerSpec.js +28 -15
  11. data/lib/jasmine-core/spec/core/EnvSpec.js +8 -8
  12. data/lib/jasmine-core/spec/core/ExceptionFormatterSpec.js +6 -6
  13. data/lib/jasmine-core/spec/core/ExceptionsSpec.js +1 -1
  14. data/lib/jasmine-core/spec/core/ExpectationResultSpec.js +8 -8
  15. data/lib/jasmine-core/spec/core/ExpectationSpec.js +17 -17
  16. data/lib/jasmine-core/spec/core/JsApiReporterSpec.js +14 -14
  17. data/lib/jasmine-core/spec/core/MockDateSpec.js +14 -14
  18. data/lib/jasmine-core/spec/core/PrettyPrintSpec.js +65 -56
  19. data/lib/jasmine-core/spec/core/QueueRunnerSpec.js +32 -18
  20. data/lib/jasmine-core/spec/core/ReportDispatcherSpec.js +27 -3
  21. data/lib/jasmine-core/spec/core/SpecSpec.js +37 -37
  22. data/lib/jasmine-core/spec/core/SpyRegistrySpec.js +46 -7
  23. data/lib/jasmine-core/spec/core/SpySpec.js +11 -11
  24. data/lib/jasmine-core/spec/core/SpyStrategySpec.js +25 -13
  25. data/lib/jasmine-core/spec/core/SuiteSpec.js +25 -25
  26. data/lib/jasmine-core/spec/core/TimerSpec.js +2 -2
  27. data/lib/jasmine-core/spec/core/TreeProcessorSpec.js +26 -26
  28. data/lib/jasmine-core/spec/core/UtilSpec.js +12 -12
  29. data/lib/jasmine-core/spec/core/asymmetric_equality/AnySpec.js +8 -8
  30. data/lib/jasmine-core/spec/core/asymmetric_equality/AnythingSpec.js +7 -7
  31. data/lib/jasmine-core/spec/core/asymmetric_equality/ArrayContainingSpec.js +6 -6
  32. data/lib/jasmine-core/spec/core/asymmetric_equality/ObjectContainingSpec.js +11 -11
  33. data/lib/jasmine-core/spec/core/asymmetric_equality/StringMatchingSpec.js +4 -4
  34. data/lib/jasmine-core/spec/core/formatErrorMsgSpec.js +13 -0
  35. data/lib/jasmine-core/spec/core/integration/CustomMatchersSpec.js +2 -2
  36. data/lib/jasmine-core/spec/core/integration/EnvSpec.js +195 -76
  37. data/lib/jasmine-core/spec/core/integration/SpecRunningSpec.js +20 -21
  38. data/lib/jasmine-core/spec/core/matchers/matchersUtilSpec.js +164 -114
  39. data/lib/jasmine-core/spec/core/matchers/toBeCloseToSpec.js +4 -4
  40. data/lib/jasmine-core/spec/core/matchers/toBeDefinedSpec.js +2 -2
  41. data/lib/jasmine-core/spec/core/matchers/toBeFalsySpec.js +2 -2
  42. data/lib/jasmine-core/spec/core/matchers/toBeGreaterThanOrEqualSpec.js +29 -0
  43. data/lib/jasmine-core/spec/core/matchers/toBeGreaterThanSpec.js +2 -2
  44. data/lib/jasmine-core/spec/core/matchers/toBeLessThanOrEqualSpec.js +29 -0
  45. data/lib/jasmine-core/spec/core/matchers/toBeLessThanSpec.js +2 -2
  46. data/lib/jasmine-core/spec/core/matchers/toBeNaNSpec.js +3 -3
  47. data/lib/jasmine-core/spec/core/matchers/toBeNullSpec.js +2 -2
  48. data/lib/jasmine-core/spec/core/matchers/toBeSpec.js +2 -2
  49. data/lib/jasmine-core/spec/core/matchers/toBeTruthySpec.js +2 -2
  50. data/lib/jasmine-core/spec/core/matchers/toBeUndefinedSpec.js +2 -2
  51. data/lib/jasmine-core/spec/core/matchers/toContainSpec.js +4 -4
  52. data/lib/jasmine-core/spec/core/matchers/toEqualSpec.js +2 -2
  53. data/lib/jasmine-core/spec/core/matchers/toHaveBeenCalledSpec.js +11 -11
  54. data/lib/jasmine-core/spec/core/matchers/toHaveBeenCalledTimesSpec.js +22 -17
  55. data/lib/jasmine-core/spec/core/matchers/toHaveBeenCalledWithSpec.js +11 -10
  56. data/lib/jasmine-core/spec/core/matchers/toMatchSpec.js +7 -6
  57. data/lib/jasmine-core/spec/core/matchers/toThrowErrorSpec.js +24 -24
  58. data/lib/jasmine-core/spec/core/matchers/toThrowSpec.js +9 -8
  59. data/lib/jasmine-core/spec/helpers/defineJasmineUnderTest.js +3 -3
  60. data/lib/jasmine-core/spec/helpers/nodeDefineJasmineUnderTest.js +5 -5
  61. data/lib/jasmine-core/spec/html/HtmlReporterSpec.js +95 -59
  62. data/lib/jasmine-core/spec/html/HtmlSpecFilterSpec.js +3 -3
  63. data/lib/jasmine-core/spec/html/MatchersHtmlSpec.js +1 -1
  64. data/lib/jasmine-core/spec/html/PrettyPrintHtmlSpec.js +4 -4
  65. data/lib/jasmine-core/spec/html/QueryStringSpec.js +5 -5
  66. data/lib/jasmine-core/spec/html/ResultsNodeSpec.js +4 -4
  67. data/lib/jasmine-core/spec/npmPackage/npmPackageSpec.js +2 -2
  68. data/lib/jasmine-core/spec/performance/large_object_test.js +1 -1
  69. data/lib/jasmine-core/version.rb +1 -1
  70. metadata +5 -3
  71. data/lib/jasmine-core/spec/node_suite.js +0 -195
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 0169ff00d52d62027ccaa73129da72cebd93ce9f
4
- data.tar.gz: 64a4e9061a2e9869383f8ec39c7390da8cadfb8f
3
+ metadata.gz: 53b9747ec8f9f68a92d930d1c1fd9985e0fe2b13
4
+ data.tar.gz: f902b066456e9891319425365eb964858313fcc6
5
5
  SHA512:
6
- metadata.gz: 0fcfaa57e6b89a26bdc8e6ebeb2e82e4ba80c9a8afe1310f8910a3f14f961ca543fd93225429579b89a40baeb366a8114e8686d80ed706d74d65ce5f81ab8539
7
- data.tar.gz: d03ec7d98abf86f1242531034446fddd57a46c5abd60bf3fbb8d478b878d954076363556573ab019c657b98408f30e7b296dbf18269cb6a7b4fcc7c16518560d
6
+ metadata.gz: 44b3b65e99e332064a6c8b0cd1568cac8226c74daa2a6690a830a6a57fbdfd21994542fb5be234b69dfa61567be9509d92ed83c2b4f75b183233cd87870ef414
7
+ data.tar.gz: 7ce561e476521b3bc09d7fb5d4f87c8c1e0928c025fa315e3262b2fa7f70f2df4abe5945ec5db6412cac331488a73de3492f91677f1d7d5731a660e487c6332d
@@ -1,5 +1,5 @@
1
1
  /*
2
- Copyright (c) 2008-2015 Pivotal Labs
2
+ Copyright (c) 2008-2016 Pivotal Labs
3
3
 
4
4
  Permission is hereby granted, free of charge, to any person obtaining
5
5
  a copy of this software and associated documentation files (the
@@ -1,5 +1,5 @@
1
1
  /*
2
- Copyright (c) 2008-2015 Pivotal Labs
2
+ Copyright (c) 2008-2016 Pivotal Labs
3
3
 
4
4
  Permission is hereby granted, free of charge, to any person obtaining
5
5
  a copy of this software and associated documentation files (the
@@ -1,5 +1,5 @@
1
1
  /*
2
- Copyright (c) 2008-2015 Pivotal Labs
2
+ Copyright (c) 2008-2016 Pivotal Labs
3
3
 
4
4
  Permission is hereby granted, free of charge, to any person obtaining
5
5
  a copy of this software and associated documentation files (the
@@ -209,9 +209,10 @@ jasmineRequire.HtmlReporter = function(j$) {
209
209
 
210
210
  if (specsExecuted < totalSpecsDefined) {
211
211
  var skippedMessage = 'Ran ' + specsExecuted + ' of ' + totalSpecsDefined + ' specs - run all';
212
+ var skippedLink = order && order.random ? '?random=true' : '?';
212
213
  alert.appendChild(
213
214
  createDom('span', {className: 'jasmine-bar jasmine-skipped'},
214
- createDom('a', {href: '?', title: 'Run all specs'}, skippedMessage)
215
+ createDom('a', {href: skippedLink, title: 'Run all specs'}, skippedMessage)
215
216
  )
216
217
  );
217
218
  }
@@ -237,15 +238,22 @@ jasmineRequire.HtmlReporter = function(j$) {
237
238
 
238
239
  alert.appendChild(createDom('span', {className: statusBarClassName}, statusBarMessage, seedBar));
239
240
 
240
- for(i = 0; i < failedSuites.length; i++) {
241
+ var errorBarClassName = 'jasmine-bar jasmine-errored';
242
+ var errorBarMessagePrefix = 'AfterAll ';
243
+
244
+ for(var i = 0; i < failedSuites.length; i++) {
241
245
  var failedSuite = failedSuites[i];
242
246
  for(var j = 0; j < failedSuite.failedExpectations.length; j++) {
243
- var errorBarMessage = 'AfterAll ' + failedSuite.failedExpectations[j].message;
244
- var errorBarClassName = 'jasmine-bar jasmine-errored';
245
- alert.appendChild(createDom('span', {className: errorBarClassName}, errorBarMessage));
247
+ alert.appendChild(createDom('span', {className: errorBarClassName}, errorBarMessagePrefix + failedSuite.failedExpectations[j].message));
246
248
  }
247
249
  }
248
250
 
251
+ var globalFailures = (doneResult && doneResult.failedExpectations) || [];
252
+ for(i = 0; i < globalFailures.length; i++) {
253
+ var failure = globalFailures[i];
254
+ alert.appendChild(createDom('span', {className: errorBarClassName}, errorBarMessagePrefix + failure.message));
255
+ }
256
+
249
257
  var results = find('.jasmine-results');
250
258
  results.appendChild(summary);
251
259
 
@@ -309,7 +317,7 @@ jasmineRequire.HtmlReporter = function(j$) {
309
317
  setMenuModeTo('jasmine-failure-list');
310
318
 
311
319
  var failureNode = find('.jasmine-failures');
312
- for (var i = 0; i < failures.length; i++) {
320
+ for (i = 0; i < failures.length; i++) {
313
321
  failureNode.appendChild(failures[i]);
314
322
  }
315
323
  }
@@ -1,5 +1,5 @@
1
1
  /*
2
- Copyright (c) 2008-2015 Pivotal Labs
2
+ Copyright (c) 2008-2016 Pivotal Labs
3
3
 
4
4
  Permission is hereby granted, free of charge, to any person obtaining
5
5
  a copy of this software and associated documentation files (the
@@ -23,7 +23,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
23
  var getJasmineRequireObj = (function (jasmineGlobal) {
24
24
  var jasmineRequire;
25
25
 
26
- if (typeof module !== 'undefined' && module.exports) {
26
+ if (typeof module !== 'undefined' && module.exports && typeof exports !== 'undefined') {
27
27
  if (typeof global !== 'undefined') {
28
28
  jasmineGlobal = global;
29
29
  } else {
@@ -47,9 +47,10 @@ var getJasmineRequireObj = (function (jasmineGlobal) {
47
47
  jRequire.base(j$, jasmineGlobal);
48
48
  j$.util = jRequire.util();
49
49
  j$.errors = jRequire.errors();
50
+ j$.formatErrorMsg = jRequire.formatErrorMsg();
50
51
  j$.Any = jRequire.Any(j$);
51
52
  j$.Anything = jRequire.Anything(j$);
52
- j$.CallTracker = jRequire.CallTracker();
53
+ j$.CallTracker = jRequire.CallTracker(j$);
53
54
  j$.MockDate = jRequire.MockDate();
54
55
  j$.Clock = jRequire.Clock();
55
56
  j$.DelayedFunctionScheduler = jRequire.DelayedFunctionScheduler();
@@ -89,6 +90,8 @@ getJasmineRequireObj().requireMatchers = function(jRequire, j$) {
89
90
  'toBeDefined',
90
91
  'toBeFalsy',
91
92
  'toBeGreaterThan',
93
+ 'toBeGreaterThanOrEqual',
94
+ 'toBeLessThanOrEqual',
92
95
  'toBeLessThan',
93
96
  'toBeNaN',
94
97
  'toBeNull',
@@ -153,7 +156,12 @@ getJasmineRequireObj().base = function(j$, jasmineGlobal) {
153
156
  };
154
157
 
155
158
  j$.fnNameFor = function(func) {
156
- return func.name || func.toString().match(/^\s*function\s*(\w*)\s*\(/)[1];
159
+ if (func.name) {
160
+ return func.name;
161
+ }
162
+
163
+ var matches = func.toString().match(/^\s*function\s*(\w*)\s*\(/);
164
+ return matches ? matches[1] : '<anonymous>';
157
165
  };
158
166
 
159
167
  j$.any = function(clazz) {
@@ -515,7 +523,6 @@ getJasmineRequireObj().Env = function(j$) {
515
523
  var realClearTimeout = j$.getGlobal().clearTimeout;
516
524
  this.clock = new j$.Clock(global, function () { return new j$.DelayedFunctionScheduler(); }, new j$.MockDate(global));
517
525
 
518
- var runnableLookupTable = {};
519
526
  var runnableResources = {};
520
527
 
521
528
  var currentSpec = null;
@@ -625,7 +632,13 @@ getJasmineRequireObj().Env = function(j$) {
625
632
  };
626
633
 
627
634
  var getSpecName = function(spec, suite) {
628
- return suite.getFullName() + ' ' + spec.description;
635
+ var fullName = [spec.description],
636
+ suiteFullName = suite.getFullName();
637
+
638
+ if (suiteFullName !== '') {
639
+ fullName.unshift(suiteFullName);
640
+ }
641
+ return fullName.join(' ');
629
642
  };
630
643
 
631
644
  // TODO: we may just be able to pass in the fn instead of wrapping here
@@ -701,9 +714,9 @@ getJasmineRequireObj().Env = function(j$) {
701
714
  env: this,
702
715
  id: getNextSuiteId(),
703
716
  description: 'Jasmine__TopLevel__Suite',
704
- queueRunner: queueRunnerFactory
717
+ expectationFactory: expectationFactory,
718
+ expectationResultFactory: expectationResultFactory
705
719
  });
706
- runnableLookupTable[topSuite.id] = topSuite;
707
720
  defaultResourcesForRunnable(topSuite.id);
708
721
  currentDeclarationSuite = topSuite;
709
722
 
@@ -754,9 +767,15 @@ getJasmineRequireObj().Env = function(j$) {
754
767
  totalSpecsDefined: totalSpecsDefined
755
768
  });
756
769
 
770
+ currentlyExecutingSuites.push(topSuite);
771
+
757
772
  processor.execute(function() {
773
+ clearResourcesForRunnable(topSuite.id);
774
+ currentlyExecutingSuites.pop();
775
+
758
776
  reporter.jasmineDone({
759
- order: order
777
+ order: order,
778
+ failedExpectations: topSuite.result.failedExpectations
760
779
  });
761
780
  });
762
781
  };
@@ -765,6 +784,10 @@ getJasmineRequireObj().Env = function(j$) {
765
784
  reporter.addReporter(reporterToAdd);
766
785
  };
767
786
 
787
+ this.provideFallbackReporter = function(reporterToAdd) {
788
+ reporter.provideFallbackReporter(reporterToAdd);
789
+ };
790
+
768
791
  var spyRegistry = new j$.SpyRegistry({currentSpies: function() {
769
792
  if(!currentRunnable()) {
770
793
  throw new Error('Spies must be created in a before function or a spec');
@@ -772,6 +795,10 @@ getJasmineRequireObj().Env = function(j$) {
772
795
  return runnableResources[currentRunnable().id].spies;
773
796
  }});
774
797
 
798
+ this.allowRespy = function(allow){
799
+ spyRegistry.allowRespy(allow);
800
+ };
801
+
775
802
  this.spyOn = function() {
776
803
  return spyRegistry.spyOn.apply(spyRegistry, arguments);
777
804
  };
@@ -787,14 +814,13 @@ getJasmineRequireObj().Env = function(j$) {
787
814
  throwOnExpectationFailure: throwOnExpectationFailure
788
815
  });
789
816
 
790
- runnableLookupTable[suite.id] = suite;
791
817
  return suite;
792
818
  };
793
819
 
794
820
  this.describe = function(description, specDefinitions) {
795
821
  var suite = suiteFactory(description);
796
822
  if (specDefinitions.length > 0) {
797
- throw new Error('describe does not expect a done parameter');
823
+ throw new Error('describe does not expect any arguments');
798
824
  }
799
825
  if (currentDeclarationSuite.markedPending) {
800
826
  suite.pend();
@@ -889,8 +915,6 @@ getJasmineRequireObj().Env = function(j$) {
889
915
  throwOnExpectationFailure: throwOnExpectationFailure
890
916
  });
891
917
 
892
- runnableLookupTable[spec.id] = spec;
893
-
894
918
  if (!self.specFilter(spec)) {
895
919
  spec.disable();
896
920
  }
@@ -1079,12 +1103,29 @@ getJasmineRequireObj().JsApiReporter = function() {
1079
1103
  return JsApiReporter;
1080
1104
  };
1081
1105
 
1082
- getJasmineRequireObj().CallTracker = function() {
1106
+ getJasmineRequireObj().CallTracker = function(j$) {
1083
1107
 
1084
1108
  function CallTracker() {
1085
1109
  var calls = [];
1110
+ var opts = {};
1111
+
1112
+ function argCloner(context) {
1113
+ var clonedArgs = [];
1114
+ var argsAsArray = j$.util.argsToArray(context.args);
1115
+ for(var i = 0; i < argsAsArray.length; i++) {
1116
+ if(Object.prototype.toString.apply(argsAsArray[i]).match(/^\[object/)) {
1117
+ clonedArgs.push(j$.util.clone(argsAsArray[i]));
1118
+ } else {
1119
+ clonedArgs.push(argsAsArray[i]);
1120
+ }
1121
+ }
1122
+ context.args = clonedArgs;
1123
+ }
1086
1124
 
1087
1125
  this.track = function(context) {
1126
+ if(opts.cloneArgs) {
1127
+ argCloner(context);
1128
+ }
1088
1129
  calls.push(context);
1089
1130
  };
1090
1131
 
@@ -1125,6 +1166,11 @@ getJasmineRequireObj().CallTracker = function() {
1125
1166
  this.reset = function() {
1126
1167
  calls = [];
1127
1168
  };
1169
+
1170
+ this.saveArgumentsByValue = function() {
1171
+ opts.cloneArgs = true;
1172
+ };
1173
+
1128
1174
  }
1129
1175
 
1130
1176
  return CallTracker;
@@ -1214,8 +1260,7 @@ getJasmineRequireObj().Clock = function() {
1214
1260
 
1215
1261
  self.tick = function(millis) {
1216
1262
  if (installed) {
1217
- mockDate.tick(millis);
1218
- delayedFunctionScheduler.tick(millis);
1263
+ delayedFunctionScheduler.tick(millis, function(millis) { mockDate.tick(millis); });
1219
1264
  } else {
1220
1265
  throw new Error('Mock clock is not installed, use jasmine.clock().install()');
1221
1266
  }
@@ -1273,11 +1318,11 @@ getJasmineRequireObj().DelayedFunctionScheduler = function() {
1273
1318
  var currentTime = 0;
1274
1319
  var delayedFnCount = 0;
1275
1320
 
1276
- self.tick = function(millis) {
1321
+ self.tick = function(millis, tickDate) {
1277
1322
  millis = millis || 0;
1278
1323
  var endTime = currentTime + millis;
1279
1324
 
1280
- runScheduledFunctions(endTime);
1325
+ runScheduledFunctions(endTime, tickDate);
1281
1326
  currentTime = endTime;
1282
1327
  };
1283
1328
 
@@ -1380,13 +1425,18 @@ getJasmineRequireObj().DelayedFunctionScheduler = function() {
1380
1425
  }
1381
1426
  }
1382
1427
 
1383
- function runScheduledFunctions(endTime) {
1428
+ function runScheduledFunctions(endTime, tickDate) {
1429
+ tickDate = tickDate || function() {};
1384
1430
  if (scheduledLookup.length === 0 || scheduledLookup[0] > endTime) {
1431
+ tickDate(endTime);
1385
1432
  return;
1386
1433
  }
1387
1434
 
1388
1435
  do {
1389
- currentTime = scheduledLookup.shift();
1436
+ var newCurrentTime = scheduledLookup.shift();
1437
+ tickDate(newCurrentTime - currentTime);
1438
+
1439
+ currentTime = newCurrentTime;
1390
1440
 
1391
1441
  var funcsToRun = scheduledFunctions[currentTime];
1392
1442
  delete scheduledFunctions[currentTime];
@@ -1841,6 +1891,7 @@ getJasmineRequireObj().QueueRunner = function(j$) {
1841
1891
  called = true;
1842
1892
  fn();
1843
1893
  }
1894
+ return null;
1844
1895
  };
1845
1896
  }
1846
1897
 
@@ -1952,14 +2003,23 @@ getJasmineRequireObj().ReportDispatcher = function() {
1952
2003
  }
1953
2004
 
1954
2005
  var reporters = [];
2006
+ var fallbackReporter = null;
1955
2007
 
1956
2008
  this.addReporter = function(reporter) {
1957
2009
  reporters.push(reporter);
1958
2010
  };
2011
+
2012
+ this.provideFallbackReporter = function(reporter) {
2013
+ fallbackReporter = reporter;
2014
+ };
2015
+
1959
2016
 
1960
2017
  return this;
1961
2018
 
1962
2019
  function dispatch(method, args) {
2020
+ if (reporters.length === 0 && fallbackReporter !== null) {
2021
+ reporters.push(fallbackReporter);
2022
+ }
1963
2023
  for (var i = 0; i < reporters.length; i++) {
1964
2024
  var reporter = reporters[i];
1965
2025
  if (reporter[method]) {
@@ -1975,26 +2035,36 @@ getJasmineRequireObj().ReportDispatcher = function() {
1975
2035
 
1976
2036
  getJasmineRequireObj().SpyRegistry = function(j$) {
1977
2037
 
2038
+ var getErrorMsg = j$.formatErrorMsg('<spyOn>', 'spyOn(<object>, <methodName>)');
2039
+
1978
2040
  function SpyRegistry(options) {
1979
2041
  options = options || {};
1980
2042
  var currentSpies = options.currentSpies || function() { return []; };
1981
2043
 
2044
+ this.allowRespy = function(allow){
2045
+ this.respy = allow;
2046
+ };
2047
+
1982
2048
  this.spyOn = function(obj, methodName) {
2049
+
1983
2050
  if (j$.util.isUndefined(obj)) {
1984
- throw new Error('spyOn could not find an object to spy upon for ' + methodName + '()');
2051
+ throw new Error(getErrorMsg('could not find an object to spy upon for ' + methodName + '()'));
1985
2052
  }
1986
2053
 
1987
2054
  if (j$.util.isUndefined(methodName)) {
1988
- throw new Error('No method name supplied');
2055
+ throw new Error(getErrorMsg('No method name supplied'));
1989
2056
  }
1990
2057
 
1991
2058
  if (j$.util.isUndefined(obj[methodName])) {
1992
- throw new Error(methodName + '() method does not exist');
2059
+ throw new Error(getErrorMsg(methodName + '() method does not exist'));
1993
2060
  }
1994
2061
 
1995
- if (obj[methodName] && j$.isSpy(obj[methodName])) {
1996
- //TODO?: should this return the current spy? Downside: may cause user confusion about spy state
1997
- throw new Error(methodName + ' has already been spied upon');
2062
+ if (obj[methodName] && j$.isSpy(obj[methodName]) ) {
2063
+ if ( !!this.respy ){
2064
+ return obj[methodName];
2065
+ }else {
2066
+ throw new Error(getErrorMsg(methodName + ' has already been spied upon'));
2067
+ }
1998
2068
  }
1999
2069
 
2000
2070
  var descriptor;
@@ -2005,28 +2075,37 @@ getJasmineRequireObj().SpyRegistry = function(j$) {
2005
2075
  }
2006
2076
 
2007
2077
  if (descriptor && !(descriptor.writable || descriptor.set)) {
2008
- throw new Error(methodName + ' is not declared writable or has no setter');
2078
+ throw new Error(getErrorMsg(methodName + ' is not declared writable or has no setter'));
2009
2079
  }
2010
2080
 
2011
- var spy = j$.createSpy(methodName, obj[methodName]);
2081
+ var originalMethod = obj[methodName],
2082
+ spiedMethod = j$.createSpy(methodName, originalMethod),
2083
+ restoreStrategy;
2084
+
2085
+ if (Object.prototype.hasOwnProperty.call(obj, methodName)) {
2086
+ restoreStrategy = function() {
2087
+ obj[methodName] = originalMethod;
2088
+ };
2089
+ } else {
2090
+ restoreStrategy = function() {
2091
+ delete obj[methodName];
2092
+ };
2093
+ }
2012
2094
 
2013
2095
  currentSpies().push({
2014
- spy: spy,
2015
- baseObj: obj,
2016
- methodName: methodName,
2017
- originalValue: obj[methodName]
2096
+ restoreObjectToOriginalState: restoreStrategy
2018
2097
  });
2019
2098
 
2020
- obj[methodName] = spy;
2099
+ obj[methodName] = spiedMethod;
2021
2100
 
2022
- return spy;
2101
+ return spiedMethod;
2023
2102
  };
2024
2103
 
2025
2104
  this.clearSpies = function() {
2026
2105
  var spies = currentSpies();
2027
- for (var i = 0; i < spies.length; i++) {
2106
+ for (var i = spies.length - 1; i >= 0; i--) {
2028
2107
  var spyEntry = spies[i];
2029
- spyEntry.baseObj[spyEntry.methodName] = spyEntry.originalValue;
2108
+ spyEntry.restoreObjectToOriginalState();
2030
2109
  }
2031
2110
  };
2032
2111
  }
@@ -2081,6 +2160,9 @@ getJasmineRequireObj().SpyStrategy = function() {
2081
2160
  };
2082
2161
 
2083
2162
  this.callFake = function(fn) {
2163
+ if(!(fn instanceof Function)) {
2164
+ throw new Error('Argument passed to callFake should be a function, got ' + fn);
2165
+ }
2084
2166
  plan = fn;
2085
2167
  return getSpy();
2086
2168
  };
@@ -2125,13 +2207,13 @@ getJasmineRequireObj().Suite = function(j$) {
2125
2207
  };
2126
2208
 
2127
2209
  Suite.prototype.getFullName = function() {
2128
- var fullName = this.description;
2129
- for (var parentSuite = this.parentSuite; parentSuite; parentSuite = parentSuite.parentSuite) {
2210
+ var fullName = [];
2211
+ for (var parentSuite = this; parentSuite; parentSuite = parentSuite.parentSuite) {
2130
2212
  if (parentSuite.parentSuite) {
2131
- fullName = parentSuite.description + ' ' + fullName;
2213
+ fullName.unshift(parentSuite.description);
2132
2214
  }
2133
2215
  }
2134
- return fullName;
2216
+ return fullName.join(' ');
2135
2217
  };
2136
2218
 
2137
2219
  Suite.prototype.disable = function() {
@@ -2665,6 +2747,18 @@ getJasmineRequireObj().errors = function() {
2665
2747
  ExpectationFailed: ExpectationFailed
2666
2748
  };
2667
2749
  };
2750
+ getJasmineRequireObj().formatErrorMsg = function() {
2751
+ function generateErrorMsg(domain, usage) {
2752
+ var usageDefinition = usage ? '\nUsage: ' + usage : '';
2753
+
2754
+ return function errorMsg(msg) {
2755
+ return domain + ' : ' + msg + usageDefinition;
2756
+ };
2757
+ }
2758
+
2759
+ return generateErrorMsg;
2760
+ };
2761
+
2668
2762
  getJasmineRequireObj().matchersUtil = function(j$) {
2669
2763
  // TODO: what to do about jasmine.pp not being inject? move to JSON.stringify? gut PrettyPrinter?
2670
2764
 
@@ -2828,35 +2922,43 @@ getJasmineRequireObj().matchersUtil = function(j$) {
2828
2922
  var size = 0;
2829
2923
  // Recursively compare objects and arrays.
2830
2924
  // Compare array lengths to determine if a deep comparison is necessary.
2831
- if (className == '[object Array]' && a.length !== b.length) {
2832
- result = false;
2833
- }
2925
+ if (className == '[object Array]') {
2926
+ size = a.length;
2927
+ if (size !== b.length) {
2928
+ return false;
2929
+ }
2834
2930
 
2835
- if (result) {
2836
- // Objects with different constructors are not equivalent, but `Object`s
2837
- // or `Array`s from different frames are.
2838
- if (className !== '[object Array]') {
2839
- var aCtor = a.constructor, bCtor = b.constructor;
2840
- if (aCtor !== bCtor && !(isFunction(aCtor) && aCtor instanceof aCtor &&
2841
- isFunction(bCtor) && bCtor instanceof bCtor)) {
2931
+ while (size--) {
2932
+ result = eq(a[size], b[size], aStack, bStack, customTesters);
2933
+ if (!result) {
2842
2934
  return false;
2843
2935
  }
2844
2936
  }
2845
- // Deep compare objects.
2846
- for (var key in a) {
2847
- if (has(a, key)) {
2848
- // Count the expected number of properties.
2849
- size++;
2850
- // Deep compare each member.
2851
- if (!(result = has(b, key) && eq(a[key], b[key], aStack, bStack, customTesters))) { break; }
2852
- }
2937
+ } else {
2938
+
2939
+ // Objects with different constructors are not equivalent, but `Object`s
2940
+ // or `Array`s from different frames are.
2941
+ var aCtor = a.constructor, bCtor = b.constructor;
2942
+ if (aCtor !== bCtor && !(isObjectConstructor(aCtor) &&
2943
+ isObjectConstructor(bCtor))) {
2944
+ return false;
2853
2945
  }
2854
- // Ensure that both objects contain the same number of properties.
2855
- if (result) {
2856
- for (key in b) {
2857
- if (has(b, key) && !(size--)) { break; }
2858
- }
2859
- result = !size;
2946
+ }
2947
+
2948
+ // Deep compare objects.
2949
+ var aKeys = keys(a, className == '[object Array]'), key;
2950
+ size = aKeys.length;
2951
+
2952
+ // Ensure that both objects contain the same number of properties before comparing deep equality.
2953
+ if (keys(b, className == '[object Array]').length !== size) { return false; }
2954
+
2955
+ while (size--) {
2956
+ key = aKeys[size];
2957
+ // Deep compare each member
2958
+ result = has(b, key) && eq(a[key], b[key], aStack, bStack, customTesters);
2959
+
2960
+ if (!result) {
2961
+ return false;
2860
2962
  }
2861
2963
  }
2862
2964
  // Remove the first object from the stack of traversed objects.
@@ -2865,14 +2967,48 @@ getJasmineRequireObj().matchersUtil = function(j$) {
2865
2967
 
2866
2968
  return result;
2867
2969
 
2868
- function has(obj, key) {
2869
- return Object.prototype.hasOwnProperty.call(obj, key);
2870
- }
2970
+ function keys(obj, isArray) {
2971
+ var allKeys = Object.keys ? Object.keys(obj) :
2972
+ (function(o) {
2973
+ var keys = [];
2974
+ for (var key in o) {
2975
+ if (has(o, key)) {
2976
+ keys.push(key);
2977
+ }
2978
+ }
2979
+ return keys;
2980
+ })(obj);
2981
+
2982
+ if (!isArray) {
2983
+ return allKeys;
2984
+ }
2985
+
2986
+ var extraKeys = [];
2987
+ for (var i in allKeys) {
2988
+ if (!allKeys[i].match(/^[0-9]+$/)) {
2989
+ extraKeys.push(allKeys[i]);
2990
+ }
2991
+ }
2871
2992
 
2872
- function isFunction(obj) {
2873
- return typeof obj === 'function';
2993
+ return extraKeys;
2874
2994
  }
2875
2995
  }
2996
+
2997
+ function has(obj, key) {
2998
+ return Object.prototype.hasOwnProperty.call(obj, key);
2999
+ }
3000
+
3001
+ function isFunction(obj) {
3002
+ return typeof obj === 'function';
3003
+ }
3004
+
3005
+ function isObjectConstructor(ctor) {
3006
+ // aCtor instanceof aCtor is true for the Object and Function
3007
+ // constructors (since a constructor is-a Function and a function is-a
3008
+ // Object). We don't just compare ctor === Object because the constructor
3009
+ // might come from a different frame with different globals.
3010
+ return isFunction(ctor) && ctor instanceof ctor;
3011
+ }
2876
3012
  };
2877
3013
 
2878
3014
  getJasmineRequireObj().toBe = function() {
@@ -2952,6 +3088,21 @@ getJasmineRequireObj().toBeGreaterThan = function() {
2952
3088
  };
2953
3089
 
2954
3090
 
3091
+ getJasmineRequireObj().toBeGreaterThanOrEqual = function() {
3092
+
3093
+ function toBeGreaterThanOrEqual() {
3094
+ return {
3095
+ compare: function(actual, expected) {
3096
+ return {
3097
+ pass: actual >= expected
3098
+ };
3099
+ }
3100
+ };
3101
+ }
3102
+
3103
+ return toBeGreaterThanOrEqual;
3104
+ };
3105
+
2955
3106
  getJasmineRequireObj().toBeLessThan = function() {
2956
3107
  function toBeLessThan() {
2957
3108
  return {
@@ -2966,6 +3117,21 @@ getJasmineRequireObj().toBeLessThan = function() {
2966
3117
 
2967
3118
  return toBeLessThan;
2968
3119
  };
3120
+ getJasmineRequireObj().toBeLessThanOrEqual = function() {
3121
+ function toBeLessThanOrEqual() {
3122
+ return {
3123
+
3124
+ compare: function(actual, expected) {
3125
+ return {
3126
+ pass: actual <= expected
3127
+ };
3128
+ }
3129
+ };
3130
+ }
3131
+
3132
+ return toBeLessThanOrEqual;
3133
+ };
3134
+
2969
3135
  getJasmineRequireObj().toBeNaN = function(j$) {
2970
3136
 
2971
3137
  function toBeNaN() {
@@ -3074,17 +3240,19 @@ getJasmineRequireObj().toEqual = function() {
3074
3240
 
3075
3241
  getJasmineRequireObj().toHaveBeenCalled = function(j$) {
3076
3242
 
3243
+ var getErrorMsg = j$.formatErrorMsg('<toHaveBeenCalled>', 'expect(<spyObj>).toHaveBeenCalled()');
3244
+
3077
3245
  function toHaveBeenCalled() {
3078
3246
  return {
3079
3247
  compare: function(actual) {
3080
3248
  var result = {};
3081
3249
 
3082
3250
  if (!j$.isSpy(actual)) {
3083
- throw new Error('Expected a spy, but got ' + j$.pp(actual) + '.');
3251
+ throw new Error(getErrorMsg('Expected a spy, but got ' + j$.pp(actual) + '.'));
3084
3252
  }
3085
3253
 
3086
3254
  if (arguments.length > 1) {
3087
- throw new Error('toHaveBeenCalled does not take arguments, use toHaveBeenCalledWith');
3255
+ throw new Error(getErrorMsg('Does not take arguments, use toHaveBeenCalledWith'));
3088
3256
  }
3089
3257
 
3090
3258
  result.pass = actual.calls.any();
@@ -3103,18 +3271,20 @@ getJasmineRequireObj().toHaveBeenCalled = function(j$) {
3103
3271
 
3104
3272
  getJasmineRequireObj().toHaveBeenCalledTimes = function(j$) {
3105
3273
 
3274
+ var getErrorMsg = j$.formatErrorMsg('<toHaveBeenCalledTimes>', 'expect(<spyObj>).toHaveBeenCalledTimes(<Number>)');
3275
+
3106
3276
  function toHaveBeenCalledTimes() {
3107
3277
  return {
3108
3278
  compare: function(actual, expected) {
3109
3279
  if (!j$.isSpy(actual)) {
3110
- throw new Error('Expected a spy, but got ' + j$.pp(actual) + '.');
3280
+ throw new Error(getErrorMsg('Expected a spy, but got ' + j$.pp(actual) + '.'));
3111
3281
  }
3112
3282
 
3113
3283
  var args = Array.prototype.slice.call(arguments, 0),
3114
3284
  result = { pass: false };
3115
3285
 
3116
- if(!expected){
3117
- throw new Error('Expected times failed is required as an argument.');
3286
+ if (!j$.isNumber_(expected)){
3287
+ throw new Error(getErrorMsg('The expected times failed is a required argument and must be a number.'));
3118
3288
  }
3119
3289
 
3120
3290
  actual = args[0];
@@ -3134,6 +3304,8 @@ getJasmineRequireObj().toHaveBeenCalledTimes = function(j$) {
3134
3304
 
3135
3305
  getJasmineRequireObj().toHaveBeenCalledWith = function(j$) {
3136
3306
 
3307
+ var getErrorMsg = j$.formatErrorMsg('<toHaveBeenCalledWith>', 'expect(<spyObj>).toHaveBeenCalledWith(...arguments)');
3308
+
3137
3309
  function toHaveBeenCalledWith(util, customEqualityTesters) {
3138
3310
  return {
3139
3311
  compare: function() {
@@ -3143,7 +3315,7 @@ getJasmineRequireObj().toHaveBeenCalledWith = function(j$) {
3143
3315
  result = { pass: false };
3144
3316
 
3145
3317
  if (!j$.isSpy(actual)) {
3146
- throw new Error('Expected a spy, but got ' + j$.pp(actual) + '.');
3318
+ throw new Error(getErrorMsg('Expected a spy, but got ' + j$.pp(actual) + '.'));
3147
3319
  }
3148
3320
 
3149
3321
  if (!actual.calls.any()) {
@@ -3168,11 +3340,13 @@ getJasmineRequireObj().toHaveBeenCalledWith = function(j$) {
3168
3340
 
3169
3341
  getJasmineRequireObj().toMatch = function(j$) {
3170
3342
 
3343
+ var getErrorMsg = j$.formatErrorMsg('<toMatch>', 'expect(<expectation>).toMatch(<string> || <regexp>)');
3344
+
3171
3345
  function toMatch() {
3172
3346
  return {
3173
3347
  compare: function(actual, expected) {
3174
3348
  if (!j$.isString_(expected) && !j$.isA_('RegExp', expected)) {
3175
- throw new Error('Expected is not a String or a RegExp');
3349
+ throw new Error(getErrorMsg('Expected is not a String or a RegExp'));
3176
3350
  }
3177
3351
 
3178
3352
  var regexp = new RegExp(expected);
@@ -3189,6 +3363,8 @@ getJasmineRequireObj().toMatch = function(j$) {
3189
3363
 
3190
3364
  getJasmineRequireObj().toThrow = function(j$) {
3191
3365
 
3366
+ var getErrorMsg = j$.formatErrorMsg('<toThrow>', 'expect(function() {<expectation>}).toThrow()');
3367
+
3192
3368
  function toThrow(util) {
3193
3369
  return {
3194
3370
  compare: function(actual, expected) {
@@ -3197,7 +3373,7 @@ getJasmineRequireObj().toThrow = function(j$) {
3197
3373
  thrown;
3198
3374
 
3199
3375
  if (typeof actual != 'function') {
3200
- throw new Error('Actual is not a Function');
3376
+ throw new Error(getErrorMsg('Actual is not a Function'));
3201
3377
  }
3202
3378
 
3203
3379
  try {
@@ -3235,6 +3411,9 @@ getJasmineRequireObj().toThrow = function(j$) {
3235
3411
  };
3236
3412
 
3237
3413
  getJasmineRequireObj().toThrowError = function(j$) {
3414
+
3415
+ var getErrorMsg = j$.formatErrorMsg('<toThrowError>', 'expect(function() {<expectation>}).toThrowError(<ErrorConstructor>, <message>)');
3416
+
3238
3417
  function toThrowError () {
3239
3418
  return {
3240
3419
  compare: function(actual) {
@@ -3244,7 +3423,7 @@ getJasmineRequireObj().toThrowError = function(j$) {
3244
3423
  thrown;
3245
3424
 
3246
3425
  if (typeof actual != 'function') {
3247
- throw new Error('Actual is not a Function');
3426
+ throw new Error(getErrorMsg('Actual is not a Function'));
3248
3427
  }
3249
3428
 
3250
3429
  var errorMatcher = getMatcher.apply(null, arguments);
@@ -3300,15 +3479,15 @@ getJasmineRequireObj().toThrowError = function(j$) {
3300
3479
  errorType = arguments[1];
3301
3480
  expected = arguments[2];
3302
3481
  if (!isAnErrorType(errorType)) {
3303
- throw new Error('Expected error type is not an Error.');
3482
+ throw new Error(getErrorMsg('Expected error type is not an Error.'));
3304
3483
  }
3305
3484
  }
3306
3485
 
3307
3486
  if (expected && !isStringOrRegExp(expected)) {
3308
3487
  if (errorType) {
3309
- throw new Error('Expected error message is not a string or RegExp.');
3488
+ throw new Error(getErrorMsg('Expected error message is not a string or RegExp.'));
3310
3489
  } else {
3311
- throw new Error('Expected is not an Error, string, or RegExp.');
3490
+ throw new Error(getErrorMsg('Expected is not an Error, string, or RegExp.'));
3312
3491
  }
3313
3492
  }
3314
3493
 
@@ -3450,5 +3629,5 @@ getJasmineRequireObj().interface = function(jasmine, env) {
3450
3629
  };
3451
3630
 
3452
3631
  getJasmineRequireObj().version = function() {
3453
- return '2.4.1';
3632
+ return '2.5.0';
3454
3633
  };