jasmine-core 2.4.0 → 2.5.2

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.
@@ -0,0 +1,7 @@
1
+ languages:
2
+ JavaScript: true
3
+ exclude_paths:
4
+ - "lib/*"
5
+ - "dist/*"
6
+ - "grunt/*"
7
+ - "images/*"
package/.editorconfig ADDED
@@ -0,0 +1,16 @@
1
+ [*]
2
+ charset = utf-8
3
+ end_of_line = lf
4
+ insert_final_newline = true
5
+
6
+ [*.{js, json, sh, yml, gemspec}]
7
+ indent_style = space
8
+ indent_size = 2
9
+
10
+ [{Rakefile, .jshintrc}]
11
+ indent_style = space
12
+ indent_size = 2
13
+
14
+ [*.{py}]
15
+ indent_style = space
16
+ indent_size = 4
@@ -115,6 +115,15 @@ Jasmine uses the [Jasmine NPM package](http://github.com/jasmine/jasmine-npm) to
115
115
 
116
116
  ...and then the results will print to the console. All specs run except those that expect a browser (the specs in `spec/html` are ignored).
117
117
 
118
+ The easiest way to run the tests in **Internet Explorer** is to run a VM that has IE installed. It's easy to do this with VirtualBox.
119
+
120
+ 1. Download and install [VirtualBox](https://www.virtualbox.org/wiki/Downloads).
121
+ 1. Download a VM image [from Microsoft](https://developer.microsoft.com/en-us/microsoft-edge/tools/vms/). Select "VirtualBox" as the platform.
122
+ 1. Unzip the downloaded archive. There should be an OVA file inside.
123
+ 1. In VirtualBox, choose `File > Import Appliance` and select the OVA file. Accept the default settings in the dialog that appears. Now you have a Windows VM!
124
+ 1. Run the VM and start IE.
125
+ 1. With `bundle exec rake jasmine` running on your host machine, navigate to `http://10.0.2.2:8888` in IE.
126
+
118
127
  ## Before Committing or Submitting a Pull Request
119
128
 
120
129
  1. Ensure all specs are green in browser *and* node
@@ -0,0 +1,17 @@
1
+ ### Are you creating an issue in the correct repository?
2
+
3
+ - When in doubt, create an issue here.
4
+ - If you have an issue with the Jasmine docs, file an issue in the docs repo
5
+ here: https://github.com/jasmine/jasmine.github.io
6
+ - This repository is for the core Jasmine framework
7
+ - If you are using a test runner that wraps Jasmine (Jasmine npm, karma, etc),
8
+ consider filing an issue with that library if appropriate
9
+
10
+ ### When submitting an issue, please answer the following:
11
+
12
+ - What version are you using?
13
+ - What environment are you running Jasmine in (node, browser, etc)?
14
+ - How are you running Jasmine (standalone, npm, karma, etc)?
15
+ - If possible, include an example spec that demonstrates your issue.
16
+
17
+ Thanks for using Jasmine!
package/MIT.LICENSE CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2008-2014 Pivotal Labs
1
+ Copyright (c) 2008-2016 Pivotal Labs
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining
4
4
  a copy of this software and associated documentation files (the
package/README.md CHANGED
@@ -9,7 +9,7 @@
9
9
 
10
10
  Jasmine is a Behavior Driven Development testing framework for JavaScript. It does not rely on browsers, DOM, or any JavaScript framework. Thus it's suited for websites, [Node.js](http://nodejs.org) projects, or anywhere that JavaScript can run.
11
11
 
12
- Documentation & guides live here: [http://jasmine.github.io](http://jasmine.github.io/)
12
+ Documentation & guides live here: [http://jasmine.github.io](http://jasmine.github.io/)
13
13
  For a quick start guide of Jasmine 2.0, see the beginning of [http://jasmine.github.io/2.0/introduction.html](http://jasmine.github.io/2.0/introduction.html)
14
14
 
15
15
  Upgrading from Jasmine 1.x? Check out the [2.0 release notes](https://github.com/jasmine/jasmine/blob/v2.0.0/release_notes/20.md) for a list of what's new (including breaking interface changes). You can also read the [upgrade guide](http://jasmine.github.io/2.0/upgrading.html).
@@ -29,6 +29,9 @@ For the Jasmine Ruby Gem:<br>
29
29
  For the Jasmine Python Egg:<br>
30
30
  [https://github.com/jasmine/jasmine-py](https://github.com/jasmine/jasmine-py)
31
31
 
32
+ For the Jasmine headless browser gulp plugin:<br>
33
+ [https://github.com/jasmine/gulp-jasmine-browser](https://github.com/jasmine/gulp-jasmine-browser)
34
+
32
35
  To install Jasmine standalone on your local box:
33
36
 
34
37
  * Download the standalone distribution for your desired release from the [releases page](https://github.com/jasmine/jasmine/releases)
@@ -73,4 +76,4 @@ Jasmine tests itself across many browsers (Safari, Chrome, Firefox, PhantomJS, a
73
76
  * [Christian Williams](mailto:antixian666@gmail.com), Cloud Foundry
74
77
  * Sheel Choksi
75
78
 
76
- Copyright (c) 2008-2015 Pivotal Labs. This software is licensed under the MIT License.
79
+ Copyright (c) 2008-2016 Pivotal Labs. This software is licensed under the MIT License.
@@ -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();
@@ -66,7 +67,7 @@ var getJasmineRequireObj = (function (jasmineGlobal) {
66
67
  j$.ReportDispatcher = jRequire.ReportDispatcher();
67
68
  j$.Spec = jRequire.Spec(j$);
68
69
  j$.SpyRegistry = jRequire.SpyRegistry(j$);
69
- j$.SpyStrategy = jRequire.SpyStrategy();
70
+ j$.SpyStrategy = jRequire.SpyStrategy(j$);
70
71
  j$.StringMatching = jRequire.StringMatching(j$);
71
72
  j$.Suite = jRequire.Suite(j$);
72
73
  j$.Timer = jRequire.Timer();
@@ -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',
@@ -144,6 +147,10 @@ getJasmineRequireObj().base = function(j$, jasmineGlobal) {
144
147
  return j$.isA_('Number', value);
145
148
  };
146
149
 
150
+ j$.isFunction_ = function(value) {
151
+ return j$.isA_('Function', value);
152
+ };
153
+
147
154
  j$.isA_ = function(typeName, value) {
148
155
  return Object.prototype.toString.apply(value) === '[object ' + typeName + ']';
149
156
  };
@@ -153,7 +160,12 @@ getJasmineRequireObj().base = function(j$, jasmineGlobal) {
153
160
  };
154
161
 
155
162
  j$.fnNameFor = function(func) {
156
- return func.name || func.toString().match(/^\s*function\s*(\w*)\s*\(/)[1];
163
+ if (func.name) {
164
+ return func.name;
165
+ }
166
+
167
+ var matches = func.toString().match(/^\s*function\s*(\w*)\s*\(/);
168
+ return matches ? matches[1] : '<anonymous>';
157
169
  };
158
170
 
159
171
  j$.any = function(clazz) {
@@ -515,7 +527,6 @@ getJasmineRequireObj().Env = function(j$) {
515
527
  var realClearTimeout = j$.getGlobal().clearTimeout;
516
528
  this.clock = new j$.Clock(global, function () { return new j$.DelayedFunctionScheduler(); }, new j$.MockDate(global));
517
529
 
518
- var runnableLookupTable = {};
519
530
  var runnableResources = {};
520
531
 
521
532
  var currentSpec = null;
@@ -612,7 +623,7 @@ getJasmineRequireObj().Env = function(j$) {
612
623
 
613
624
  while(suite) {
614
625
  befores = befores.concat(suite.beforeFns);
615
- afters = afters.concat(suite.afterFns.reverse());
626
+ afters = afters.concat(suite.afterFns);
616
627
 
617
628
  suite = suite.parentSuite;
618
629
  }
@@ -625,7 +636,13 @@ getJasmineRequireObj().Env = function(j$) {
625
636
  };
626
637
 
627
638
  var getSpecName = function(spec, suite) {
628
- return suite.getFullName() + ' ' + spec.description;
639
+ var fullName = [spec.description],
640
+ suiteFullName = suite.getFullName();
641
+
642
+ if (suiteFullName !== '') {
643
+ fullName.unshift(suiteFullName);
644
+ }
645
+ return fullName.join(' ');
629
646
  };
630
647
 
631
648
  // TODO: we may just be able to pass in the fn instead of wrapping here
@@ -701,9 +718,9 @@ getJasmineRequireObj().Env = function(j$) {
701
718
  env: this,
702
719
  id: getNextSuiteId(),
703
720
  description: 'Jasmine__TopLevel__Suite',
704
- queueRunner: queueRunnerFactory
721
+ expectationFactory: expectationFactory,
722
+ expectationResultFactory: expectationResultFactory
705
723
  });
706
- runnableLookupTable[topSuite.id] = topSuite;
707
724
  defaultResourcesForRunnable(topSuite.id);
708
725
  currentDeclarationSuite = topSuite;
709
726
 
@@ -754,9 +771,15 @@ getJasmineRequireObj().Env = function(j$) {
754
771
  totalSpecsDefined: totalSpecsDefined
755
772
  });
756
773
 
774
+ currentlyExecutingSuites.push(topSuite);
775
+
757
776
  processor.execute(function() {
777
+ clearResourcesForRunnable(topSuite.id);
778
+ currentlyExecutingSuites.pop();
779
+
758
780
  reporter.jasmineDone({
759
- order: order
781
+ order: order,
782
+ failedExpectations: topSuite.result.failedExpectations
760
783
  });
761
784
  });
762
785
  };
@@ -765,6 +788,14 @@ getJasmineRequireObj().Env = function(j$) {
765
788
  reporter.addReporter(reporterToAdd);
766
789
  };
767
790
 
791
+ this.provideFallbackReporter = function(reporterToAdd) {
792
+ reporter.provideFallbackReporter(reporterToAdd);
793
+ };
794
+
795
+ this.clearReporters = function() {
796
+ reporter.clearReporters();
797
+ };
798
+
768
799
  var spyRegistry = new j$.SpyRegistry({currentSpies: function() {
769
800
  if(!currentRunnable()) {
770
801
  throw new Error('Spies must be created in a before function or a spec');
@@ -772,6 +803,10 @@ getJasmineRequireObj().Env = function(j$) {
772
803
  return runnableResources[currentRunnable().id].spies;
773
804
  }});
774
805
 
806
+ this.allowRespy = function(allow){
807
+ spyRegistry.allowRespy(allow);
808
+ };
809
+
775
810
  this.spyOn = function() {
776
811
  return spyRegistry.spyOn.apply(spyRegistry, arguments);
777
812
  };
@@ -787,14 +822,13 @@ getJasmineRequireObj().Env = function(j$) {
787
822
  throwOnExpectationFailure: throwOnExpectationFailure
788
823
  });
789
824
 
790
- runnableLookupTable[suite.id] = suite;
791
825
  return suite;
792
826
  };
793
827
 
794
828
  this.describe = function(description, specDefinitions) {
795
829
  var suite = suiteFactory(description);
796
830
  if (specDefinitions.length > 0) {
797
- throw new Error('describe does not expect a done parameter');
831
+ throw new Error('describe does not expect any arguments');
798
832
  }
799
833
  if (currentDeclarationSuite.markedPending) {
800
834
  suite.pend();
@@ -889,8 +923,6 @@ getJasmineRequireObj().Env = function(j$) {
889
923
  throwOnExpectationFailure: throwOnExpectationFailure
890
924
  });
891
925
 
892
- runnableLookupTable[spec.id] = spec;
893
-
894
926
  if (!self.specFilter(spec)) {
895
927
  spec.disable();
896
928
  }
@@ -1079,12 +1111,29 @@ getJasmineRequireObj().JsApiReporter = function() {
1079
1111
  return JsApiReporter;
1080
1112
  };
1081
1113
 
1082
- getJasmineRequireObj().CallTracker = function() {
1114
+ getJasmineRequireObj().CallTracker = function(j$) {
1083
1115
 
1084
1116
  function CallTracker() {
1085
1117
  var calls = [];
1118
+ var opts = {};
1119
+
1120
+ function argCloner(context) {
1121
+ var clonedArgs = [];
1122
+ var argsAsArray = j$.util.argsToArray(context.args);
1123
+ for(var i = 0; i < argsAsArray.length; i++) {
1124
+ if(Object.prototype.toString.apply(argsAsArray[i]).match(/^\[object/)) {
1125
+ clonedArgs.push(j$.util.clone(argsAsArray[i]));
1126
+ } else {
1127
+ clonedArgs.push(argsAsArray[i]);
1128
+ }
1129
+ }
1130
+ context.args = clonedArgs;
1131
+ }
1086
1132
 
1087
1133
  this.track = function(context) {
1134
+ if(opts.cloneArgs) {
1135
+ argCloner(context);
1136
+ }
1088
1137
  calls.push(context);
1089
1138
  };
1090
1139
 
@@ -1125,6 +1174,11 @@ getJasmineRequireObj().CallTracker = function() {
1125
1174
  this.reset = function() {
1126
1175
  calls = [];
1127
1176
  };
1177
+
1178
+ this.saveArgumentsByValue = function() {
1179
+ opts.cloneArgs = true;
1180
+ };
1181
+
1128
1182
  }
1129
1183
 
1130
1184
  return CallTracker;
@@ -1214,8 +1268,7 @@ getJasmineRequireObj().Clock = function() {
1214
1268
 
1215
1269
  self.tick = function(millis) {
1216
1270
  if (installed) {
1217
- mockDate.tick(millis);
1218
- delayedFunctionScheduler.tick(millis);
1271
+ delayedFunctionScheduler.tick(millis, function(millis) { mockDate.tick(millis); });
1219
1272
  } else {
1220
1273
  throw new Error('Mock clock is not installed, use jasmine.clock().install()');
1221
1274
  }
@@ -1273,11 +1326,11 @@ getJasmineRequireObj().DelayedFunctionScheduler = function() {
1273
1326
  var currentTime = 0;
1274
1327
  var delayedFnCount = 0;
1275
1328
 
1276
- self.tick = function(millis) {
1329
+ self.tick = function(millis, tickDate) {
1277
1330
  millis = millis || 0;
1278
1331
  var endTime = currentTime + millis;
1279
1332
 
1280
- runScheduledFunctions(endTime);
1333
+ runScheduledFunctions(endTime, tickDate);
1281
1334
  currentTime = endTime;
1282
1335
  };
1283
1336
 
@@ -1380,13 +1433,18 @@ getJasmineRequireObj().DelayedFunctionScheduler = function() {
1380
1433
  }
1381
1434
  }
1382
1435
 
1383
- function runScheduledFunctions(endTime) {
1436
+ function runScheduledFunctions(endTime, tickDate) {
1437
+ tickDate = tickDate || function() {};
1384
1438
  if (scheduledLookup.length === 0 || scheduledLookup[0] > endTime) {
1439
+ tickDate(endTime - currentTime);
1385
1440
  return;
1386
1441
  }
1387
1442
 
1388
1443
  do {
1389
- currentTime = scheduledLookup.shift();
1444
+ var newCurrentTime = scheduledLookup.shift();
1445
+ tickDate(newCurrentTime - currentTime);
1446
+
1447
+ currentTime = newCurrentTime;
1390
1448
 
1391
1449
  var funcsToRun = scheduledFunctions[currentTime];
1392
1450
  delete scheduledFunctions[currentTime];
@@ -1405,6 +1463,11 @@ getJasmineRequireObj().DelayedFunctionScheduler = function() {
1405
1463
  // scheduled in a funcToRun from forcing an extra iteration
1406
1464
  currentTime !== endTime &&
1407
1465
  scheduledLookup[0] <= endTime);
1466
+
1467
+ // ran out of functions to call, but still time left on the clock
1468
+ if (currentTime !== endTime) {
1469
+ tickDate(endTime - currentTime);
1470
+ }
1408
1471
  }
1409
1472
  }
1410
1473
 
@@ -1841,6 +1904,7 @@ getJasmineRequireObj().QueueRunner = function(j$) {
1841
1904
  called = true;
1842
1905
  fn();
1843
1906
  }
1907
+ return null;
1844
1908
  };
1845
1909
  }
1846
1910
 
@@ -1952,14 +2016,26 @@ getJasmineRequireObj().ReportDispatcher = function() {
1952
2016
  }
1953
2017
 
1954
2018
  var reporters = [];
2019
+ var fallbackReporter = null;
1955
2020
 
1956
2021
  this.addReporter = function(reporter) {
1957
2022
  reporters.push(reporter);
1958
2023
  };
1959
2024
 
2025
+ this.provideFallbackReporter = function(reporter) {
2026
+ fallbackReporter = reporter;
2027
+ };
2028
+
2029
+ this.clearReporters = function() {
2030
+ reporters = [];
2031
+ };
2032
+
1960
2033
  return this;
1961
2034
 
1962
2035
  function dispatch(method, args) {
2036
+ if (reporters.length === 0 && fallbackReporter !== null) {
2037
+ reporters.push(fallbackReporter);
2038
+ }
1963
2039
  for (var i = 0; i < reporters.length; i++) {
1964
2040
  var reporter = reporters[i];
1965
2041
  if (reporter[method]) {
@@ -1975,26 +2051,36 @@ getJasmineRequireObj().ReportDispatcher = function() {
1975
2051
 
1976
2052
  getJasmineRequireObj().SpyRegistry = function(j$) {
1977
2053
 
2054
+ var getErrorMsg = j$.formatErrorMsg('<spyOn>', 'spyOn(<object>, <methodName>)');
2055
+
1978
2056
  function SpyRegistry(options) {
1979
2057
  options = options || {};
1980
2058
  var currentSpies = options.currentSpies || function() { return []; };
1981
2059
 
2060
+ this.allowRespy = function(allow){
2061
+ this.respy = allow;
2062
+ };
2063
+
1982
2064
  this.spyOn = function(obj, methodName) {
2065
+
1983
2066
  if (j$.util.isUndefined(obj)) {
1984
- throw new Error('spyOn could not find an object to spy upon for ' + methodName + '()');
2067
+ throw new Error(getErrorMsg('could not find an object to spy upon for ' + methodName + '()'));
1985
2068
  }
1986
2069
 
1987
2070
  if (j$.util.isUndefined(methodName)) {
1988
- throw new Error('No method name supplied');
2071
+ throw new Error(getErrorMsg('No method name supplied'));
1989
2072
  }
1990
2073
 
1991
2074
  if (j$.util.isUndefined(obj[methodName])) {
1992
- throw new Error(methodName + '() method does not exist');
2075
+ throw new Error(getErrorMsg(methodName + '() method does not exist'));
1993
2076
  }
1994
2077
 
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');
2078
+ if (obj[methodName] && j$.isSpy(obj[methodName]) ) {
2079
+ if ( !!this.respy ){
2080
+ return obj[methodName];
2081
+ }else {
2082
+ throw new Error(getErrorMsg(methodName + ' has already been spied upon'));
2083
+ }
1998
2084
  }
1999
2085
 
2000
2086
  var descriptor;
@@ -2005,28 +2091,39 @@ getJasmineRequireObj().SpyRegistry = function(j$) {
2005
2091
  }
2006
2092
 
2007
2093
  if (descriptor && !(descriptor.writable || descriptor.set)) {
2008
- throw new Error(methodName + ' is not declared writable or has no setter');
2094
+ throw new Error(getErrorMsg(methodName + ' is not declared writable or has no setter'));
2009
2095
  }
2010
2096
 
2011
- var spy = j$.createSpy(methodName, obj[methodName]);
2097
+ var originalMethod = obj[methodName],
2098
+ spiedMethod = j$.createSpy(methodName, originalMethod),
2099
+ restoreStrategy;
2100
+
2101
+ if (Object.prototype.hasOwnProperty.call(obj, methodName)) {
2102
+ restoreStrategy = function() {
2103
+ obj[methodName] = originalMethod;
2104
+ };
2105
+ } else {
2106
+ restoreStrategy = function() {
2107
+ if (!delete obj[methodName]) {
2108
+ obj[methodName] = originalMethod;
2109
+ }
2110
+ };
2111
+ }
2012
2112
 
2013
2113
  currentSpies().push({
2014
- spy: spy,
2015
- baseObj: obj,
2016
- methodName: methodName,
2017
- originalValue: obj[methodName]
2114
+ restoreObjectToOriginalState: restoreStrategy
2018
2115
  });
2019
2116
 
2020
- obj[methodName] = spy;
2117
+ obj[methodName] = spiedMethod;
2021
2118
 
2022
- return spy;
2119
+ return spiedMethod;
2023
2120
  };
2024
2121
 
2025
2122
  this.clearSpies = function() {
2026
2123
  var spies = currentSpies();
2027
- for (var i = 0; i < spies.length; i++) {
2124
+ for (var i = spies.length - 1; i >= 0; i--) {
2028
2125
  var spyEntry = spies[i];
2029
- spyEntry.baseObj[spyEntry.methodName] = spyEntry.originalValue;
2126
+ spyEntry.restoreObjectToOriginalState();
2030
2127
  }
2031
2128
  };
2032
2129
  }
@@ -2034,7 +2131,7 @@ getJasmineRequireObj().SpyRegistry = function(j$) {
2034
2131
  return SpyRegistry;
2035
2132
  };
2036
2133
 
2037
- getJasmineRequireObj().SpyStrategy = function() {
2134
+ getJasmineRequireObj().SpyStrategy = function(j$) {
2038
2135
 
2039
2136
  function SpyStrategy(options) {
2040
2137
  options = options || {};
@@ -2081,6 +2178,9 @@ getJasmineRequireObj().SpyStrategy = function() {
2081
2178
  };
2082
2179
 
2083
2180
  this.callFake = function(fn) {
2181
+ if(!j$.isFunction_(fn)) {
2182
+ throw new Error('Argument passed to callFake should be a function, got ' + fn);
2183
+ }
2084
2184
  plan = fn;
2085
2185
  return getSpy();
2086
2186
  };
@@ -2125,13 +2225,13 @@ getJasmineRequireObj().Suite = function(j$) {
2125
2225
  };
2126
2226
 
2127
2227
  Suite.prototype.getFullName = function() {
2128
- var fullName = this.description;
2129
- for (var parentSuite = this.parentSuite; parentSuite; parentSuite = parentSuite.parentSuite) {
2228
+ var fullName = [];
2229
+ for (var parentSuite = this; parentSuite; parentSuite = parentSuite.parentSuite) {
2130
2230
  if (parentSuite.parentSuite) {
2131
- fullName = parentSuite.description + ' ' + fullName;
2231
+ fullName.unshift(parentSuite.description);
2132
2232
  }
2133
2233
  }
2134
- return fullName;
2234
+ return fullName.join(' ');
2135
2235
  };
2136
2236
 
2137
2237
  Suite.prototype.disable = function() {
@@ -2665,6 +2765,18 @@ getJasmineRequireObj().errors = function() {
2665
2765
  ExpectationFailed: ExpectationFailed
2666
2766
  };
2667
2767
  };
2768
+ getJasmineRequireObj().formatErrorMsg = function() {
2769
+ function generateErrorMsg(domain, usage) {
2770
+ var usageDefinition = usage ? '\nUsage: ' + usage : '';
2771
+
2772
+ return function errorMsg(msg) {
2773
+ return domain + ' : ' + msg + usageDefinition;
2774
+ };
2775
+ }
2776
+
2777
+ return generateErrorMsg;
2778
+ };
2779
+
2668
2780
  getJasmineRequireObj().matchersUtil = function(j$) {
2669
2781
  // TODO: what to do about jasmine.pp not being inject? move to JSON.stringify? gut PrettyPrinter?
2670
2782
 
@@ -2828,35 +2940,43 @@ getJasmineRequireObj().matchersUtil = function(j$) {
2828
2940
  var size = 0;
2829
2941
  // Recursively compare objects and arrays.
2830
2942
  // Compare array lengths to determine if a deep comparison is necessary.
2831
- if (className == '[object Array]' && a.length !== b.length) {
2832
- result = false;
2833
- }
2943
+ if (className == '[object Array]') {
2944
+ size = a.length;
2945
+ if (size !== b.length) {
2946
+ return false;
2947
+ }
2834
2948
 
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)) {
2949
+ while (size--) {
2950
+ result = eq(a[size], b[size], aStack, bStack, customTesters);
2951
+ if (!result) {
2842
2952
  return false;
2843
2953
  }
2844
2954
  }
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
- }
2955
+ } else {
2956
+
2957
+ // Objects with different constructors are not equivalent, but `Object`s
2958
+ // or `Array`s from different frames are.
2959
+ var aCtor = a.constructor, bCtor = b.constructor;
2960
+ if (aCtor !== bCtor && !(isObjectConstructor(aCtor) &&
2961
+ isObjectConstructor(bCtor))) {
2962
+ return false;
2853
2963
  }
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;
2964
+ }
2965
+
2966
+ // Deep compare objects.
2967
+ var aKeys = keys(a, className == '[object Array]'), key;
2968
+ size = aKeys.length;
2969
+
2970
+ // Ensure that both objects contain the same number of properties before comparing deep equality.
2971
+ if (keys(b, className == '[object Array]').length !== size) { return false; }
2972
+
2973
+ while (size--) {
2974
+ key = aKeys[size];
2975
+ // Deep compare each member
2976
+ result = has(b, key) && eq(a[key], b[key], aStack, bStack, customTesters);
2977
+
2978
+ if (!result) {
2979
+ return false;
2860
2980
  }
2861
2981
  }
2862
2982
  // Remove the first object from the stack of traversed objects.
@@ -2865,14 +2985,52 @@ getJasmineRequireObj().matchersUtil = function(j$) {
2865
2985
 
2866
2986
  return result;
2867
2987
 
2868
- function has(obj, key) {
2869
- return Object.prototype.hasOwnProperty.call(obj, key);
2870
- }
2988
+ function keys(obj, isArray) {
2989
+ var allKeys = Object.keys ? Object.keys(obj) :
2990
+ (function(o) {
2991
+ var keys = [];
2992
+ for (var key in o) {
2993
+ if (has(o, key)) {
2994
+ keys.push(key);
2995
+ }
2996
+ }
2997
+ return keys;
2998
+ })(obj);
2871
2999
 
2872
- function isFunction(obj) {
2873
- return typeof obj === 'function';
3000
+ if (!isArray) {
3001
+ return allKeys;
3002
+ }
3003
+
3004
+ var extraKeys = [];
3005
+ if (allKeys.length === 0) {
3006
+ return allKeys;
3007
+ }
3008
+
3009
+ for (var x = 0; x < allKeys.length; x++) {
3010
+ if (!allKeys[x].match(/^[0-9]+$/)) {
3011
+ extraKeys.push(allKeys[x]);
3012
+ }
3013
+ }
3014
+
3015
+ return extraKeys;
2874
3016
  }
2875
3017
  }
3018
+
3019
+ function has(obj, key) {
3020
+ return Object.prototype.hasOwnProperty.call(obj, key);
3021
+ }
3022
+
3023
+ function isFunction(obj) {
3024
+ return typeof obj === 'function';
3025
+ }
3026
+
3027
+ function isObjectConstructor(ctor) {
3028
+ // aCtor instanceof aCtor is true for the Object and Function
3029
+ // constructors (since a constructor is-a Function and a function is-a
3030
+ // Object). We don't just compare ctor === Object because the constructor
3031
+ // might come from a different frame with different globals.
3032
+ return isFunction(ctor) && ctor instanceof ctor;
3033
+ }
2876
3034
  };
2877
3035
 
2878
3036
  getJasmineRequireObj().toBe = function() {
@@ -2952,6 +3110,21 @@ getJasmineRequireObj().toBeGreaterThan = function() {
2952
3110
  };
2953
3111
 
2954
3112
 
3113
+ getJasmineRequireObj().toBeGreaterThanOrEqual = function() {
3114
+
3115
+ function toBeGreaterThanOrEqual() {
3116
+ return {
3117
+ compare: function(actual, expected) {
3118
+ return {
3119
+ pass: actual >= expected
3120
+ };
3121
+ }
3122
+ };
3123
+ }
3124
+
3125
+ return toBeGreaterThanOrEqual;
3126
+ };
3127
+
2955
3128
  getJasmineRequireObj().toBeLessThan = function() {
2956
3129
  function toBeLessThan() {
2957
3130
  return {
@@ -2966,6 +3139,21 @@ getJasmineRequireObj().toBeLessThan = function() {
2966
3139
 
2967
3140
  return toBeLessThan;
2968
3141
  };
3142
+ getJasmineRequireObj().toBeLessThanOrEqual = function() {
3143
+ function toBeLessThanOrEqual() {
3144
+ return {
3145
+
3146
+ compare: function(actual, expected) {
3147
+ return {
3148
+ pass: actual <= expected
3149
+ };
3150
+ }
3151
+ };
3152
+ }
3153
+
3154
+ return toBeLessThanOrEqual;
3155
+ };
3156
+
2969
3157
  getJasmineRequireObj().toBeNaN = function(j$) {
2970
3158
 
2971
3159
  function toBeNaN() {
@@ -3074,17 +3262,19 @@ getJasmineRequireObj().toEqual = function() {
3074
3262
 
3075
3263
  getJasmineRequireObj().toHaveBeenCalled = function(j$) {
3076
3264
 
3265
+ var getErrorMsg = j$.formatErrorMsg('<toHaveBeenCalled>', 'expect(<spyObj>).toHaveBeenCalled()');
3266
+
3077
3267
  function toHaveBeenCalled() {
3078
3268
  return {
3079
3269
  compare: function(actual) {
3080
3270
  var result = {};
3081
3271
 
3082
3272
  if (!j$.isSpy(actual)) {
3083
- throw new Error('Expected a spy, but got ' + j$.pp(actual) + '.');
3273
+ throw new Error(getErrorMsg('Expected a spy, but got ' + j$.pp(actual) + '.'));
3084
3274
  }
3085
3275
 
3086
3276
  if (arguments.length > 1) {
3087
- throw new Error('toHaveBeenCalled does not take arguments, use toHaveBeenCalledWith');
3277
+ throw new Error(getErrorMsg('Does not take arguments, use toHaveBeenCalledWith'));
3088
3278
  }
3089
3279
 
3090
3280
  result.pass = actual.calls.any();
@@ -3103,18 +3293,20 @@ getJasmineRequireObj().toHaveBeenCalled = function(j$) {
3103
3293
 
3104
3294
  getJasmineRequireObj().toHaveBeenCalledTimes = function(j$) {
3105
3295
 
3296
+ var getErrorMsg = j$.formatErrorMsg('<toHaveBeenCalledTimes>', 'expect(<spyObj>).toHaveBeenCalledTimes(<Number>)');
3297
+
3106
3298
  function toHaveBeenCalledTimes() {
3107
3299
  return {
3108
3300
  compare: function(actual, expected) {
3109
3301
  if (!j$.isSpy(actual)) {
3110
- throw new Error('Expected a spy, but got ' + j$.pp(actual) + '.');
3302
+ throw new Error(getErrorMsg('Expected a spy, but got ' + j$.pp(actual) + '.'));
3111
3303
  }
3112
3304
 
3113
3305
  var args = Array.prototype.slice.call(arguments, 0),
3114
3306
  result = { pass: false };
3115
3307
 
3116
- if(!expected){
3117
- throw new Error('Expected times failed is required as an argument.');
3308
+ if (!j$.isNumber_(expected)){
3309
+ throw new Error(getErrorMsg('The expected times failed is a required argument and must be a number.'));
3118
3310
  }
3119
3311
 
3120
3312
  actual = args[0];
@@ -3134,6 +3326,8 @@ getJasmineRequireObj().toHaveBeenCalledTimes = function(j$) {
3134
3326
 
3135
3327
  getJasmineRequireObj().toHaveBeenCalledWith = function(j$) {
3136
3328
 
3329
+ var getErrorMsg = j$.formatErrorMsg('<toHaveBeenCalledWith>', 'expect(<spyObj>).toHaveBeenCalledWith(...arguments)');
3330
+
3137
3331
  function toHaveBeenCalledWith(util, customEqualityTesters) {
3138
3332
  return {
3139
3333
  compare: function() {
@@ -3143,7 +3337,7 @@ getJasmineRequireObj().toHaveBeenCalledWith = function(j$) {
3143
3337
  result = { pass: false };
3144
3338
 
3145
3339
  if (!j$.isSpy(actual)) {
3146
- throw new Error('Expected a spy, but got ' + j$.pp(actual) + '.');
3340
+ throw new Error(getErrorMsg('Expected a spy, but got ' + j$.pp(actual) + '.'));
3147
3341
  }
3148
3342
 
3149
3343
  if (!actual.calls.any()) {
@@ -3168,11 +3362,13 @@ getJasmineRequireObj().toHaveBeenCalledWith = function(j$) {
3168
3362
 
3169
3363
  getJasmineRequireObj().toMatch = function(j$) {
3170
3364
 
3365
+ var getErrorMsg = j$.formatErrorMsg('<toMatch>', 'expect(<expectation>).toMatch(<string> || <regexp>)');
3366
+
3171
3367
  function toMatch() {
3172
3368
  return {
3173
3369
  compare: function(actual, expected) {
3174
3370
  if (!j$.isString_(expected) && !j$.isA_('RegExp', expected)) {
3175
- throw new Error('Expected is not a String or a RegExp');
3371
+ throw new Error(getErrorMsg('Expected is not a String or a RegExp'));
3176
3372
  }
3177
3373
 
3178
3374
  var regexp = new RegExp(expected);
@@ -3189,6 +3385,8 @@ getJasmineRequireObj().toMatch = function(j$) {
3189
3385
 
3190
3386
  getJasmineRequireObj().toThrow = function(j$) {
3191
3387
 
3388
+ var getErrorMsg = j$.formatErrorMsg('<toThrow>', 'expect(function() {<expectation>}).toThrow()');
3389
+
3192
3390
  function toThrow(util) {
3193
3391
  return {
3194
3392
  compare: function(actual, expected) {
@@ -3197,7 +3395,7 @@ getJasmineRequireObj().toThrow = function(j$) {
3197
3395
  thrown;
3198
3396
 
3199
3397
  if (typeof actual != 'function') {
3200
- throw new Error('Actual is not a Function');
3398
+ throw new Error(getErrorMsg('Actual is not a Function'));
3201
3399
  }
3202
3400
 
3203
3401
  try {
@@ -3235,6 +3433,9 @@ getJasmineRequireObj().toThrow = function(j$) {
3235
3433
  };
3236
3434
 
3237
3435
  getJasmineRequireObj().toThrowError = function(j$) {
3436
+
3437
+ var getErrorMsg = j$.formatErrorMsg('<toThrowError>', 'expect(function() {<expectation>}).toThrowError(<ErrorConstructor>, <message>)');
3438
+
3238
3439
  function toThrowError () {
3239
3440
  return {
3240
3441
  compare: function(actual) {
@@ -3244,7 +3445,7 @@ getJasmineRequireObj().toThrowError = function(j$) {
3244
3445
  thrown;
3245
3446
 
3246
3447
  if (typeof actual != 'function') {
3247
- throw new Error('Actual is not a Function');
3448
+ throw new Error(getErrorMsg('Actual is not a Function'));
3248
3449
  }
3249
3450
 
3250
3451
  var errorMatcher = getMatcher.apply(null, arguments);
@@ -3300,15 +3501,15 @@ getJasmineRequireObj().toThrowError = function(j$) {
3300
3501
  errorType = arguments[1];
3301
3502
  expected = arguments[2];
3302
3503
  if (!isAnErrorType(errorType)) {
3303
- throw new Error('Expected error type is not an Error.');
3504
+ throw new Error(getErrorMsg('Expected error type is not an Error.'));
3304
3505
  }
3305
3506
  }
3306
3507
 
3307
3508
  if (expected && !isStringOrRegExp(expected)) {
3308
3509
  if (errorType) {
3309
- throw new Error('Expected error message is not a string or RegExp.');
3510
+ throw new Error(getErrorMsg('Expected error message is not a string or RegExp.'));
3310
3511
  } else {
3311
- throw new Error('Expected is not an Error, string, or RegExp.');
3512
+ throw new Error(getErrorMsg('Expected is not an Error, string, or RegExp.'));
3312
3513
  }
3313
3514
  }
3314
3515
 
@@ -3450,5 +3651,5 @@ getJasmineRequireObj().interface = function(jasmine, env) {
3450
3651
  };
3451
3652
 
3452
3653
  getJasmineRequireObj().version = function() {
3453
- return '2.4.0';
3654
+ return '2.5.2';
3454
3655
  };
@@ -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
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "jasmine-core",
3
3
  "license": "MIT",
4
- "version": "2.4.0",
4
+ "version": "2.5.2",
5
5
  "repository": {
6
6
  "type": "git",
7
7
  "url": "https://github.com/jasmine/jasmine.git"
@@ -13,22 +13,22 @@
13
13
  "bdd"
14
14
  ],
15
15
  "scripts": {
16
- "test": "./node_modules/.bin/grunt jshint execSpecsInNode"
16
+ "test": "grunt jshint execSpecsInNode"
17
17
  },
18
18
  "description": "Official packaging of Jasmine's core files for use by Node.js projects.",
19
19
  "homepage": "http://jasmine.github.io",
20
20
  "main": "./lib/jasmine-core.js",
21
21
  "devDependencies": {
22
- "glob": "~5.0.13",
23
- "grunt": "~0.4.1",
24
- "grunt-cli": "^0.1.13",
25
- "grunt-contrib-compass": "~0.6.0",
26
- "grunt-contrib-compress": "~0.5.2",
27
- "grunt-contrib-concat": "~0.3.0",
28
- "grunt-contrib-jshint": "~0.7.0",
29
- "jasmine": "git://github.com/jasmine/jasmine-npm.git",
22
+ "glob": "~7.0.5",
23
+ "grunt": "^1.0.1",
24
+ "grunt-cli": "^1.2.0",
25
+ "grunt-contrib-compass": "^1.1.1",
26
+ "grunt-contrib-compress": "^1.3.0",
27
+ "grunt-contrib-concat": "^1.0.1",
28
+ "grunt-contrib-jshint": "^1.0.0",
29
+ "jasmine": "^2.4.0",
30
30
  "load-grunt-tasks": "^0.4.0",
31
- "shelljs": "~0.1.4",
31
+ "shelljs": "^0.7.0",
32
32
  "temp": "~0.8.1"
33
33
  }
34
34
  }