jasmine-core 2.4.1 → 2.5.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 (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
  };