jasmine-core 2.6.4 → 2.7.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: c673112abd7b640e9bd6b9cf88f17880f8a64a0f
4
- data.tar.gz: a05601e46292ec06611cfd192eff15c0fbd03f68
3
+ metadata.gz: c5517bbc48f6454b1ca988b0597b95cbb01150b1
4
+ data.tar.gz: ba02fd49a073847ef3d322715dfbc99707090f4f
5
5
  SHA512:
6
- metadata.gz: cf3a294a022aa965aaf9f16475003f0901f8a1724b340575a6cfac372d9008cc153109c5888bec22525e8e8fdd8849effb7a843db02bd21955dcc26384ce8d6b
7
- data.tar.gz: 8b02dfb58fa1dfd5eaec2d4f4150dfc55625c9f30b4c1e0e64e736297141b7ce8da156273e9b4e941666fe3cc3f7146f3c2aedf9f21f6af111122354a67a1de6
6
+ metadata.gz: 65a948e7728d15413d2a01f59c95977bb3b989a8082490eddb82935134e67345a34c7bce3f20c5d6f1e93b8d02d4e29d48c066709c732df23ed0bf5438211261
7
+ data.tar.gz: ccdf26d3da662633660c0c925fab57aa77bde6c490f79869ed625dd8fc42c86f44156a4d1cf19fd0783382a586fbaaa1466e250efbe0a93a95b5a7e2eaff3f55
@@ -210,7 +210,7 @@ jasmineRequire.HtmlReporter = function(j$) {
210
210
 
211
211
  if (specsExecuted < totalSpecsDefined) {
212
212
  var skippedMessage = 'Ran ' + specsExecuted + ' of ' + totalSpecsDefined + ' specs - run all';
213
- var skippedLink = order && order.random ? '?random=true' : '?';
213
+ var skippedLink = addToExistingQueryString('spec', '');
214
214
  alert.appendChild(
215
215
  createDom('span', {className: 'jasmine-bar jasmine-skipped'},
216
216
  createDom('a', {href: skippedLink, title: 'Run all specs'}, skippedMessage)
@@ -71,6 +71,7 @@ var getJasmineRequireObj = (function (jasmineGlobal) {
71
71
  j$.SpyRegistry = jRequire.SpyRegistry(j$);
72
72
  j$.SpyStrategy = jRequire.SpyStrategy(j$);
73
73
  j$.StringMatching = jRequire.StringMatching(j$);
74
+ j$.UserContext = jRequire.UserContext(j$);
74
75
  j$.Suite = jRequire.Suite(j$);
75
76
  j$.Timer = jRequire.Timer();
76
77
  j$.TreeProcessor = jRequire.TreeProcessor();
@@ -138,6 +139,7 @@ getJasmineRequireObj().base = function(j$, jasmineGlobal) {
138
139
  j$.MAX_PRETTY_PRINT_DEPTH = 40;
139
140
  /**
140
141
  * Maximum number of array elements to display when pretty printing objects.
142
+ * This will also limit the number of keys and values displayed for an object.
141
143
  * Elements past this number will be ellipised.
142
144
  * @name jasmine.MAX_PRETTY_PRINT_ARRAY_LENGTH
143
145
  */
@@ -185,6 +187,10 @@ getJasmineRequireObj().base = function(j$, jasmineGlobal) {
185
187
  return j$.isA_('Function', value);
186
188
  };
187
189
 
190
+ j$.isAsyncFunction_ = function(value) {
191
+ return j$.isA_('AsyncFunction', value);
192
+ };
193
+
188
194
  j$.isA_ = function(typeName, value) {
189
195
  return j$.getType_(value) === '[object ' + typeName + ']';
190
196
  };
@@ -462,20 +468,25 @@ getJasmineRequireObj().Spec = function(j$) {
462
468
 
463
469
  this.onStart(this);
464
470
 
465
- if (!this.isExecutable() || this.markedPending || enabled === false) {
466
- complete(enabled);
467
- return;
468
- }
469
-
470
471
  var fns = this.beforeAndAfterFns();
471
- var allFns = fns.befores.concat(this.queueableFn).concat(fns.afters);
472
+ var regularFns = fns.befores.concat(this.queueableFn);
472
473
 
473
- this.queueRunnerFactory({
474
- queueableFns: allFns,
474
+ var runnerConfig = {
475
+ isLeaf: true,
476
+ queueableFns: regularFns,
477
+ cleanupFns: fns.afters,
475
478
  onException: function() { self.onException.apply(self, arguments); },
476
479
  onComplete: complete,
477
480
  userContext: this.userContext()
478
- });
481
+ };
482
+
483
+ if (!this.isExecutable() || this.markedPending || enabled === false) {
484
+ runnerConfig.queueableFns = [];
485
+ runnerConfig.cleanupFns = [];
486
+ runnerConfig.onComplete = function() { complete(enabled); };
487
+ }
488
+
489
+ this.queueRunnerFactory(runnerConfig);
479
490
 
480
491
  function complete(enabledAgain) {
481
492
  self.result.status = self.status(enabledAgain);
@@ -812,6 +823,7 @@ getJasmineRequireObj().Env = function(j$) {
812
823
  options.timeout = {setTimeout: realSetTimeout, clearTimeout: realClearTimeout};
813
824
  options.fail = self.fail;
814
825
  options.globalErrors = globalErrors;
826
+ options.completeOnFirstError = throwOnExpectationFailure && options.isLeaf;
815
827
 
816
828
  new j$.QueueRunner(options).execute();
817
829
  };
@@ -874,7 +886,8 @@ getJasmineRequireObj().Env = function(j$) {
874
886
  }
875
887
 
876
888
  reporter.jasmineStarted({
877
- totalSpecsDefined: totalSpecsDefined
889
+ totalSpecsDefined: totalSpecsDefined,
890
+ order: order
878
891
  });
879
892
 
880
893
  currentlyExecutingSuites.push(topSuite);
@@ -935,6 +948,12 @@ getJasmineRequireObj().Env = function(j$) {
935
948
  }
936
949
  };
937
950
 
951
+ var ensureIsFunctionOrAsync = function(fn, caller) {
952
+ if (!j$.isFunction_(fn) && !j$.isAsyncFunction_(fn)) {
953
+ throw new Error(caller + ' expects a function argument; received ' + j$.getType_(fn));
954
+ }
955
+ };
956
+
938
957
  var suiteFactory = function(description) {
939
958
  var suite = new j$.Suite({
940
959
  env: self,
@@ -1073,7 +1092,7 @@ getJasmineRequireObj().Env = function(j$) {
1073
1092
  // it() sometimes doesn't have a fn argument, so only check the type if
1074
1093
  // it's given.
1075
1094
  if (arguments.length > 1 && typeof fn !== 'undefined') {
1076
- ensureIsFunction(fn, 'it');
1095
+ ensureIsFunctionOrAsync(fn, 'it');
1077
1096
  }
1078
1097
  var spec = specFactory(description, fn, currentDeclarationSuite, timeout);
1079
1098
  if (currentDeclarationSuite.markedPending) {
@@ -1087,7 +1106,7 @@ getJasmineRequireObj().Env = function(j$) {
1087
1106
  // xit(), like it(), doesn't always have a fn argument, so only check the
1088
1107
  // type when needed.
1089
1108
  if (arguments.length > 1 && typeof fn !== 'undefined') {
1090
- ensureIsFunction(fn, 'xit');
1109
+ ensureIsFunctionOrAsync(fn, 'xit');
1091
1110
  }
1092
1111
  var spec = this.it.apply(this, arguments);
1093
1112
  spec.pend('Temporarily disabled with xit');
@@ -1095,7 +1114,7 @@ getJasmineRequireObj().Env = function(j$) {
1095
1114
  };
1096
1115
 
1097
1116
  this.fit = function(description, fn, timeout){
1098
- ensureIsFunction(fn, 'fit');
1117
+ ensureIsFunctionOrAsync(fn, 'fit');
1099
1118
  var spec = specFactory(description, fn, currentDeclarationSuite, timeout);
1100
1119
  currentDeclarationSuite.addChild(spec);
1101
1120
  focusedRunnables.push(spec.id);
@@ -1112,7 +1131,7 @@ getJasmineRequireObj().Env = function(j$) {
1112
1131
  };
1113
1132
 
1114
1133
  this.beforeEach = function(beforeEachFunction, timeout) {
1115
- ensureIsFunction(beforeEachFunction, 'beforeEach');
1134
+ ensureIsFunctionOrAsync(beforeEachFunction, 'beforeEach');
1116
1135
  currentDeclarationSuite.beforeEach({
1117
1136
  fn: beforeEachFunction,
1118
1137
  timeout: function() { return timeout || j$.DEFAULT_TIMEOUT_INTERVAL; }
@@ -1120,7 +1139,7 @@ getJasmineRequireObj().Env = function(j$) {
1120
1139
  };
1121
1140
 
1122
1141
  this.beforeAll = function(beforeAllFunction, timeout) {
1123
- ensureIsFunction(beforeAllFunction, 'beforeAll');
1142
+ ensureIsFunctionOrAsync(beforeAllFunction, 'beforeAll');
1124
1143
  currentDeclarationSuite.beforeAll({
1125
1144
  fn: beforeAllFunction,
1126
1145
  timeout: function() { return timeout || j$.DEFAULT_TIMEOUT_INTERVAL; }
@@ -1128,7 +1147,8 @@ getJasmineRequireObj().Env = function(j$) {
1128
1147
  };
1129
1148
 
1130
1149
  this.afterEach = function(afterEachFunction, timeout) {
1131
- ensureIsFunction(afterEachFunction, 'afterEach');
1150
+ ensureIsFunctionOrAsync(afterEachFunction, 'afterEach');
1151
+ afterEachFunction.isCleanup = true;
1132
1152
  currentDeclarationSuite.afterEach({
1133
1153
  fn: afterEachFunction,
1134
1154
  timeout: function() { return timeout || j$.DEFAULT_TIMEOUT_INTERVAL; }
@@ -1136,7 +1156,7 @@ getJasmineRequireObj().Env = function(j$) {
1136
1156
  };
1137
1157
 
1138
1158
  this.afterAll = function(afterAllFunction, timeout) {
1139
- ensureIsFunction(afterAllFunction, 'afterAll');
1159
+ ensureIsFunctionOrAsync(afterAllFunction, 'afterAll');
1140
1160
  currentDeclarationSuite.afterAll({
1141
1161
  fn: afterAllFunction,
1142
1162
  timeout: function() { return timeout || j$.DEFAULT_TIMEOUT_INTERVAL; }
@@ -1177,6 +1197,10 @@ getJasmineRequireObj().Env = function(j$) {
1177
1197
  message: message,
1178
1198
  error: error && error.message ? error : null
1179
1199
  });
1200
+
1201
+ if (self.throwingExpectationFailures()) {
1202
+ throw new Error(message);
1203
+ }
1180
1204
  };
1181
1205
  }
1182
1206
 
@@ -2523,12 +2547,12 @@ getJasmineRequireObj().matchersUtil = function(j$) {
2523
2547
  if (!result) {
2524
2548
  return false;
2525
2549
  }
2526
- } else if (className == '[object Set]') {
2550
+ } else if (className == '[object Set]' || className == '[object Map]') {
2527
2551
  if (a.size != b.size) {
2528
2552
  diffBuilder.record(a, b);
2529
2553
  return false;
2530
2554
  }
2531
- var iterA = a.values(), iterB = b.values();
2555
+ var iterA = a.entries(), iterB = b.entries();
2532
2556
  var valA, valB;
2533
2557
  do {
2534
2558
  valA = iterA.next();
@@ -2768,8 +2792,18 @@ getJasmineRequireObj().toBeCloseTo = function() {
2768
2792
  precision = precision || 2;
2769
2793
  }
2770
2794
 
2795
+ if (expected === null || actual === null) {
2796
+ throw new Error('Cannot use toBeCloseTo with null. Arguments evaluated to: ' +
2797
+ 'expect(' + actual + ').toBeCloseTo(' + expected + ').'
2798
+ );
2799
+ }
2800
+
2801
+ var pow = Math.pow(10, precision + 1);
2802
+ var delta = Math.abs(expected - actual);
2803
+ var maxDelta = Math.pow(10, -precision) / 2;
2804
+
2771
2805
  return {
2772
- pass: Math.abs(expected - actual) < (Math.pow(10, -precision) / 2)
2806
+ pass: Math.round(delta * pow) / pow <= maxDelta
2773
2807
  };
2774
2808
  }
2775
2809
  };
@@ -3650,7 +3684,7 @@ getJasmineRequireObj().pp = function(j$) {
3650
3684
  function hasCustomToString(value) {
3651
3685
  // value.toString !== Object.prototype.toString if value has no custom toString but is from another context (e.g.
3652
3686
  // iframe, web worker)
3653
- return value.toString !== Object.prototype.toString && (value.toString() !== Object.prototype.toString.call(value));
3687
+ return j$.isFunction_(value.toString) && value.toString !== Object.prototype.toString && (value.toString() !== Object.prototype.toString.call(value));
3654
3688
  }
3655
3689
 
3656
3690
  PrettyPrinter.prototype.format = function(value) {
@@ -3678,8 +3712,10 @@ getJasmineRequireObj().pp = function(j$) {
3678
3712
  this.emitScalar('HTMLNode');
3679
3713
  } else if (value instanceof Date) {
3680
3714
  this.emitScalar('Date(' + value + ')');
3681
- } else if (value.toString && value.toString() == '[object Set]') {
3715
+ } else if (j$.getType_(value) == '[object Set]') {
3682
3716
  this.emitSet(value);
3717
+ } else if (j$.getType_(value) == '[object Map]') {
3718
+ this.emitMap(value);
3683
3719
  } else if (value.toString && typeof value === 'object' && !j$.isArray_(value) && hasCustomToString(value)) {
3684
3720
  this.emitScalar(value.toString());
3685
3721
  } else if (j$.util.arrayContains(this.seen, value)) {
@@ -3701,15 +3737,28 @@ getJasmineRequireObj().pp = function(j$) {
3701
3737
  };
3702
3738
 
3703
3739
  PrettyPrinter.prototype.iterateObject = function(obj, fn) {
3704
- for (var property in obj) {
3705
- if (!Object.prototype.hasOwnProperty.call(obj, property)) { continue; }
3706
- fn(property, obj.__lookupGetter__ ? (!j$.util.isUndefined(obj.__lookupGetter__(property)) &&
3707
- obj.__lookupGetter__(property) !== null) : false);
3740
+ var objKeys = keys(obj, j$.isArray_(obj));
3741
+ var isGetter = function isGetter(prop) {};
3742
+
3743
+ if (obj.__lookupGetter__) {
3744
+ isGetter = function isGetter(prop) {
3745
+ var getter = obj.__lookupGetter__(prop);
3746
+ return !j$.util.isUndefined(getter) && getter !== null;
3747
+ };
3748
+
3708
3749
  }
3750
+ var length = Math.min(objKeys.length, j$.MAX_PRETTY_PRINT_ARRAY_LENGTH);
3751
+ for (var i = 0; i < length; i++) {
3752
+ var property = objKeys[i];
3753
+ fn(property, isGetter(property));
3754
+ }
3755
+
3756
+ return objKeys.length > length;
3709
3757
  };
3710
3758
 
3711
3759
  PrettyPrinter.prototype.emitArray = j$.unimplementedMethod_;
3712
3760
  PrettyPrinter.prototype.emitSet = j$.unimplementedMethod_;
3761
+ PrettyPrinter.prototype.emitMap = j$.unimplementedMethod_;
3713
3762
  PrettyPrinter.prototype.emitObject = j$.unimplementedMethod_;
3714
3763
  PrettyPrinter.prototype.emitScalar = j$.unimplementedMethod_;
3715
3764
  PrettyPrinter.prototype.emitString = j$.unimplementedMethod_;
@@ -3717,7 +3766,7 @@ getJasmineRequireObj().pp = function(j$) {
3717
3766
  function StringPrettyPrinter() {
3718
3767
  PrettyPrinter.call(this);
3719
3768
 
3720
- this.string = '';
3769
+ this.stringParts = [];
3721
3770
  }
3722
3771
 
3723
3772
  j$.util.inherit(StringPrettyPrinter, PrettyPrinter);
@@ -3749,11 +3798,7 @@ getJasmineRequireObj().pp = function(j$) {
3749
3798
 
3750
3799
  var self = this;
3751
3800
  var first = array.length === 0;
3752
- this.iterateObject(array, function(property, isGetter) {
3753
- if (property.match(/^\d+$/)) {
3754
- return;
3755
- }
3756
-
3801
+ var truncated = this.iterateObject(array, function(property, isGetter) {
3757
3802
  if (first) {
3758
3803
  first = false;
3759
3804
  } else {
@@ -3763,6 +3808,8 @@ getJasmineRequireObj().pp = function(j$) {
3763
3808
  self.formatProperty(array, property, isGetter);
3764
3809
  });
3765
3810
 
3811
+ if (truncated) { this.append(', ...'); }
3812
+
3766
3813
  this.append(' ]');
3767
3814
  };
3768
3815
 
@@ -3786,6 +3833,26 @@ getJasmineRequireObj().pp = function(j$) {
3786
3833
  this.append(' )');
3787
3834
  };
3788
3835
 
3836
+ StringPrettyPrinter.prototype.emitMap = function(map) {
3837
+ if (this.ppNestLevel_ > j$.MAX_PRETTY_PRINT_DEPTH) {
3838
+ this.append('Map');
3839
+ return;
3840
+ }
3841
+ this.append('Map( ');
3842
+ var size = Math.min(map.size, j$.MAX_PRETTY_PRINT_ARRAY_LENGTH);
3843
+ var iter = map.entries();
3844
+ for (var i = 0; i < size; i++) {
3845
+ if (i > 0) {
3846
+ this.append(', ');
3847
+ }
3848
+ this.format(iter.next().value);
3849
+ }
3850
+ if (map.size > size){
3851
+ this.append(', ...');
3852
+ }
3853
+ this.append(' )');
3854
+ };
3855
+
3789
3856
  StringPrettyPrinter.prototype.emitObject = function(obj) {
3790
3857
  var ctor = obj.constructor,
3791
3858
  constructorName;
@@ -3804,7 +3871,7 @@ getJasmineRequireObj().pp = function(j$) {
3804
3871
  this.append('({ ');
3805
3872
  var first = true;
3806
3873
 
3807
- this.iterateObject(obj, function(property, isGetter) {
3874
+ var truncated = this.iterateObject(obj, function(property, isGetter) {
3808
3875
  if (first) {
3809
3876
  first = false;
3810
3877
  } else {
@@ -3814,6 +3881,8 @@ getJasmineRequireObj().pp = function(j$) {
3814
3881
  self.formatProperty(obj, property, isGetter);
3815
3882
  });
3816
3883
 
3884
+ if (truncated) { this.append(', ...'); }
3885
+
3817
3886
  this.append(' })');
3818
3887
  };
3819
3888
 
@@ -3828,13 +3897,42 @@ getJasmineRequireObj().pp = function(j$) {
3828
3897
  };
3829
3898
 
3830
3899
  StringPrettyPrinter.prototype.append = function(value) {
3831
- this.string += value;
3900
+ this.stringParts.push(value);
3832
3901
  };
3833
3902
 
3903
+ function keys(obj, isArray) {
3904
+ var allKeys = Object.keys ? Object.keys(obj) :
3905
+ (function(o) {
3906
+ var keys = [];
3907
+ for (var key in o) {
3908
+ if (j$.util.has(o, key)) {
3909
+ keys.push(key);
3910
+ }
3911
+ }
3912
+ return keys;
3913
+ })(obj);
3914
+
3915
+ if (!isArray) {
3916
+ return allKeys;
3917
+ }
3918
+
3919
+ if (allKeys.length === 0) {
3920
+ return allKeys;
3921
+ }
3922
+
3923
+ var extraKeys = [];
3924
+ for (var i = 0; i < allKeys.length; i++) {
3925
+ if (!/^[0-9]+$/.test(allKeys[i])) {
3926
+ extraKeys.push(allKeys[i]);
3927
+ }
3928
+ }
3929
+
3930
+ return extraKeys;
3931
+ }
3834
3932
  return function(value) {
3835
3933
  var stringPrettyPrinter = new StringPrettyPrinter();
3836
3934
  stringPrettyPrinter.format(value);
3837
- return stringPrettyPrinter.string;
3935
+ return stringPrettyPrinter.stringParts.join('');
3838
3936
  };
3839
3937
  };
3840
3938
 
@@ -3852,15 +3950,18 @@ getJasmineRequireObj().QueueRunner = function(j$) {
3852
3950
  }
3853
3951
 
3854
3952
  function QueueRunner(attrs) {
3855
- this.queueableFns = attrs.queueableFns || [];
3953
+ var queueableFns = attrs.queueableFns || [];
3954
+ this.queueableFns = queueableFns.concat(attrs.cleanupFns || []);
3955
+ this.firstCleanupIx = queueableFns.length;
3856
3956
  this.onComplete = attrs.onComplete || function() {};
3857
3957
  this.clearStack = attrs.clearStack || function(fn) {fn();};
3858
3958
  this.onException = attrs.onException || function() {};
3859
3959
  this.catchException = attrs.catchException || function() { return true; };
3860
- this.userContext = attrs.userContext || {};
3960
+ this.userContext = attrs.userContext || new j$.UserContext();
3861
3961
  this.timeout = attrs.timeout || {setTimeout: setTimeout, clearTimeout: clearTimeout};
3862
3962
  this.fail = attrs.fail || function() {};
3863
3963
  this.globalErrors = attrs.globalErrors || { pushListener: function() {}, popListener: function() {} };
3964
+ this.completeOnFirstError = !!attrs.completeOnFirstError;
3864
3965
  }
3865
3966
 
3866
3967
  QueueRunner.prototype.execute = function() {
@@ -3869,22 +3970,33 @@ getJasmineRequireObj().QueueRunner = function(j$) {
3869
3970
  self.onException(error);
3870
3971
  };
3871
3972
  this.globalErrors.pushListener(this.handleFinalError);
3872
- this.run(this.queueableFns, 0);
3973
+ this.run(0);
3974
+ };
3975
+
3976
+ QueueRunner.prototype.skipToCleanup = function(lastRanIndex) {
3977
+ if (lastRanIndex < this.firstCleanupIx) {
3978
+ this.run(this.firstCleanupIx);
3979
+ } else {
3980
+ this.run(lastRanIndex + 1);
3981
+ }
3873
3982
  };
3874
3983
 
3875
- QueueRunner.prototype.run = function(queueableFns, recursiveIndex) {
3876
- var length = queueableFns.length,
3984
+ QueueRunner.prototype.run = function(recursiveIndex) {
3985
+ var length = this.queueableFns.length,
3877
3986
  self = this,
3878
3987
  iterativeIndex;
3879
3988
 
3880
3989
 
3881
3990
  for(iterativeIndex = recursiveIndex; iterativeIndex < length; iterativeIndex++) {
3882
- var queueableFn = queueableFns[iterativeIndex];
3883
- if (queueableFn.fn.length > 0) {
3884
- attemptAsync(queueableFn);
3991
+ var result = attempt(iterativeIndex);
3992
+
3993
+ if (!result.completedSynchronously) {
3994
+ return;
3995
+ }
3996
+
3997
+ if (this.completeOnFirstError && result.errored) {
3998
+ this.skipToCleanup(iterativeIndex);
3885
3999
  return;
3886
- } else {
3887
- attemptSync(queueableFn);
3888
4000
  }
3889
4001
  }
3890
4002
 
@@ -3893,41 +4005,46 @@ getJasmineRequireObj().QueueRunner = function(j$) {
3893
4005
  self.onComplete();
3894
4006
  });
3895
4007
 
3896
- function attemptSync(queueableFn) {
3897
- try {
3898
- queueableFn.fn.call(self.userContext);
3899
- } catch (e) {
3900
- handleException(e, queueableFn);
3901
- }
3902
- }
3903
-
3904
- function attemptAsync(queueableFn) {
4008
+ function attempt() {
3905
4009
  var clearTimeout = function () {
3906
4010
  Function.prototype.apply.apply(self.timeout.clearTimeout, [j$.getGlobal(), [timeoutId]]);
3907
4011
  },
3908
- completedSynchronously = true,
3909
4012
  setTimeout = function(delayedFn, delay) {
3910
4013
  return Function.prototype.apply.apply(self.timeout.setTimeout, [j$.getGlobal(), [delayedFn, delay]]);
3911
4014
  },
4015
+ completedSynchronously = true,
3912
4016
  handleError = function(error) {
3913
4017
  onException(error);
3914
4018
  next();
3915
4019
  },
3916
- next = once(function () {
4020
+ cleanup = once(function() {
3917
4021
  clearTimeout(timeoutId);
3918
4022
  self.globalErrors.popListener(handleError);
4023
+ }),
4024
+ next = once(function () {
4025
+ cleanup();
4026
+
4027
+ function runNext() {
4028
+ if (self.completeOnFirstError && errored) {
4029
+ self.skipToCleanup(iterativeIndex);
4030
+ } else {
4031
+ self.run(iterativeIndex + 1);
4032
+ }
4033
+ }
4034
+
3919
4035
  if (completedSynchronously) {
3920
- setTimeout(function() {
3921
- self.run(queueableFns, iterativeIndex + 1);
3922
- });
4036
+ setTimeout(runNext);
3923
4037
  } else {
3924
- self.run(queueableFns, iterativeIndex + 1);
4038
+ runNext();
3925
4039
  }
3926
4040
  }),
4041
+ errored = false,
4042
+ queueableFn = self.queueableFns[iterativeIndex],
3927
4043
  timeoutId;
3928
4044
 
3929
4045
  next.fail = function() {
3930
4046
  self.fail.apply(null, arguments);
4047
+ errored = true;
3931
4048
  next();
3932
4049
  };
3933
4050
 
@@ -3942,24 +4059,39 @@ getJasmineRequireObj().QueueRunner = function(j$) {
3942
4059
  }
3943
4060
 
3944
4061
  try {
3945
- queueableFn.fn.call(self.userContext, next);
3946
- completedSynchronously = false;
4062
+ if (queueableFn.fn.length === 0) {
4063
+ var maybeThenable = queueableFn.fn.call(self.userContext);
4064
+
4065
+ if (maybeThenable && j$.isFunction_(maybeThenable.then)) {
4066
+ maybeThenable.then(next, next.fail);
4067
+ completedSynchronously = false;
4068
+ return { completedSynchronously: false };
4069
+ }
4070
+ } else {
4071
+ queueableFn.fn.call(self.userContext, next);
4072
+ completedSynchronously = false;
4073
+ return { completedSynchronously: false };
4074
+ }
3947
4075
  } catch (e) {
3948
4076
  handleException(e, queueableFn);
3949
- next();
4077
+ errored = true;
3950
4078
  }
3951
- }
3952
4079
 
3953
- function onException(e) {
3954
- self.onException(e);
3955
- }
4080
+ cleanup();
4081
+ return { completedSynchronously: true, errored: errored };
4082
+
4083
+ function onException(e) {
4084
+ self.onException(e);
4085
+ errored = true;
4086
+ }
3956
4087
 
3957
- function handleException(e, queueableFn) {
3958
- onException(e);
3959
- if (!self.catchException(e)) {
3960
- //TODO: set a var when we catch an exception and
3961
- //use a finally block to close the loop in a nice way..
3962
- throw e;
4088
+ function handleException(e, queueableFn) {
4089
+ onException(e);
4090
+ if (!self.catchException(e)) {
4091
+ //TODO: set a var when we catch an exception and
4092
+ //use a finally block to close the loop in a nice way..
4093
+ throw e;
4094
+ }
3963
4095
  }
3964
4096
  }
3965
4097
  };
@@ -4689,14 +4821,14 @@ getJasmineRequireObj().Suite = function(j$) {
4689
4821
 
4690
4822
  Suite.prototype.sharedUserContext = function() {
4691
4823
  if (!this.sharedContext) {
4692
- this.sharedContext = this.parentSuite ? clone(this.parentSuite.sharedUserContext()) : {};
4824
+ this.sharedContext = this.parentSuite ? this.parentSuite.clonedSharedUserContext() : new j$.UserContext();
4693
4825
  }
4694
4826
 
4695
4827
  return this.sharedContext;
4696
4828
  };
4697
4829
 
4698
4830
  Suite.prototype.clonedSharedUserContext = function() {
4699
- return clone(this.sharedUserContext());
4831
+ return j$.UserContext.fromExisting(this.sharedUserContext());
4700
4832
  };
4701
4833
 
4702
4834
  Suite.prototype.onException = function() {
@@ -4748,17 +4880,6 @@ getJasmineRequireObj().Suite = function(j$) {
4748
4880
  return !args[0];
4749
4881
  }
4750
4882
 
4751
- function clone(obj) {
4752
- var clonedObj = {};
4753
- for (var prop in obj) {
4754
- if (obj.hasOwnProperty(prop)) {
4755
- clonedObj[prop] = obj[prop];
4756
- }
4757
- }
4758
-
4759
- return clonedObj;
4760
- }
4761
-
4762
4883
  return Suite;
4763
4884
  };
4764
4885
 
@@ -4996,6 +5117,25 @@ getJasmineRequireObj().TreeProcessor = function() {
4996
5117
  return TreeProcessor;
4997
5118
  };
4998
5119
 
5120
+ getJasmineRequireObj().UserContext = function(j$) {
5121
+ function UserContext() {
5122
+ }
5123
+
5124
+ UserContext.fromExisting = function(oldContext) {
5125
+ var context = new UserContext();
5126
+
5127
+ for (var prop in oldContext) {
5128
+ if (oldContext.hasOwnProperty(prop)) {
5129
+ context[prop] = oldContext[prop];
5130
+ }
5131
+ }
5132
+
5133
+ return context;
5134
+ };
5135
+
5136
+ return UserContext;
5137
+ };
5138
+
4999
5139
  getJasmineRequireObj().version = function() {
5000
- return '2.6.4';
5140
+ return '2.7.0';
5001
5141
  };