jasmine-core 3.9.0 → 3.99.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.
@@ -1,5 +1,5 @@
1
1
  /*
2
- Copyright (c) 2008-2021 Pivotal Labs
2
+ Copyright (c) 2008-2022 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
@@ -60,11 +60,15 @@ var getJasmineRequireObj = (function(jasmineGlobal) {
60
60
  j$.Any = jRequire.Any(j$);
61
61
  j$.Anything = jRequire.Anything(j$);
62
62
  j$.CallTracker = jRequire.CallTracker(j$);
63
- j$.MockDate = jRequire.MockDate();
63
+ j$.MockDate = jRequire.MockDate(j$);
64
64
  j$.getClearStack = jRequire.clearStack(j$);
65
65
  j$.Clock = jRequire.Clock();
66
66
  j$.DelayedFunctionScheduler = jRequire.DelayedFunctionScheduler(j$);
67
+ j$.Deprecator = jRequire.Deprecator(j$);
67
68
  j$.Env = jRequire.Env(j$);
69
+ j$.deprecatingThisProxy = jRequire.deprecatingThisProxy(j$);
70
+ j$.deprecatingSuiteProxy = jRequire.deprecatingSuiteProxy(j$);
71
+ j$.deprecatingSpecProxy = jRequire.deprecatingSpecProxy(j$);
68
72
  j$.StackTrace = jRequire.StackTrace(j$);
69
73
  j$.ExceptionFormatter = jRequire.ExceptionFormatter(j$);
70
74
  j$.ExpectationFilterChain = jRequire.ExpectationFilterChain();
@@ -76,11 +80,34 @@ var getJasmineRequireObj = (function(jasmineGlobal) {
76
80
  j$
77
81
  );
78
82
  j$.makePrettyPrinter = jRequire.makePrettyPrinter(j$);
79
- j$.pp = j$.makePrettyPrinter();
83
+ j$.basicPrettyPrinter_ = j$.makePrettyPrinter();
84
+ Object.defineProperty(j$, 'pp', {
85
+ get: function() {
86
+ j$.getEnv().deprecated(
87
+ 'jasmine.pp is deprecated and will be removed in a future release. ' +
88
+ 'Use the pp method of the matchersUtil passed to the matcher factory ' +
89
+ "or the asymmetric equality tester's `asymmetricMatch` method " +
90
+ 'instead. See ' +
91
+ '<https://jasmine.github.io/tutorials/upgrading_to_Jasmine_4.0#static-utils> for details.'
92
+ );
93
+ return j$.basicPrettyPrinter_;
94
+ }
95
+ });
80
96
  j$.MatchersUtil = jRequire.MatchersUtil(j$);
81
- j$.matchersUtil = new j$.MatchersUtil({
97
+ var staticMatchersUtil = new j$.MatchersUtil({
82
98
  customTesters: [],
83
- pp: j$.pp
99
+ pp: j$.basicPrettyPrinter_
100
+ });
101
+ Object.defineProperty(j$, 'matchersUtil', {
102
+ get: function() {
103
+ j$.getEnv().deprecated(
104
+ 'jasmine.matchersUtil is deprecated and will be removed ' +
105
+ 'in a future release. Use the instance passed to the matcher factory or ' +
106
+ "the asymmetric equality tester's `asymmetricMatch` method instead. " +
107
+ 'See <https://jasmine.github.io/tutorials/upgrading_to_Jasmine_4.0#static-utils> for details.'
108
+ );
109
+ return staticMatchersUtil;
110
+ }
84
111
  });
85
112
 
86
113
  j$.ObjectContaining = jRequire.ObjectContaining(j$);
@@ -96,6 +123,7 @@ var getJasmineRequireObj = (function(jasmineGlobal) {
96
123
  j$.SpyRegistry = jRequire.SpyRegistry(j$);
97
124
  j$.SpyStrategy = jRequire.SpyStrategy(j$);
98
125
  j$.StringMatching = jRequire.StringMatching(j$);
126
+ j$.StringContaining = jRequire.StringContaining(j$);
99
127
  j$.UserContext = jRequire.UserContext(j$);
100
128
  j$.Suite = jRequire.Suite(j$);
101
129
  j$.Timer = jRequire.Timer();
@@ -175,6 +203,7 @@ getJasmineRequireObj().base = function(j$, jasmineGlobal) {
175
203
  * Maximum object depth the pretty printer will print to.
176
204
  * Set this to a lower value to speed up pretty printing if you have large objects.
177
205
  * @name jasmine.MAX_PRETTY_PRINT_DEPTH
206
+ * @default 8
178
207
  * @since 1.3.0
179
208
  */
180
209
  j$.MAX_PRETTY_PRINT_DEPTH = 8;
@@ -183,6 +212,7 @@ getJasmineRequireObj().base = function(j$, jasmineGlobal) {
183
212
  * This will also limit the number of keys and values displayed for an object.
184
213
  * Elements past this number will be ellipised.
185
214
  * @name jasmine.MAX_PRETTY_PRINT_ARRAY_LENGTH
215
+ * @default 50
186
216
  * @since 2.7.0
187
217
  */
188
218
  j$.MAX_PRETTY_PRINT_ARRAY_LENGTH = 50;
@@ -190,15 +220,35 @@ getJasmineRequireObj().base = function(j$, jasmineGlobal) {
190
220
  * Maximum number of characters to display when pretty printing objects.
191
221
  * Characters past this number will be ellipised.
192
222
  * @name jasmine.MAX_PRETTY_PRINT_CHARS
223
+ * @default 100
193
224
  * @since 2.9.0
194
225
  */
195
226
  j$.MAX_PRETTY_PRINT_CHARS = 1000;
196
227
  /**
197
- * Default number of milliseconds Jasmine will wait for an asynchronous spec to complete.
228
+ * Default number of milliseconds Jasmine will wait for an asynchronous spec,
229
+ * before, or after function to complete. This can be overridden on a case by
230
+ * case basis by passing a time limit as the third argument to {@link it},
231
+ * {@link beforeEach}, {@link afterEach}, {@link beforeAll}, or
232
+ * {@link afterAll}. The value must be no greater than the largest number of
233
+ * milliseconds supported by setTimeout, which is usually 2147483647.
234
+ *
235
+ * While debugging tests, you may want to set this to a large number (or pass
236
+ * a large number to one of the functions mentioned above) so that Jasmine
237
+ * does not move on to after functions or the next spec while you're debugging.
198
238
  * @name jasmine.DEFAULT_TIMEOUT_INTERVAL
239
+ * @default 5000
199
240
  * @since 1.3.0
200
241
  */
201
- j$.DEFAULT_TIMEOUT_INTERVAL = 5000;
242
+ var DEFAULT_TIMEOUT_INTERVAL = 5000;
243
+ Object.defineProperty(j$, 'DEFAULT_TIMEOUT_INTERVAL', {
244
+ get: function() {
245
+ return DEFAULT_TIMEOUT_INTERVAL;
246
+ },
247
+ set: function(newValue) {
248
+ j$.util.validateTimeout(newValue, 'jasmine.DEFAULT_TIMEOUT_INTERVAL');
249
+ DEFAULT_TIMEOUT_INTERVAL = newValue;
250
+ }
251
+ });
202
252
 
203
253
  j$.getGlobal = function() {
204
254
  return jasmineGlobal;
@@ -397,7 +447,7 @@ getJasmineRequireObj().base = function(j$, jasmineGlobal) {
397
447
  };
398
448
 
399
449
  /**
400
- * Get a matcher, usable in any {@link matchers|matcher} that uses Jasmine's equality (e.g. {@link matchers#toEqual|toEqual}, {@link matchers#toContain|toContain}, or {@link matchers#toHaveBeenCalledWith|toHaveBeenCalledWith}),
450
+ * Get an {@link AsymmetricEqualityTester}, usable in any {@link matchers|matcher} that uses Jasmine's equality (e.g. {@link matchers#toEqual|toEqual}, {@link matchers#toContain|toContain}, or {@link matchers#toHaveBeenCalledWith|toHaveBeenCalledWith}),
401
451
  * that will succeed if the actual value being compared is an instance of the specified class/constructor.
402
452
  * @name jasmine.any
403
453
  * @since 1.3.0
@@ -409,7 +459,7 @@ getJasmineRequireObj().base = function(j$, jasmineGlobal) {
409
459
  };
410
460
 
411
461
  /**
412
- * Get a matcher, usable in any {@link matchers|matcher} that uses Jasmine's equality (e.g. {@link matchers#toEqual|toEqual}, {@link matchers#toContain|toContain}, or {@link matchers#toHaveBeenCalledWith|toHaveBeenCalledWith}),
462
+ * Get an {@link AsymmetricEqualityTester}, usable in any {@link matchers|matcher} that uses Jasmine's equality (e.g. {@link matchers#toEqual|toEqual}, {@link matchers#toContain|toContain}, or {@link matchers#toHaveBeenCalledWith|toHaveBeenCalledWith}),
413
463
  * that will succeed if the actual value being compared is not `null` and not `undefined`.
414
464
  * @name jasmine.anything
415
465
  * @since 2.2.0
@@ -420,7 +470,7 @@ getJasmineRequireObj().base = function(j$, jasmineGlobal) {
420
470
  };
421
471
 
422
472
  /**
423
- * Get a matcher, usable in any {@link matchers|matcher} that uses Jasmine's equality (e.g. {@link matchers#toEqual|toEqual}, {@link matchers#toContain|toContain}, or {@link matchers#toHaveBeenCalledWith|toHaveBeenCalledWith}),
473
+ * Get an {@link AsymmetricEqualityTester}, usable in any {@link matchers|matcher} that uses Jasmine's equality (e.g. {@link matchers#toEqual|toEqual}, {@link matchers#toContain|toContain}, or {@link matchers#toHaveBeenCalledWith|toHaveBeenCalledWith}),
424
474
  * that will succeed if the actual value being compared is `true` or anything truthy.
425
475
  * @name jasmine.truthy
426
476
  * @since 3.1.0
@@ -431,7 +481,7 @@ getJasmineRequireObj().base = function(j$, jasmineGlobal) {
431
481
  };
432
482
 
433
483
  /**
434
- * Get a matcher, usable in any {@link matchers|matcher} that uses Jasmine's equality (e.g. {@link matchers#toEqual|toEqual}, {@link matchers#toContain|toContain}, or {@link matchers#toHaveBeenCalledWith|toHaveBeenCalledWith}),
484
+ * Get an {@link AsymmetricEqualityTester}, usable in any {@link matchers|matcher} that uses Jasmine's equality (e.g. {@link matchers#toEqual|toEqual}, {@link matchers#toContain|toContain}, or {@link matchers#toHaveBeenCalledWith|toHaveBeenCalledWith}),
435
485
  * that will succeed if the actual value being compared is `null`, `undefined`, `0`, `false` or anything falsey.
436
486
  * @name jasmine.falsy
437
487
  * @since 3.1.0
@@ -442,7 +492,7 @@ getJasmineRequireObj().base = function(j$, jasmineGlobal) {
442
492
  };
443
493
 
444
494
  /**
445
- * Get a matcher, usable in any {@link matchers|matcher} that uses Jasmine's equality (e.g. {@link matchers#toEqual|toEqual}, {@link matchers#toContain|toContain}, or {@link matchers#toHaveBeenCalledWith|toHaveBeenCalledWith}),
495
+ * Get an {@link AsymmetricEqualityTester}, usable in any {@link matchers|matcher} that uses Jasmine's equality (e.g. {@link matchers#toEqual|toEqual}, {@link matchers#toContain|toContain}, or {@link matchers#toHaveBeenCalledWith|toHaveBeenCalledWith}),
446
496
  * that will succeed if the actual value being compared is empty.
447
497
  * @name jasmine.empty
448
498
  * @since 3.1.0
@@ -453,7 +503,7 @@ getJasmineRequireObj().base = function(j$, jasmineGlobal) {
453
503
  };
454
504
 
455
505
  /**
456
- * Get a matcher, usable in any {@link matchers|matcher} that uses Jasmine's equality (e.g. {@link matchers#toEqual|toEqual}, {@link matchers#toContain|toContain}, or {@link matchers#toHaveBeenCalledWith|toHaveBeenCalledWith}),
506
+ * Get an {@link AsymmetricEqualityTester}, usable in any {@link matchers|matcher} that uses Jasmine's equality (e.g. {@link matchers#toEqual|toEqual}, {@link matchers#toContain|toContain}, or {@link matchers#toHaveBeenCalledWith|toHaveBeenCalledWith}),
457
507
  * that will succeed if the actual value being compared is not empty.
458
508
  * @name jasmine.notEmpty
459
509
  * @since 3.1.0
@@ -464,7 +514,7 @@ getJasmineRequireObj().base = function(j$, jasmineGlobal) {
464
514
  };
465
515
 
466
516
  /**
467
- * Get a matcher, usable in any {@link matchers|matcher} that uses Jasmine's equality (e.g. {@link matchers#toEqual|toEqual}, {@link matchers#toContain|toContain}, or {@link matchers#toHaveBeenCalledWith|toHaveBeenCalledWith}),
517
+ * Get an {@link AsymmetricEqualityTester}, usable in any {@link matchers|matcher} that uses Jasmine's equality (e.g. {@link matchers#toEqual|toEqual}, {@link matchers#toContain|toContain}, or {@link matchers#toHaveBeenCalledWith|toHaveBeenCalledWith}),
468
518
  * that will succeed if the actual value being compared contains at least the keys and values.
469
519
  * @name jasmine.objectContaining
470
520
  * @since 1.3.0
@@ -476,7 +526,7 @@ getJasmineRequireObj().base = function(j$, jasmineGlobal) {
476
526
  };
477
527
 
478
528
  /**
479
- * Get a matcher, usable in any {@link matchers|matcher} that uses Jasmine's equality (e.g. {@link matchers#toEqual|toEqual}, {@link matchers#toContain|toContain}, or {@link matchers#toHaveBeenCalledWith|toHaveBeenCalledWith}),
529
+ * Get an {@link AsymmetricEqualityTester}, usable in any {@link matchers|matcher} that uses Jasmine's equality (e.g. {@link matchers#toEqual|toEqual}, {@link matchers#toContain|toContain}, or {@link matchers#toHaveBeenCalledWith|toHaveBeenCalledWith}),
480
530
  * that will succeed if the actual value is a `String` that matches the `RegExp` or `String`.
481
531
  * @name jasmine.stringMatching
482
532
  * @since 2.2.0
@@ -488,7 +538,19 @@ getJasmineRequireObj().base = function(j$, jasmineGlobal) {
488
538
  };
489
539
 
490
540
  /**
491
- * Get a matcher, usable in any {@link matchers|matcher} that uses Jasmine's equality (e.g. {@link matchers#toEqual|toEqual}, {@link matchers#toContain|toContain}, or {@link matchers#toHaveBeenCalledWith|toHaveBeenCalledWith}),
541
+ * Get an {@link AsymmetricEqualityTester}, usable in any {@link matchers|matcher} that uses Jasmine's equality (e.g. {@link matchers#toEqual|toEqual}, {@link matchers#toContain|toContain}, or {@link matchers#toHaveBeenCalledWith|toHaveBeenCalledWith}),
542
+ * that will succeed if the actual value is a `String` that contains the specified `String`.
543
+ * @name jasmine.stringContaining
544
+ * @since 3.10.0
545
+ * @function
546
+ * @param {String} expected
547
+ */
548
+ j$.stringContaining = function(expected) {
549
+ return new j$.StringContaining(expected);
550
+ };
551
+
552
+ /**
553
+ * Get an {@link AsymmetricEqualityTester}, usable in any {@link matchers|matcher} that uses Jasmine's equality (e.g. {@link matchers#toEqual|toEqual}, {@link matchers#toContain|toContain}, or {@link matchers#toHaveBeenCalledWith|toHaveBeenCalledWith}),
492
554
  * that will succeed if the actual value is an `Array` that contains at least the elements in the sample.
493
555
  * @name jasmine.arrayContaining
494
556
  * @since 2.2.0
@@ -500,7 +562,7 @@ getJasmineRequireObj().base = function(j$, jasmineGlobal) {
500
562
  };
501
563
 
502
564
  /**
503
- * Get a matcher, usable in any {@link matchers|matcher} that uses Jasmine's equality (e.g. {@link matchers#toEqual|toEqual}, {@link matchers#toContain|toContain}, or {@link matchers#toHaveBeenCalledWith|toHaveBeenCalledWith}),
565
+ * Get an {@link AsymmetricEqualityTester}, usable in any {@link matchers|matcher} that uses Jasmine's equality (e.g. {@link matchers#toEqual|toEqual}, {@link matchers#toContain|toContain}, or {@link matchers#toHaveBeenCalledWith|toHaveBeenCalledWith}),
504
566
  * that will succeed if the actual value is an `Array` that contains all of the elements in the sample in any order.
505
567
  * @name jasmine.arrayWithExactContents
506
568
  * @since 2.8.0
@@ -512,7 +574,7 @@ getJasmineRequireObj().base = function(j$, jasmineGlobal) {
512
574
  };
513
575
 
514
576
  /**
515
- * Get a matcher, usable in any {@link matchers|matcher} that uses Jasmine's equality (e.g. {@link matchers#toEqual|toEqual}, {@link matchers#toContain|toContain}, or {@link matchers#toHaveBeenCalledWith|toHaveBeenCalledWith}),
577
+ * Get an {@link AsymmetricEqualityTester}, usable in any {@link matchers|matcher} that uses Jasmine's equality (e.g. {@link matchers#toEqual|toEqual}, {@link matchers#toContain|toContain}, or {@link matchers#toHaveBeenCalledWith|toHaveBeenCalledWith}),
516
578
  * that will succeed if every key/value pair in the sample passes the deep equality comparison
517
579
  * with at least one key/value pair in the actual value being compared
518
580
  * @name jasmine.mapContaining
@@ -525,7 +587,7 @@ getJasmineRequireObj().base = function(j$, jasmineGlobal) {
525
587
  };
526
588
 
527
589
  /**
528
- * Get a matcher, usable in any {@link matchers|matcher} that uses Jasmine's equality (e.g. {@link matchers#toEqual|toEqual}, {@link matchers#toContain|toContain}, or {@link matchers#toHaveBeenCalledWith|toHaveBeenCalledWith}),
590
+ * Get an {@link AsymmetricEqualityTester}, usable in any {@link matchers|matcher} that uses Jasmine's equality (e.g. {@link matchers#toEqual|toEqual}, {@link matchers#toContain|toContain}, or {@link matchers#toHaveBeenCalledWith|toHaveBeenCalledWith}),
529
591
  * that will succeed if every item in the sample passes the deep equality comparison
530
592
  * with at least one item in the actual value being compared
531
593
  * @name jasmine.setContaining
@@ -700,6 +762,21 @@ getJasmineRequireObj().util = function(j$) {
700
762
  }
701
763
  };
702
764
 
765
+ util.validateTimeout = function(timeout, msgPrefix) {
766
+ // Timeouts are implemented with setTimeout, which only supports a limited
767
+ // range of values. The limit is unspecified, as is the behavior when it's
768
+ // exceeded. But on all currently supported JS runtimes, setTimeout calls
769
+ // the callback immediately when the timeout is greater than 2147483647
770
+ // (the maximum value of a signed 32 bit integer).
771
+ var max = 2147483647;
772
+
773
+ if (timeout > max) {
774
+ throw new Error(
775
+ (msgPrefix || 'Timeout value') + ' cannot be greater than ' + max
776
+ );
777
+ }
778
+ };
779
+
703
780
  return util;
704
781
  };
705
782
 
@@ -707,6 +784,7 @@ getJasmineRequireObj().Spec = function(j$) {
707
784
  /**
708
785
  * @interface Spec
709
786
  * @see Configuration#specFilter
787
+ * @since 2.0.0
710
788
  */
711
789
  function Spec(attrs) {
712
790
  this.expectationFactory = attrs.expectationFactory;
@@ -717,6 +795,7 @@ getJasmineRequireObj().Spec = function(j$) {
717
795
  * @name Spec#id
718
796
  * @readonly
719
797
  * @type {string}
798
+ * @since 2.0.0
720
799
  */
721
800
  this.id = attrs.id;
722
801
  /**
@@ -724,6 +803,7 @@ getJasmineRequireObj().Spec = function(j$) {
724
803
  * @name Spec#description
725
804
  * @readonly
726
805
  * @type {string}
806
+ * @since 2.0.0
727
807
  */
728
808
  this.description = attrs.description || '';
729
809
  this.queueableFn = attrs.queueableFn;
@@ -738,6 +818,8 @@ getJasmineRequireObj().Spec = function(j$) {
738
818
  return {};
739
819
  };
740
820
  this.onStart = attrs.onStart || function() {};
821
+ this.autoCleanClosures =
822
+ attrs.autoCleanClosures === undefined ? true : !!attrs.autoCleanClosures;
741
823
  this.getSpecName =
742
824
  attrs.getSpecName ||
743
825
  function() {
@@ -745,6 +827,7 @@ getJasmineRequireObj().Spec = function(j$) {
745
827
  };
746
828
  this.expectationResultFactory =
747
829
  attrs.expectationResultFactory || function() {};
830
+ this.deprecated = attrs.deprecated || function() {};
748
831
  this.queueRunnerFactory = attrs.queueRunnerFactory || function() {};
749
832
  this.catchingExceptions =
750
833
  attrs.catchingExceptions ||
@@ -755,7 +838,7 @@ getJasmineRequireObj().Spec = function(j$) {
755
838
  this.timer = attrs.timer || new j$.Timer();
756
839
 
757
840
  if (!this.queueableFn.fn) {
758
- this.pend();
841
+ this.exclude();
759
842
  }
760
843
 
761
844
  /**
@@ -770,7 +853,8 @@ getJasmineRequireObj().Spec = function(j$) {
770
853
  * @property {String} status - Once the spec has completed, this string represents the pass/fail status of this spec.
771
854
  * @property {number} duration - The time in ms used by the spec execution, including any before/afterEach.
772
855
  * @property {Object} properties - User-supplied properties, if any, that were set using {@link Env#setSpecProperty}
773
- */
856
+ * @since 2.0.0
857
+ x */
774
858
  this.result = {
775
859
  id: this.id,
776
860
  description: this.description,
@@ -822,7 +906,9 @@ getJasmineRequireObj().Spec = function(j$) {
822
906
 
823
907
  var complete = {
824
908
  fn: function(done) {
825
- self.queueableFn.fn = null;
909
+ if (self.autoCleanClosures) {
910
+ self.queueableFn.fn = null;
911
+ }
826
912
  self.result.status = self.status(excluded, failSpecWithNoExp);
827
913
  self.result.duration = self.timer.elapsed();
828
914
  self.resultCallback(self.result, done);
@@ -839,13 +925,32 @@ getJasmineRequireObj().Spec = function(j$) {
839
925
  onException: function() {
840
926
  self.onException.apply(self, arguments);
841
927
  },
842
- onComplete: function() {
843
- onComplete(
844
- self.result.status === 'failed' &&
845
- new j$.StopExecutionError('spec failed')
928
+ onMultipleDone: function() {
929
+ // Issue a deprecation. Include the context ourselves and pass
930
+ // ignoreRunnable: true, since getting here always means that we've already
931
+ // moved on and the current runnable isn't the one that caused the problem.
932
+ self.deprecated(
933
+ "An asynchronous function called its 'done' " +
934
+ 'callback more than once. This is a bug in the spec, beforeAll, ' +
935
+ 'beforeEach, afterAll, or afterEach function in question. This will ' +
936
+ 'be treated as an error in a future version. See' +
937
+ '<https://jasmine.github.io/tutorials/upgrading_to_Jasmine_4.0#deprecations-due-to-calling-done-multiple-times> ' +
938
+ 'for more information.\n' +
939
+ '(in spec: ' +
940
+ self.getFullName() +
941
+ ')',
942
+ { ignoreRunnable: true }
846
943
  );
847
944
  },
848
- userContext: this.userContext()
945
+ onComplete: function() {
946
+ if (self.result.status === 'failed') {
947
+ onComplete(new j$.StopExecutionError('spec failed'));
948
+ } else {
949
+ onComplete();
950
+ }
951
+ },
952
+ userContext: this.userContext(),
953
+ runnableName: this.getFullName.bind(this)
849
954
  };
850
955
 
851
956
  if (this.markedPending || excluded === true) {
@@ -859,6 +964,36 @@ getJasmineRequireObj().Spec = function(j$) {
859
964
  this.queueRunnerFactory(runnerConfig);
860
965
  };
861
966
 
967
+ Spec.prototype.reset = function() {
968
+ /**
969
+ * @typedef SpecResult
970
+ * @property {Int} id - The unique id of this spec.
971
+ * @property {String} description - The description passed to the {@link it} that created this spec.
972
+ * @property {String} fullName - The full description including all ancestors of this spec.
973
+ * @property {Expectation[]} failedExpectations - The list of expectations that failed during execution of this spec.
974
+ * @property {Expectation[]} passedExpectations - The list of expectations that passed during execution of this spec.
975
+ * @property {Expectation[]} deprecationWarnings - The list of deprecation warnings that occurred during execution this spec.
976
+ * @property {String} pendingReason - If the spec is {@link pending}, this will be the reason.
977
+ * @property {String} status - Once the spec has completed, this string represents the pass/fail status of this spec.
978
+ * @property {number} duration - The time in ms used by the spec execution, including any before/afterEach.
979
+ * @property {Object} properties - User-supplied properties, if any, that were set using {@link Env#setSpecProperty}
980
+ * @since 2.0.0
981
+ */
982
+ this.result = {
983
+ id: this.id,
984
+ description: this.description,
985
+ fullName: this.getFullName(),
986
+ failedExpectations: [],
987
+ passedExpectations: [],
988
+ deprecationWarnings: [],
989
+ pendingReason: this.excludeMessage,
990
+ duration: null,
991
+ properties: null,
992
+ trace: null
993
+ };
994
+ this.markedPending = this.markedExcluding;
995
+ };
996
+
862
997
  Spec.prototype.onException = function onException(e) {
863
998
  if (Spec.isPendingSpecException(e)) {
864
999
  this.pend(extractCustomPendingMessage(e));
@@ -882,6 +1017,10 @@ getJasmineRequireObj().Spec = function(j$) {
882
1017
  );
883
1018
  };
884
1019
 
1020
+ /*
1021
+ * Marks state as pending
1022
+ * @param {string} [message] An optional reason message
1023
+ */
885
1024
  Spec.prototype.pend = function(message) {
886
1025
  this.markedPending = true;
887
1026
  if (message) {
@@ -889,6 +1028,19 @@ getJasmineRequireObj().Spec = function(j$) {
889
1028
  }
890
1029
  };
891
1030
 
1031
+ /*
1032
+ * Like {@link Spec#pend}, but pending state will survive {@link Spec#reset}
1033
+ * Useful for fit, xit, where pending state remains.
1034
+ * @param {string} [message] An optional reason message
1035
+ */
1036
+ Spec.prototype.exclude = function(message) {
1037
+ this.markedExcluding = true;
1038
+ if (this.message) {
1039
+ this.excludeMessage = message;
1040
+ }
1041
+ this.pend(message);
1042
+ };
1043
+
892
1044
  Spec.prototype.getResult = function() {
893
1045
  this.result.status = this.status();
894
1046
  return this.result;
@@ -921,6 +1073,7 @@ getJasmineRequireObj().Spec = function(j$) {
921
1073
  * @name Spec#getFullName
922
1074
  * @function
923
1075
  * @returns {string}
1076
+ * @since 2.0.0
924
1077
  */
925
1078
  Spec.prototype.getFullName = function() {
926
1079
  return this.getSpecName(this);
@@ -1147,8 +1300,31 @@ getJasmineRequireObj().Env = function(j$) {
1147
1300
  * @since 3.5.0
1148
1301
  * @type function
1149
1302
  * @default undefined
1303
+ * @deprecated In a future version, Jasmine will ignore the Promise config
1304
+ * property and always create native promises instead.
1150
1305
  */
1151
- Promise: undefined
1306
+ Promise: undefined,
1307
+ /**
1308
+ * Clean closures when a suite is done running (done by clearing the stored function reference).
1309
+ * This prevents memory leaks, but you won't be able to run jasmine multiple times.
1310
+ * @name Configuration#autoCleanClosures
1311
+ * @since 3.10.0
1312
+ * @type boolean
1313
+ * @default true
1314
+ */
1315
+ autoCleanClosures: true,
1316
+ /**
1317
+ * Whether or not to issue warnings for certain deprecated functionality
1318
+ * every time it's used. If not set or set to false, deprecation warnings
1319
+ * for methods that tend to be called frequently will be issued only once
1320
+ * or otherwise throttled to to prevent the suite output from being flooded
1321
+ * with warnings.
1322
+ * @name Configuration#verboseDeprecations
1323
+ * @since 3.6.0
1324
+ * @type Boolean
1325
+ * @default false
1326
+ */
1327
+ verboseDeprecations: false
1152
1328
  };
1153
1329
 
1154
1330
  var currentSuite = function() {
@@ -1201,7 +1377,8 @@ getJasmineRequireObj().Env = function(j$) {
1201
1377
  var booleanProps = [
1202
1378
  'random',
1203
1379
  'failSpecWithNoExpectations',
1204
- 'hideDisabled'
1380
+ 'hideDisabled',
1381
+ 'autoCleanClosures'
1205
1382
  ];
1206
1383
 
1207
1384
  booleanProps.forEach(function(prop) {
@@ -1211,6 +1388,18 @@ getJasmineRequireObj().Env = function(j$) {
1211
1388
  });
1212
1389
 
1213
1390
  if (typeof configuration.failFast !== 'undefined') {
1391
+ // We can't unconditionally issue a warning here because then users who
1392
+ // get the configuration from Jasmine, modify it, and pass it back would
1393
+ // see the warning.
1394
+ if (configuration.failFast !== config.failFast) {
1395
+ this.deprecated(
1396
+ 'The `failFast` config property is deprecated and will be removed ' +
1397
+ 'in a future version of Jasmine. Please use `stopOnSpecFailure` ' +
1398
+ 'instead.',
1399
+ { ignoreRunnable: true }
1400
+ );
1401
+ }
1402
+
1214
1403
  if (typeof configuration.stopOnSpecFailure !== 'undefined') {
1215
1404
  if (configuration.stopOnSpecFailure !== configuration.failFast) {
1216
1405
  throw new Error(
@@ -1228,6 +1417,18 @@ getJasmineRequireObj().Env = function(j$) {
1228
1417
  }
1229
1418
 
1230
1419
  if (typeof configuration.oneFailurePerSpec !== 'undefined') {
1420
+ // We can't unconditionally issue a warning here because then users who
1421
+ // get the configuration from Jasmine, modify it, and pass it back would
1422
+ // see the warning.
1423
+ if (configuration.oneFailurePerSpec !== config.oneFailurePerSpec) {
1424
+ this.deprecated(
1425
+ 'The `oneFailurePerSpec` config property is deprecated and will be ' +
1426
+ 'removed in a future version of Jasmine. Please use ' +
1427
+ '`stopSpecOnExpectationFailure` instead.',
1428
+ { ignoreRunnable: true }
1429
+ );
1430
+ }
1431
+
1231
1432
  if (typeof configuration.stopSpecOnExpectationFailure !== 'undefined') {
1232
1433
  if (
1233
1434
  configuration.stopSpecOnExpectationFailure !==
@@ -1267,12 +1468,22 @@ getJasmineRequireObj().Env = function(j$) {
1267
1468
  typeof configuration.Promise.reject === 'function'
1268
1469
  ) {
1269
1470
  customPromise = configuration.Promise;
1471
+ self.deprecated(
1472
+ 'The `Promise` config property is deprecated. Future versions ' +
1473
+ 'of Jasmine will create native promises even if the `Promise` ' +
1474
+ 'config property is set. Please remove it.'
1475
+ );
1270
1476
  } else {
1271
1477
  throw new Error(
1272
1478
  'Custom promise library missing `resolve`/`reject` functions'
1273
1479
  );
1274
1480
  }
1275
1481
  }
1482
+
1483
+ if (configuration.hasOwnProperty('verboseDeprecations')) {
1484
+ config.verboseDeprecations = configuration.verboseDeprecations;
1485
+ deprecator.verboseDeprecations(config.verboseDeprecations);
1486
+ }
1276
1487
  };
1277
1488
 
1278
1489
  /**
@@ -1293,13 +1504,19 @@ getJasmineRequireObj().Env = function(j$) {
1293
1504
  Object.defineProperty(this, 'specFilter', {
1294
1505
  get: function() {
1295
1506
  self.deprecated(
1296
- 'Getting specFilter directly from Env is deprecated and will be removed in a future version of Jasmine, please check the specFilter option from `configuration`'
1507
+ 'Getting specFilter directly from Env is deprecated and will be ' +
1508
+ 'removed in a future version of Jasmine. Please check the ' +
1509
+ 'specFilter option from `configuration` instead.',
1510
+ { ignoreRunnable: true }
1297
1511
  );
1298
1512
  return config.specFilter;
1299
1513
  },
1300
1514
  set: function(val) {
1301
1515
  self.deprecated(
1302
- 'Setting specFilter directly on Env is deprecated and will be removed in a future version of Jasmine, please use the specFilter option in `configure`'
1516
+ 'Setting specFilter directly on Env is deprecated and will be ' +
1517
+ 'removed in a future version of Jasmine. Please use the ' +
1518
+ 'specFilter option in `configure` instead.',
1519
+ { ignoreRunnable: true }
1303
1520
  );
1304
1521
  config.specFilter = val;
1305
1522
  }
@@ -1346,6 +1563,17 @@ getJasmineRequireObj().Env = function(j$) {
1346
1563
  runnableResources[currentRunnable().id].customMatchers;
1347
1564
 
1348
1565
  for (var matcherName in matchersToAdd) {
1566
+ if (matchersToAdd[matcherName].length > 1) {
1567
+ self.deprecated(
1568
+ 'The matcher factory for "' +
1569
+ matcherName +
1570
+ '" ' +
1571
+ 'accepts custom equality testers, but this parameter will no longer be ' +
1572
+ 'passed in a future release. ' +
1573
+ 'See <https://jasmine.github.io/tutorials/upgrading_to_Jasmine_4.0#matchers-cet> for details.'
1574
+ );
1575
+ }
1576
+
1349
1577
  customMatchers[matcherName] = matchersToAdd[matcherName];
1350
1578
  }
1351
1579
  };
@@ -1360,6 +1588,17 @@ getJasmineRequireObj().Env = function(j$) {
1360
1588
  runnableResources[currentRunnable().id].customAsyncMatchers;
1361
1589
 
1362
1590
  for (var matcherName in matchersToAdd) {
1591
+ if (matchersToAdd[matcherName].length > 1) {
1592
+ self.deprecated(
1593
+ 'The matcher factory for "' +
1594
+ matcherName +
1595
+ '" ' +
1596
+ 'accepts custom equality testers, but this parameter will no longer be ' +
1597
+ 'passed in a future release. ' +
1598
+ 'See <https://jasmine.github.io/tutorials/upgrading_to_Jasmine_4.0#matchers-cet> for details.'
1599
+ );
1600
+ }
1601
+
1363
1602
  customAsyncMatchers[matcherName] = matchersToAdd[matcherName];
1364
1603
  }
1365
1604
  };
@@ -1442,7 +1681,9 @@ getJasmineRequireObj().Env = function(j$) {
1442
1681
  }
1443
1682
 
1444
1683
  delayedExpectationResult.message +=
1445
- 'Did you forget to return or await the result of expectAsync?';
1684
+ '1. Did you forget to return or await the result of expectAsync?\n' +
1685
+ '2. Was done() invoked before an async operation completed?\n' +
1686
+ '3. Did an expectation follow a call to done()?';
1446
1687
 
1447
1688
  topSuite.result.failedExpectations.push(delayedExpectationResult);
1448
1689
  }
@@ -1507,10 +1748,11 @@ getJasmineRequireObj().Env = function(j$) {
1507
1748
  delete runnableResources[id];
1508
1749
  };
1509
1750
 
1510
- var beforeAndAfterFns = function(suite) {
1751
+ var beforeAndAfterFns = function(targetSuite) {
1511
1752
  return function() {
1512
1753
  var befores = [],
1513
- afters = [];
1754
+ afters = [],
1755
+ suite = targetSuite;
1514
1756
 
1515
1757
  while (suite) {
1516
1758
  befores = befores.concat(suite.beforeFns);
@@ -1559,7 +1801,8 @@ getJasmineRequireObj().Env = function(j$) {
1559
1801
  this.deprecated(
1560
1802
  'Setting throwOnExpectationFailure directly on Env is deprecated and ' +
1561
1803
  'will be removed in a future version of Jasmine. Please use the ' +
1562
- 'stopSpecOnExpectationFailure option in `configure`.'
1804
+ 'stopSpecOnExpectationFailure option in `configure`.',
1805
+ { ignoreRunnable: true }
1563
1806
  );
1564
1807
  this.configure({ oneFailurePerSpec: !!value });
1565
1808
  };
@@ -1568,7 +1811,8 @@ getJasmineRequireObj().Env = function(j$) {
1568
1811
  this.deprecated(
1569
1812
  'Getting throwingExpectationFailures directly from Env is deprecated ' +
1570
1813
  'and will be removed in a future version of Jasmine. Please check ' +
1571
- 'the stopSpecOnExpectationFailure option from `configuration`.'
1814
+ 'the stopSpecOnExpectationFailure option from `configuration`.',
1815
+ { ignoreRunnable: true }
1572
1816
  );
1573
1817
  return config.oneFailurePerSpec;
1574
1818
  };
@@ -1585,7 +1829,8 @@ getJasmineRequireObj().Env = function(j$) {
1585
1829
  this.deprecated(
1586
1830
  'Setting stopOnSpecFailure directly is deprecated and will be ' +
1587
1831
  'removed in a future version of Jasmine. Please use the ' +
1588
- 'stopOnSpecFailure option in `configure`.'
1832
+ 'stopOnSpecFailure option in `configure`.',
1833
+ { ignoreRunnable: true }
1589
1834
  );
1590
1835
  this.configure({ stopOnSpecFailure: !!value });
1591
1836
  };
@@ -1594,7 +1839,8 @@ getJasmineRequireObj().Env = function(j$) {
1594
1839
  this.deprecated(
1595
1840
  'Getting stoppingOnSpecFailure directly from Env is deprecated and ' +
1596
1841
  'will be removed in a future version of Jasmine. Please check the ' +
1597
- 'stopOnSpecFailure option from `configuration`.'
1842
+ 'stopOnSpecFailure option from `configuration`.',
1843
+ { ignoreRunnable: true }
1598
1844
  );
1599
1845
  return config.failFast;
1600
1846
  };
@@ -1609,14 +1855,20 @@ getJasmineRequireObj().Env = function(j$) {
1609
1855
  */
1610
1856
  this.randomizeTests = function(value) {
1611
1857
  this.deprecated(
1612
- 'Setting randomizeTests directly is deprecated and will be removed in a future version of Jasmine, please use the random option in `configure`'
1858
+ 'Setting randomizeTests directly is deprecated and will be removed ' +
1859
+ 'in a future version of Jasmine. Please use the random option in ' +
1860
+ '`configure` instead.',
1861
+ { ignoreRunnable: true }
1613
1862
  );
1614
1863
  config.random = !!value;
1615
1864
  };
1616
1865
 
1617
1866
  this.randomTests = function() {
1618
1867
  this.deprecated(
1619
- 'Getting randomTests directly from Env is deprecated and will be removed in a future version of Jasmine, please check the random option from `configuration`'
1868
+ 'Getting randomTests directly from Env is deprecated and will be ' +
1869
+ 'removed in a future version of Jasmine. Please check the random ' +
1870
+ 'option from `configuration` instead.',
1871
+ { ignoreRunnable: true }
1620
1872
  );
1621
1873
  return config.random;
1622
1874
  };
@@ -1631,7 +1883,10 @@ getJasmineRequireObj().Env = function(j$) {
1631
1883
  */
1632
1884
  this.seed = function(value) {
1633
1885
  this.deprecated(
1634
- 'Setting seed directly is deprecated and will be removed in a future version of Jasmine, please use the seed option in `configure`'
1886
+ 'Setting seed directly is deprecated and will be removed in a ' +
1887
+ 'future version of Jasmine. Please use the seed option in ' +
1888
+ '`configure` instead.',
1889
+ { ignoreRunnable: true }
1635
1890
  );
1636
1891
  if (value) {
1637
1892
  config.seed = value;
@@ -1641,7 +1896,10 @@ getJasmineRequireObj().Env = function(j$) {
1641
1896
 
1642
1897
  this.hidingDisabled = function(value) {
1643
1898
  this.deprecated(
1644
- 'Getting hidingDisabled directly from Env is deprecated and will be removed in a future version of Jasmine, please check the hideDisabled option from `configuration`'
1899
+ 'Getting hidingDisabled directly from Env is deprecated and will ' +
1900
+ 'be removed in a future version of Jasmine. Please check the ' +
1901
+ 'hideDisabled option from `configuration` instead.',
1902
+ { ignoreRunnable: true }
1645
1903
  );
1646
1904
  return config.hideDisabled;
1647
1905
  };
@@ -1654,30 +1912,39 @@ getJasmineRequireObj().Env = function(j$) {
1654
1912
  */
1655
1913
  this.hideDisabled = function(value) {
1656
1914
  this.deprecated(
1657
- 'Setting hideDisabled directly is deprecated and will be removed in a future version of Jasmine, please use the hideDisabled option in `configure`'
1915
+ 'Setting hideDisabled directly is deprecated and will be removed ' +
1916
+ 'in a future version of Jasmine. Please use the hideDisabled option ' +
1917
+ 'in `configure` instead.',
1918
+ { ignoreRunnable: true }
1658
1919
  );
1659
1920
  config.hideDisabled = !!value;
1660
1921
  };
1661
1922
 
1662
- this.deprecated = function(deprecation) {
1923
+ /**
1924
+ * Causes a deprecation warning to be logged to the console and reported to
1925
+ * reporters.
1926
+ *
1927
+ * The optional second parameter is an object that can have either of the
1928
+ * following properties:
1929
+ *
1930
+ * omitStackTrace: Whether to omit the stack trace. Optional. Defaults to
1931
+ * false. This option is ignored if the deprecation is an Error. Set this
1932
+ * when the stack trace will not contain anything that helps the user find
1933
+ * the source of the deprecation.
1934
+ *
1935
+ * ignoreRunnable: Whether to log the deprecation on the root suite, ignoring
1936
+ * the spec or suite that's running when it happens. Optional. Defaults to
1937
+ * false.
1938
+ *
1939
+ * @name Env#deprecated
1940
+ * @since 2.99
1941
+ * @function
1942
+ * @param {String|Error} deprecation The deprecation message
1943
+ * @param {Object} [options] Optional extra options, as described above
1944
+ */
1945
+ this.deprecated = function(deprecation, options) {
1663
1946
  var runnable = currentRunnable() || topSuite;
1664
- var context;
1665
-
1666
- if (runnable === topSuite) {
1667
- context = '';
1668
- } else if (runnable === currentSuite()) {
1669
- context = ' (in suite: ' + runnable.getFullName() + ')';
1670
- } else {
1671
- context = ' (in spec: ' + runnable.getFullName() + ')';
1672
- }
1673
-
1674
- runnable.addDeprecationWarning(deprecation);
1675
- if (
1676
- typeof console !== 'undefined' &&
1677
- typeof console.error === 'function'
1678
- ) {
1679
- console.error('DEPRECATION: ' + deprecation + context);
1680
- }
1947
+ deprecator.addDeprecationWarning(runnable, deprecation, options);
1681
1948
  };
1682
1949
 
1683
1950
  var queueRunnerFactory = function(options, args) {
@@ -1711,9 +1978,10 @@ getJasmineRequireObj().Env = function(j$) {
1711
1978
  description: 'Jasmine__TopLevel__Suite',
1712
1979
  expectationFactory: expectationFactory,
1713
1980
  asyncExpectationFactory: suiteAsyncExpectationFactory,
1714
- expectationResultFactory: expectationResultFactory
1981
+ expectationResultFactory: expectationResultFactory,
1982
+ autoCleanClosures: config.autoCleanClosures
1715
1983
  });
1716
- defaultResourcesForRunnable(topSuite.id);
1984
+ var deprecator = new j$.Deprecator(topSuite);
1717
1985
  currentDeclarationSuite = topSuite;
1718
1986
 
1719
1987
  /**
@@ -1722,9 +1990,10 @@ getJasmineRequireObj().Env = function(j$) {
1722
1990
  * @function
1723
1991
  * @name Env#topSuite
1724
1992
  * @return {Suite} the root suite
1993
+ * @since 2.0.0
1725
1994
  */
1726
1995
  this.topSuite = function() {
1727
- return topSuite;
1996
+ return j$.deprecatingSuiteProxy(topSuite, null, this);
1728
1997
  };
1729
1998
 
1730
1999
  /**
@@ -1799,7 +2068,8 @@ getJasmineRequireObj().Env = function(j$) {
1799
2068
  */
1800
2069
  'specDone'
1801
2070
  ],
1802
- queueRunnerFactory
2071
+ queueRunnerFactory,
2072
+ self.deprecated
1803
2073
  );
1804
2074
 
1805
2075
  /**
@@ -1830,6 +2100,11 @@ getJasmineRequireObj().Env = function(j$) {
1830
2100
  * @return {Promise<undefined>}
1831
2101
  */
1832
2102
  this.execute = function(runnablesToRun, onComplete) {
2103
+ if (this._executedBefore) {
2104
+ topSuite.reset();
2105
+ }
2106
+ this._executedBefore = true;
2107
+ defaultResourcesForRunnable(topSuite.id);
1833
2108
  installGlobalErrors();
1834
2109
 
1835
2110
  if (!runnablesToRun) {
@@ -1913,6 +2188,7 @@ getJasmineRequireObj().Env = function(j$) {
1913
2188
  * @typedef JasmineStartedInfo
1914
2189
  * @property {Int} totalSpecsDefined - The total number of specs defined in this suite.
1915
2190
  * @property {Order} order - Information about the ordering (random or not) of this execution of the suite.
2191
+ * @since 2.0.0
1916
2192
  */
1917
2193
  reporter.jasmineStarted(
1918
2194
  {
@@ -1951,6 +2227,7 @@ getJasmineRequireObj().Env = function(j$) {
1951
2227
  * @property {Order} order - Information about the ordering (random or not) of this execution of the suite.
1952
2228
  * @property {Expectation[]} failedExpectations - List of expectations that failed in an {@link afterAll} at the global level.
1953
2229
  * @property {Expectation[]} deprecationWarnings - List of deprecation warnings that occurred at the global level.
2230
+ * @since 2.4.0
1954
2231
  */
1955
2232
  reporter.jasmineDone(
1956
2233
  {
@@ -2114,7 +2391,8 @@ getJasmineRequireObj().Env = function(j$) {
2114
2391
  expectationFactory: expectationFactory,
2115
2392
  asyncExpectationFactory: suiteAsyncExpectationFactory,
2116
2393
  expectationResultFactory: expectationResultFactory,
2117
- throwOnExpectationFailure: config.oneFailurePerSpec
2394
+ throwOnExpectationFailure: config.oneFailurePerSpec,
2395
+ autoCleanClosures: config.autoCleanClosures
2118
2396
  });
2119
2397
 
2120
2398
  return suite;
@@ -2127,20 +2405,27 @@ getJasmineRequireObj().Env = function(j$) {
2127
2405
  if (specDefinitions.length > 0) {
2128
2406
  throw new Error('describe does not expect any arguments');
2129
2407
  }
2130
- if (currentDeclarationSuite.markedPending) {
2131
- suite.pend();
2408
+ if (currentDeclarationSuite.markedExcluding) {
2409
+ suite.exclude();
2132
2410
  }
2133
2411
  addSpecsToSuite(suite, specDefinitions);
2134
- return suite;
2412
+ if (suite.parentSuite && !suite.children.length) {
2413
+ this.deprecated(
2414
+ 'describe with no children (describe() or it()) is ' +
2415
+ 'deprecated and will be removed in a future version of Jasmine. ' +
2416
+ 'Please either remove the describe or add children to it.'
2417
+ );
2418
+ }
2419
+ return j$.deprecatingSuiteProxy(suite, suite.parentSuite, this);
2135
2420
  };
2136
2421
 
2137
2422
  this.xdescribe = function(description, specDefinitions) {
2138
2423
  ensureIsNotNested('xdescribe');
2139
2424
  ensureIsFunction(specDefinitions, 'xdescribe');
2140
2425
  var suite = suiteFactory(description);
2141
- suite.pend();
2426
+ suite.exclude();
2142
2427
  addSpecsToSuite(suite, specDefinitions);
2143
- return suite;
2428
+ return j$.deprecatingSuiteProxy(suite, suite.parentSuite, this);
2144
2429
  };
2145
2430
 
2146
2431
  var focusedRunnables = [];
@@ -2155,7 +2440,7 @@ getJasmineRequireObj().Env = function(j$) {
2155
2440
  unfocusAncestor();
2156
2441
  addSpecsToSuite(suite, specDefinitions);
2157
2442
 
2158
- return suite;
2443
+ return j$.deprecatingSuiteProxy(suite, suite.parentSuite, this);
2159
2444
  };
2160
2445
 
2161
2446
  function addSpecsToSuite(suite, specDefinitions) {
@@ -2165,7 +2450,7 @@ getJasmineRequireObj().Env = function(j$) {
2165
2450
 
2166
2451
  var declarationError = null;
2167
2452
  try {
2168
- specDefinitions.call(suite);
2453
+ specDefinitions.call(j$.deprecatingThisProxy(suite, self));
2169
2454
  } catch (e) {
2170
2455
  declarationError = e;
2171
2456
  }
@@ -2207,6 +2492,7 @@ getJasmineRequireObj().Env = function(j$) {
2207
2492
  beforeAndAfterFns: beforeAndAfterFns(suite),
2208
2493
  expectationFactory: expectationFactory,
2209
2494
  asyncExpectationFactory: specAsyncExpectationFactory,
2495
+ deprecated: self.deprecated,
2210
2496
  resultCallback: specResultCallback,
2211
2497
  getSpecName: function(spec) {
2212
2498
  return getSpecName(spec, suite);
@@ -2223,6 +2509,7 @@ getJasmineRequireObj().Env = function(j$) {
2223
2509
  timeout: timeout || 0
2224
2510
  },
2225
2511
  throwOnExpectationFailure: config.oneFailurePerSpec,
2512
+ autoCleanClosures: config.autoCleanClosures,
2226
2513
  timer: new j$.Timer()
2227
2514
  });
2228
2515
  return spec;
@@ -2245,21 +2532,32 @@ getJasmineRequireObj().Env = function(j$) {
2245
2532
  }
2246
2533
  };
2247
2534
 
2248
- this.it = function(description, fn, timeout) {
2535
+ this.it_ = function(description, fn, timeout) {
2249
2536
  ensureIsNotNested('it');
2250
2537
  // it() sometimes doesn't have a fn argument, so only check the type if
2251
2538
  // it's given.
2252
2539
  if (arguments.length > 1 && typeof fn !== 'undefined') {
2253
2540
  ensureIsFunctionOrAsync(fn, 'it');
2254
2541
  }
2542
+
2543
+ if (timeout) {
2544
+ j$.util.validateTimeout(timeout);
2545
+ }
2546
+
2255
2547
  var spec = specFactory(description, fn, currentDeclarationSuite, timeout);
2256
- if (currentDeclarationSuite.markedPending) {
2257
- spec.pend();
2548
+ if (currentDeclarationSuite.markedExcluding) {
2549
+ spec.exclude();
2258
2550
  }
2259
2551
  currentDeclarationSuite.addChild(spec);
2552
+
2260
2553
  return spec;
2261
2554
  };
2262
2555
 
2556
+ this.it = function(description, fn, timeout) {
2557
+ var spec = this.it_(description, fn, timeout);
2558
+ return j$.deprecatingSpecProxy(spec, this);
2559
+ };
2560
+
2263
2561
  this.xit = function(description, fn, timeout) {
2264
2562
  ensureIsNotNested('xit');
2265
2563
  // xit(), like it(), doesn't always have a fn argument, so only check the
@@ -2267,19 +2565,23 @@ getJasmineRequireObj().Env = function(j$) {
2267
2565
  if (arguments.length > 1 && typeof fn !== 'undefined') {
2268
2566
  ensureIsFunctionOrAsync(fn, 'xit');
2269
2567
  }
2270
- var spec = this.it.apply(this, arguments);
2271
- spec.pend('Temporarily disabled with xit');
2272
- return spec;
2568
+ var spec = this.it_.apply(this, arguments);
2569
+ spec.exclude('Temporarily disabled with xit');
2570
+ return j$.deprecatingSpecProxy(spec, this);
2273
2571
  };
2274
2572
 
2275
2573
  this.fit = function(description, fn, timeout) {
2276
2574
  ensureIsNotNested('fit');
2277
2575
  ensureIsFunctionOrAsync(fn, 'fit');
2576
+
2577
+ if (timeout) {
2578
+ j$.util.validateTimeout(timeout);
2579
+ }
2278
2580
  var spec = specFactory(description, fn, currentDeclarationSuite, timeout);
2279
2581
  currentDeclarationSuite.addChild(spec);
2280
2582
  focusedRunnables.push(spec.id);
2281
2583
  unfocusAncestor();
2282
- return spec;
2584
+ return j$.deprecatingSpecProxy(spec, this);
2283
2585
  };
2284
2586
 
2285
2587
  /**
@@ -2339,6 +2641,11 @@ getJasmineRequireObj().Env = function(j$) {
2339
2641
  this.beforeEach = function(beforeEachFunction, timeout) {
2340
2642
  ensureIsNotNested('beforeEach');
2341
2643
  ensureIsFunctionOrAsync(beforeEachFunction, 'beforeEach');
2644
+
2645
+ if (timeout) {
2646
+ j$.util.validateTimeout(timeout);
2647
+ }
2648
+
2342
2649
  currentDeclarationSuite.beforeEach({
2343
2650
  fn: beforeEachFunction,
2344
2651
  timeout: timeout || 0
@@ -2348,6 +2655,11 @@ getJasmineRequireObj().Env = function(j$) {
2348
2655
  this.beforeAll = function(beforeAllFunction, timeout) {
2349
2656
  ensureIsNotNested('beforeAll');
2350
2657
  ensureIsFunctionOrAsync(beforeAllFunction, 'beforeAll');
2658
+
2659
+ if (timeout) {
2660
+ j$.util.validateTimeout(timeout);
2661
+ }
2662
+
2351
2663
  currentDeclarationSuite.beforeAll({
2352
2664
  fn: beforeAllFunction,
2353
2665
  timeout: timeout || 0
@@ -2357,6 +2669,11 @@ getJasmineRequireObj().Env = function(j$) {
2357
2669
  this.afterEach = function(afterEachFunction, timeout) {
2358
2670
  ensureIsNotNested('afterEach');
2359
2671
  ensureIsFunctionOrAsync(afterEachFunction, 'afterEach');
2672
+
2673
+ if (timeout) {
2674
+ j$.util.validateTimeout(timeout);
2675
+ }
2676
+
2360
2677
  afterEachFunction.isCleanup = true;
2361
2678
  currentDeclarationSuite.afterEach({
2362
2679
  fn: afterEachFunction,
@@ -2367,6 +2684,11 @@ getJasmineRequireObj().Env = function(j$) {
2367
2684
  this.afterAll = function(afterAllFunction, timeout) {
2368
2685
  ensureIsNotNested('afterAll');
2369
2686
  ensureIsFunctionOrAsync(afterAllFunction, 'afterAll');
2687
+
2688
+ if (timeout) {
2689
+ j$.util.validateTimeout(timeout);
2690
+ }
2691
+
2370
2692
  currentDeclarationSuite.afterAll({
2371
2693
  fn: afterAllFunction,
2372
2694
  timeout: timeout || 0
@@ -2627,7 +2949,7 @@ getJasmineRequireObj().ArrayContaining = function(j$) {
2627
2949
  if (!j$.isArray_(this.sample)) {
2628
2950
  throw new Error(
2629
2951
  'You must provide an array to arrayContaining, not ' +
2630
- j$.pp(this.sample) +
2952
+ j$.basicPrettyPrinter_(this.sample) +
2631
2953
  '.'
2632
2954
  );
2633
2955
  }
@@ -2668,7 +2990,7 @@ getJasmineRequireObj().ArrayWithExactContents = function(j$) {
2668
2990
  if (!j$.isArray_(this.sample)) {
2669
2991
  throw new Error(
2670
2992
  'You must provide an array to arrayWithExactContents, not ' +
2671
- j$.pp(this.sample) +
2993
+ j$.basicPrettyPrinter_(this.sample) +
2672
2994
  '.'
2673
2995
  );
2674
2996
  }
@@ -2737,7 +3059,8 @@ getJasmineRequireObj().MapContaining = function(j$) {
2737
3059
  function MapContaining(sample) {
2738
3060
  if (!j$.isMap(sample)) {
2739
3061
  throw new Error(
2740
- 'You must provide a map to `mapContaining`, not ' + j$.pp(sample)
3062
+ 'You must provide a map to `mapContaining`, not ' +
3063
+ j$.basicPrettyPrinter_(sample)
2741
3064
  );
2742
3065
  }
2743
3066
 
@@ -2888,7 +3211,8 @@ getJasmineRequireObj().SetContaining = function(j$) {
2888
3211
  function SetContaining(sample) {
2889
3212
  if (!j$.isSet(sample)) {
2890
3213
  throw new Error(
2891
- 'You must provide a set to `setContaining`, not ' + j$.pp(sample)
3214
+ 'You must provide a set to `setContaining`, not ' +
3215
+ j$.basicPrettyPrinter_(sample)
2892
3216
  );
2893
3217
  }
2894
3218
 
@@ -2926,6 +3250,31 @@ getJasmineRequireObj().SetContaining = function(j$) {
2926
3250
  return SetContaining;
2927
3251
  };
2928
3252
 
3253
+ getJasmineRequireObj().StringContaining = function(j$) {
3254
+ function StringContaining(expected) {
3255
+ if (!j$.isString_(expected)) {
3256
+ throw new Error('Expected is not a String');
3257
+ }
3258
+
3259
+ this.expected = expected;
3260
+ }
3261
+
3262
+ StringContaining.prototype.asymmetricMatch = function(other) {
3263
+ if (!j$.isString_(other)) {
3264
+ // Arrays, etc. don't match no matter what their indexOf returns.
3265
+ return false;
3266
+ }
3267
+
3268
+ return other.indexOf(this.expected) !== -1;
3269
+ };
3270
+
3271
+ StringContaining.prototype.jasmineToString = function() {
3272
+ return '<jasmine.stringContaining("' + this.expected + '")>';
3273
+ };
3274
+
3275
+ return StringContaining;
3276
+ };
3277
+
2929
3278
  getJasmineRequireObj().StringMatching = function(j$) {
2930
3279
  function StringMatching(expected) {
2931
3280
  if (!j$.isString_(expected) && !j$.isA_('RegExp', expected)) {
@@ -3013,34 +3362,49 @@ getJasmineRequireObj().asymmetricEqualityTesterArgCompatShim = function(j$) {
3013
3362
  matchersUtil,
3014
3363
  customEqualityTesters
3015
3364
  ) {
3016
- var self = Object.create(matchersUtil),
3017
- props,
3018
- i,
3019
- k;
3365
+ var self = Object.create(matchersUtil);
3020
3366
 
3021
- copy(self, customEqualityTesters, 'length');
3367
+ copyAndDeprecate(self, customEqualityTesters, 'length');
3022
3368
 
3023
3369
  for (i = 0; i < customEqualityTesters.length; i++) {
3024
- copy(self, customEqualityTesters, i);
3370
+ copyAndDeprecate(self, customEqualityTesters, i);
3371
+ }
3372
+
3373
+ // Avoid copying array props if we've previously done so,
3374
+ // to avoid triggering our own deprecation warnings.
3375
+ if (!self.isAsymmetricEqualityTesterArgCompatShim_) {
3376
+ copyAndDeprecateArrayMethods(self);
3025
3377
  }
3026
3378
 
3027
- var props = arrayProps();
3379
+ self.isAsymmetricEqualityTesterArgCompatShim_ = true;
3380
+ return self;
3381
+ }
3382
+
3383
+ function copyAndDeprecateArrayMethods(dest) {
3384
+ var props = arrayProps(),
3385
+ i,
3386
+ k;
3028
3387
 
3029
3388
  for (i = 0; i < props.length; i++) {
3030
3389
  k = props[i];
3390
+
3031
3391
  // Skip length (dealt with above), and anything that collides with
3032
3392
  // MatchesUtil e.g. an Array.prototype.contains method added by user code
3033
- if (k !== 'length' && !self[k]) {
3034
- copy(self, Array.prototype, k);
3393
+ if (k !== 'length' && !dest[k]) {
3394
+ copyAndDeprecate(dest, Array.prototype, k);
3035
3395
  }
3036
3396
  }
3037
-
3038
- return self;
3039
3397
  }
3040
3398
 
3041
- function copy(dest, src, propName) {
3399
+ function copyAndDeprecate(dest, src, propName) {
3042
3400
  Object.defineProperty(dest, propName, {
3043
3401
  get: function() {
3402
+ j$.getEnv().deprecated(
3403
+ 'The second argument to asymmetricMatch is now a ' +
3404
+ 'MatchersUtil. Using it as an array of custom equality testers is ' +
3405
+ 'deprecated and will stop working in a future release. ' +
3406
+ 'See <https://jasmine.github.io/tutorials/upgrading_to_Jasmine_4.0#asymmetricMatch-cet> for details.'
3407
+ );
3044
3408
  return src[propName];
3045
3409
  }
3046
3410
  });
@@ -3122,6 +3486,7 @@ getJasmineRequireObj().CallTracker = function(j$) {
3122
3486
  /**
3123
3487
  * Get the "this" object that was passed to a specific invocation of this spy.
3124
3488
  * @name Spy#calls#thisFor
3489
+ * @since 3.8.0
3125
3490
  * @function
3126
3491
  * @param {Integer} index The 0-based invocation index.
3127
3492
  * @return {Object?}
@@ -3283,6 +3648,7 @@ getJasmineRequireObj().Clock = function() {
3283
3648
 
3284
3649
  /**
3285
3650
  * @class Clock
3651
+ * @since 1.3.0
3286
3652
  * @classdesc Jasmine's mock clock is used when testing time dependent code.<br>
3287
3653
  * _Note:_ Do not construct this directly. You can get the current clock with
3288
3654
  * {@link jasmine.clock}.
@@ -3513,13 +3879,31 @@ getJasmineRequireObj().DelayedFunctionScheduler = function(j$) {
3513
3879
  var currentTime = 0;
3514
3880
  var delayedFnCount = 0;
3515
3881
  var deletedKeys = [];
3882
+ var ticking = false;
3516
3883
 
3517
3884
  self.tick = function(millis, tickDate) {
3518
- millis = millis || 0;
3519
- var endTime = currentTime + millis;
3885
+ if (ticking) {
3886
+ j$.getEnv().deprecated(
3887
+ 'The behavior of reentrant calls to jasmine.clock().tick() will ' +
3888
+ 'change in a future version. Either modify the affected spec to ' +
3889
+ 'not call tick() from within a setTimeout or setInterval handler, ' +
3890
+ 'or be aware that it may behave differently in the future. See ' +
3891
+ '<https://jasmine.github.io/tutorials/upgrading_to_Jasmine_4.0#deprecations-due-to-reentrant-calls-to-jasmine-clock-tick> ' +
3892
+ 'for details.'
3893
+ );
3894
+ }
3895
+
3896
+ ticking = true;
3897
+
3898
+ try {
3899
+ millis = millis || 0;
3900
+ var endTime = currentTime + millis;
3520
3901
 
3521
- runScheduledFunctions(endTime, tickDate);
3522
- currentTime = endTime;
3902
+ runScheduledFunctions(endTime, tickDate);
3903
+ currentTime = endTime;
3904
+ } finally {
3905
+ ticking = false;
3906
+ }
3523
3907
  };
3524
3908
 
3525
3909
  self.scheduleFunction = function(
@@ -3684,6 +4068,302 @@ getJasmineRequireObj().DelayedFunctionScheduler = function(j$) {
3684
4068
  return DelayedFunctionScheduler;
3685
4069
  };
3686
4070
 
4071
+ /* eslint-disable compat/compat */
4072
+ // TODO: Remove this in the next major release.
4073
+ getJasmineRequireObj().deprecatingSpecProxy = function(j$) {
4074
+ function isMember(target, prop) {
4075
+ return (
4076
+ Object.keys(target).indexOf(prop) !== -1 ||
4077
+ Object.keys(j$.Spec.prototype).indexOf(prop) !== -1
4078
+ );
4079
+ }
4080
+
4081
+ function isAllowedMember(prop) {
4082
+ return prop === 'id' || prop === 'description' || prop === 'getFullName';
4083
+ }
4084
+
4085
+ function msg(member) {
4086
+ var memberName = member.toString().replace(/^Symbol\((.+)\)$/, '$1');
4087
+ return (
4088
+ 'Access to private Spec members (in this case `' +
4089
+ memberName +
4090
+ '`) is not supported and will break in ' +
4091
+ 'a future release. See <https://jasmine.github.io/api/edge/Spec.html> ' +
4092
+ 'for correct usage.'
4093
+ );
4094
+ }
4095
+
4096
+ try {
4097
+ new Proxy({}, {});
4098
+ } catch (e) {
4099
+ // Environment does not support Poxy.
4100
+ return function(spec) {
4101
+ return spec;
4102
+ };
4103
+ }
4104
+
4105
+ function DeprecatingSpecProxyHandler(env) {
4106
+ this._env = env;
4107
+ }
4108
+
4109
+ DeprecatingSpecProxyHandler.prototype.get = function(target, prop, receiver) {
4110
+ this._maybeDeprecate(target, prop);
4111
+
4112
+ if (prop === 'getFullName') {
4113
+ // getFullName calls a private method. Re-bind 'this' to avoid a bogus
4114
+ // deprecation warning.
4115
+ return target.getFullName.bind(target);
4116
+ } else {
4117
+ return target[prop];
4118
+ }
4119
+ };
4120
+
4121
+ DeprecatingSpecProxyHandler.prototype.set = function(target, prop, value) {
4122
+ this._maybeDeprecate(target, prop);
4123
+ return (target[prop] = value);
4124
+ };
4125
+
4126
+ DeprecatingSpecProxyHandler.prototype._maybeDeprecate = function(
4127
+ target,
4128
+ prop
4129
+ ) {
4130
+ if (isMember(target, prop) && !isAllowedMember(prop)) {
4131
+ this._env.deprecated(msg(prop));
4132
+ }
4133
+ };
4134
+
4135
+ function deprecatingSpecProxy(spec, env) {
4136
+ return new Proxy(spec, new DeprecatingSpecProxyHandler(env));
4137
+ }
4138
+
4139
+ return deprecatingSpecProxy;
4140
+ };
4141
+
4142
+ /* eslint-disable compat/compat */
4143
+ // TODO: Remove this in the next major release.
4144
+ getJasmineRequireObj().deprecatingSuiteProxy = function(j$) {
4145
+ var allowedMembers = [
4146
+ 'id',
4147
+ 'children',
4148
+ 'description',
4149
+ 'parentSuite',
4150
+ 'getFullName'
4151
+ ];
4152
+
4153
+ function isMember(target, prop) {
4154
+ return (
4155
+ Object.keys(target).indexOf(prop) !== -1 ||
4156
+ Object.keys(j$.Suite.prototype).indexOf(prop) !== -1
4157
+ );
4158
+ }
4159
+
4160
+ function isAllowedMember(prop) {
4161
+ return allowedMembers.indexOf(prop) !== -1;
4162
+ }
4163
+
4164
+ function msg(member) {
4165
+ var memberName = member.toString().replace(/^Symbol\((.+)\)$/, '$1');
4166
+ return (
4167
+ 'Access to private Suite members (in this case `' +
4168
+ memberName +
4169
+ '`) is not supported and will break in ' +
4170
+ 'a future release. See <https://jasmine.github.io/api/edge/Suite.html> ' +
4171
+ 'for correct usage.'
4172
+ );
4173
+ }
4174
+ try {
4175
+ new Proxy({}, {});
4176
+ } catch (e) {
4177
+ // Environment does not support Poxy.
4178
+ return function(suite) {
4179
+ return suite;
4180
+ };
4181
+ }
4182
+
4183
+ function DeprecatingSuiteProxyHandler(parentSuite, env) {
4184
+ this._parentSuite = parentSuite;
4185
+ this._env = env;
4186
+ }
4187
+
4188
+ DeprecatingSuiteProxyHandler.prototype.get = function(
4189
+ target,
4190
+ prop,
4191
+ receiver
4192
+ ) {
4193
+ if (prop === 'children') {
4194
+ if (!this._children) {
4195
+ this._children = target.children.map(
4196
+ this._proxyForChild.bind(this, receiver)
4197
+ );
4198
+ }
4199
+
4200
+ return this._children;
4201
+ } else if (prop === 'parentSuite') {
4202
+ return this._parentSuite;
4203
+ } else {
4204
+ this._maybeDeprecate(target, prop);
4205
+ return target[prop];
4206
+ }
4207
+ };
4208
+
4209
+ DeprecatingSuiteProxyHandler.prototype.set = function(target, prop, value) {
4210
+ this._maybeDeprecate(target, prop);
4211
+ return (target[prop] = value);
4212
+ };
4213
+
4214
+ DeprecatingSuiteProxyHandler.prototype._maybeDeprecate = function(
4215
+ target,
4216
+ prop
4217
+ ) {
4218
+ if (isMember(target, prop) && !isAllowedMember(prop)) {
4219
+ this._env.deprecated(msg(prop));
4220
+ }
4221
+ };
4222
+
4223
+ DeprecatingSuiteProxyHandler.prototype._proxyForChild = function(
4224
+ ownProxy,
4225
+ child
4226
+ ) {
4227
+ if (child.children) {
4228
+ return deprecatingSuiteProxy(child, ownProxy, this._env);
4229
+ } else {
4230
+ return j$.deprecatingSpecProxy(child, this._env);
4231
+ }
4232
+ };
4233
+
4234
+ function deprecatingSuiteProxy(suite, parentSuite, env) {
4235
+ return new Proxy(suite, new DeprecatingSuiteProxyHandler(parentSuite, env));
4236
+ }
4237
+
4238
+ return deprecatingSuiteProxy;
4239
+ };
4240
+
4241
+ /* eslint-disable compat/compat */
4242
+ // TODO: Remove this in the next major release.
4243
+ getJasmineRequireObj().deprecatingThisProxy = function(j$) {
4244
+ var msg =
4245
+ "Access to 'this' in describe functions (and in arrow functions " +
4246
+ 'inside describe functions) is deprecated.';
4247
+
4248
+ try {
4249
+ new Proxy({}, {});
4250
+ } catch (e) {
4251
+ // Environment does not support Poxy.
4252
+ return function(suite) {
4253
+ return suite;
4254
+ };
4255
+ }
4256
+
4257
+ function DeprecatingThisProxyHandler(env) {
4258
+ this._env = env;
4259
+ }
4260
+
4261
+ DeprecatingThisProxyHandler.prototype.get = function(target, prop, receiver) {
4262
+ this._env.deprecated(msg);
4263
+ return target[prop];
4264
+ };
4265
+
4266
+ DeprecatingThisProxyHandler.prototype.set = function(target, prop, value) {
4267
+ this._env.deprecated(msg);
4268
+ return (target[prop] = value);
4269
+ };
4270
+
4271
+ return function(suite, env) {
4272
+ return new Proxy(suite, new DeprecatingThisProxyHandler(env));
4273
+ };
4274
+ };
4275
+
4276
+ getJasmineRequireObj().Deprecator = function(j$) {
4277
+ function Deprecator(topSuite) {
4278
+ this.topSuite_ = topSuite;
4279
+ this.verbose_ = false;
4280
+ this.toSuppress_ = [];
4281
+ }
4282
+
4283
+ var verboseNote =
4284
+ 'Note: This message will be shown only once. Set the verboseDeprecations ' +
4285
+ 'config property to true to see every occurrence.';
4286
+
4287
+ Deprecator.prototype.verboseDeprecations = function(enabled) {
4288
+ this.verbose_ = enabled;
4289
+ };
4290
+
4291
+ // runnable is a spec or a suite.
4292
+ // deprecation is a string or an Error.
4293
+ // See Env#deprecated for a description of the options argument.
4294
+ Deprecator.prototype.addDeprecationWarning = function(
4295
+ runnable,
4296
+ deprecation,
4297
+ options
4298
+ ) {
4299
+ options = options || {};
4300
+
4301
+ if (!this.verbose_ && !j$.isError_(deprecation)) {
4302
+ if (this.toSuppress_.indexOf(deprecation) !== -1) {
4303
+ return;
4304
+ }
4305
+ this.toSuppress_.push(deprecation);
4306
+ }
4307
+
4308
+ this.log_(runnable, deprecation, options);
4309
+ this.report_(runnable, deprecation, options);
4310
+ };
4311
+
4312
+ Deprecator.prototype.log_ = function(runnable, deprecation, options) {
4313
+ var context;
4314
+
4315
+ if (j$.isError_(deprecation)) {
4316
+ console.error(deprecation);
4317
+ return;
4318
+ }
4319
+
4320
+ if (runnable === this.topSuite_ || options.ignoreRunnable) {
4321
+ context = '';
4322
+ } else if (runnable.children) {
4323
+ context = ' (in suite: ' + runnable.getFullName() + ')';
4324
+ } else {
4325
+ context = ' (in spec: ' + runnable.getFullName() + ')';
4326
+ }
4327
+
4328
+ if (!options.omitStackTrace) {
4329
+ context += '\n' + this.stackTrace_();
4330
+ }
4331
+
4332
+ if (!this.verbose_) {
4333
+ context += '\n' + verboseNote;
4334
+ }
4335
+
4336
+ console.error('DEPRECATION: ' + deprecation + context);
4337
+ };
4338
+
4339
+ Deprecator.prototype.stackTrace_ = function() {
4340
+ var formatter = new j$.ExceptionFormatter();
4341
+ return formatter.stack(j$.util.errorWithStack()).replace(/^Error\n/m, '');
4342
+ };
4343
+
4344
+ Deprecator.prototype.report_ = function(runnable, deprecation, options) {
4345
+ if (options.ignoreRunnable) {
4346
+ runnable = this.topSuite_;
4347
+ }
4348
+
4349
+ if (j$.isError_(deprecation)) {
4350
+ runnable.addDeprecationWarning(deprecation);
4351
+ return;
4352
+ }
4353
+
4354
+ if (!this.verbose_) {
4355
+ deprecation += '\n' + verboseNote;
4356
+ }
4357
+
4358
+ runnable.addDeprecationWarning({
4359
+ message: deprecation,
4360
+ omitStackTrace: options.omitStackTrace || false
4361
+ });
4362
+ };
4363
+
4364
+ return Deprecator;
4365
+ };
4366
+
3687
4367
  getJasmineRequireObj().errors = function() {
3688
4368
  function ExpectationFailed() {}
3689
4369
 
@@ -3787,7 +4467,7 @@ getJasmineRequireObj().ExceptionFormatter = function(j$) {
3787
4467
  }
3788
4468
 
3789
4469
  if (!empty) {
3790
- return 'error properties: ' + j$.pp(result) + '\n';
4470
+ return 'error properties: ' + j$.basicPrettyPrinter_(result) + '\n';
3791
4471
  }
3792
4472
 
3793
4473
  return '';
@@ -3925,6 +4605,7 @@ getJasmineRequireObj().Expectation = function(j$) {
3925
4605
  * Otherwise evaluate the matcher.
3926
4606
  * @member
3927
4607
  * @name async-matchers#already
4608
+ * @since 3.8.0
3928
4609
  * @type {async-matchers}
3929
4610
  * @example
3930
4611
  * await expectAsync(myPromise).already.toBeResolved();
@@ -4140,7 +4821,7 @@ getJasmineRequireObj().buildExpectationResult = function(j$) {
4140
4821
  var result = {
4141
4822
  matcherName: options.matcherName,
4142
4823
  message: message(),
4143
- stack: stack(),
4824
+ stack: options.omitStackTrace ? '' : stack(),
4144
4825
  passed: options.passed
4145
4826
  };
4146
4827
 
@@ -4226,7 +4907,15 @@ getJasmineRequireObj().Expector = function(j$) {
4226
4907
 
4227
4908
  this.args.unshift(this.actual);
4228
4909
 
4229
- var matcher = matcherFactory(this.matchersUtil, this.customEqualityTesters);
4910
+ // TODO: Remove support for passing customEqualityTesters in the next major release.
4911
+ var matcher;
4912
+
4913
+ if (matcherFactory.length >= 2) {
4914
+ matcher = matcherFactory(this.matchersUtil, this.customEqualityTesters);
4915
+ } else {
4916
+ matcher = matcherFactory(this.matchersUtil);
4917
+ }
4918
+
4230
4919
  var comparisonFunc = this.filters.selectComparisonFunc(matcher);
4231
4920
  return comparisonFunc || matcher.compare;
4232
4921
  };
@@ -4911,8 +5600,6 @@ getJasmineRequireObj().DiffBuilder = function(j$) {
4911
5600
  };
4912
5601
 
4913
5602
  getJasmineRequireObj().MatchersUtil = function(j$) {
4914
- // TODO: convert all uses of j$.pp to use the injected pp
4915
-
4916
5603
  /**
4917
5604
  * @class MatchersUtil
4918
5605
  * @classdesc Utilities for use in implementing matchers.<br>
@@ -4943,10 +5630,19 @@ getJasmineRequireObj().MatchersUtil = function(j$) {
4943
5630
  * @since 2.0.0
4944
5631
  * @param {*} haystack The collection to search
4945
5632
  * @param {*} needle The value to search for
4946
- * @param [customTesters] An array of custom equality testers
5633
+ * @param [customTesters] An array of custom equality testers. Deprecated.
5634
+ * As of 3.6 this parameter no longer needs to be passed. It will be removed in 4.0.
4947
5635
  * @returns {boolean} True if `needle` was found in `haystack`
4948
5636
  */
4949
5637
  MatchersUtil.prototype.contains = function(haystack, needle, customTesters) {
5638
+ if (customTesters) {
5639
+ j$.getEnv().deprecated(
5640
+ 'Passing custom equality testers ' +
5641
+ 'to MatchersUtil#contains is deprecated. ' +
5642
+ 'See <https://jasmine.github.io/tutorials/upgrading_to_Jasmine_4.0#matchers-cet> for details.'
5643
+ );
5644
+ }
5645
+
4950
5646
  if (j$.isSet(haystack)) {
4951
5647
  return haystack.has(needle);
4952
5648
  }
@@ -4956,8 +5652,13 @@ getJasmineRequireObj().MatchersUtil = function(j$) {
4956
5652
  (!!haystack && !haystack.indexOf)
4957
5653
  ) {
4958
5654
  for (var i = 0; i < haystack.length; i++) {
4959
- if (this.equals(haystack[i], needle, customTesters)) {
4960
- return true;
5655
+ try {
5656
+ this.suppressDeprecation_ = true;
5657
+ if (this.equals(haystack[i], needle, customTesters)) {
5658
+ return true;
5659
+ }
5660
+ } finally {
5661
+ this.suppressDeprecation_ = false;
4961
5662
  }
4962
5663
  }
4963
5664
  return false;
@@ -5061,7 +5762,8 @@ getJasmineRequireObj().MatchersUtil = function(j$) {
5061
5762
  * @since 2.0.0
5062
5763
  * @param {*} a The first value to compare
5063
5764
  * @param {*} b The second value to compare
5064
- * @param [customTesters] An array of custom equality testers
5765
+ * @param [customTesters] An array of custom equality testers. Deprecated.
5766
+ * As of 3.6 this parameter no longer needs to be passed. It will be removed in 4.0.
5065
5767
  * @returns {boolean} True if the values are equal
5066
5768
  */
5067
5769
  MatchersUtil.prototype.equals = function(
@@ -5075,6 +5777,22 @@ getJasmineRequireObj().MatchersUtil = function(j$) {
5075
5777
  if (isDiffBuilder(customTestersOrDiffBuilder)) {
5076
5778
  diffBuilder = customTestersOrDiffBuilder;
5077
5779
  } else {
5780
+ if (customTestersOrDiffBuilder && !this.suppressDeprecation_) {
5781
+ j$.getEnv().deprecated(
5782
+ 'Passing custom equality testers ' +
5783
+ 'to MatchersUtil#equals is deprecated. ' +
5784
+ 'See <https://jasmine.github.io/tutorials/upgrading_to_Jasmine_4.0#matchers-cet> for details.'
5785
+ );
5786
+ }
5787
+
5788
+ if (diffBuilderOrNothing) {
5789
+ j$.getEnv().deprecated(
5790
+ 'Diff builder should be passed ' +
5791
+ 'as the third argument to MatchersUtil#equals, not the fourth. ' +
5792
+ 'See <https://jasmine.github.io/tutorials/upgrading_to_Jasmine_4.0#matchers-cet> for details.'
5793
+ );
5794
+ }
5795
+
5078
5796
  customTesters = customTestersOrDiffBuilder;
5079
5797
  diffBuilder = diffBuilderOrNothing;
5080
5798
  }
@@ -5571,9 +6289,33 @@ getJasmineRequireObj().MatchersUtil = function(j$) {
5571
6289
  /**
5572
6290
  * @interface AsymmetricEqualityTester
5573
6291
  * @classdesc An asymmetric equality tester is an object that can match multiple
5574
- * objects. Examples include jasmine.any() and jasmine.stringMatching().
5575
- * User-defined asymmetric equality testers can also be defined and used in
5576
- * expectations.
6292
+ * objects. Examples include jasmine.any() and jasmine.stringMatching(). Jasmine
6293
+ * includes a number of built-in asymmetric equality testers, such as
6294
+ * {@link jasmine.objectContaining}. User-defined asymmetric equality testers are
6295
+ * also supported.
6296
+ *
6297
+ * Asymmetric equality testers work with any matcher, including user-defined
6298
+ * custom matchers, that uses {@link MatchersUtil#equals} or
6299
+ * {@link MatchersUtil#contains}.
6300
+ *
6301
+ * @example
6302
+ * function numberDivisibleBy(divisor) {
6303
+ * return {
6304
+ * asymmetricMatch: function(n) {
6305
+ * return typeof n === 'number' && n % divisor === 0;
6306
+ * },
6307
+ * jasmineToString: function() {
6308
+ * return `<a number divisible by ${divisor}>`;
6309
+ * }
6310
+ * };
6311
+ * }
6312
+ *
6313
+ * var actual = {
6314
+ * n: 2,
6315
+ * otherFields: "don't care"
6316
+ * };
6317
+ *
6318
+ * expect(actual).toEqual(jasmine.objectContaining({n: numberDivisibleBy(2)}));
5577
6319
  * @see custom_asymmetric_equality_testers
5578
6320
  * @since 2.0.0
5579
6321
  */
@@ -7196,7 +7938,7 @@ getJasmineRequireObj().toThrowMatching = function(j$) {
7196
7938
  return toThrowMatching;
7197
7939
  };
7198
7940
 
7199
- getJasmineRequireObj().MockDate = function() {
7941
+ getJasmineRequireObj().MockDate = function(j$) {
7200
7942
  function MockDate(global) {
7201
7943
  var self = this;
7202
7944
  var currentTime = 0;
@@ -7214,6 +7956,14 @@ getJasmineRequireObj().MockDate = function() {
7214
7956
  if (mockDate instanceof GlobalDate) {
7215
7957
  currentTime = mockDate.getTime();
7216
7958
  } else {
7959
+ if (!j$.util.isUndefined(mockDate)) {
7960
+ j$.getEnv().deprecated(
7961
+ 'The argument to jasmine.clock().mockDate(), if specified, ' +
7962
+ 'should be a Date instance. Passing anything other than a Date ' +
7963
+ 'will be treated as an error in a future release.'
7964
+ );
7965
+ }
7966
+
7217
7967
  currentTime = new GlobalDate().getTime();
7218
7968
  }
7219
7969
 
@@ -7715,10 +8465,14 @@ getJasmineRequireObj().QueueRunner = function(j$) {
7715
8465
  StopExecutionError.prototype = new Error();
7716
8466
  j$.StopExecutionError = StopExecutionError;
7717
8467
 
7718
- function once(fn) {
8468
+ function once(fn, onTwice) {
7719
8469
  var called = false;
7720
8470
  return function(arg) {
7721
- if (!called) {
8471
+ if (called) {
8472
+ if (onTwice) {
8473
+ onTwice();
8474
+ }
8475
+ } else {
7722
8476
  called = true;
7723
8477
  // Direct call using single parameter, because cleanup/next does not need more
7724
8478
  fn(arg);
@@ -7727,6 +8481,16 @@ getJasmineRequireObj().QueueRunner = function(j$) {
7727
8481
  };
7728
8482
  }
7729
8483
 
8484
+ function fallbackOnMultipleDone() {
8485
+ console.error(
8486
+ new Error(
8487
+ "An asynchronous function called its 'done' " +
8488
+ 'callback more than once, in a QueueRunner without a onMultipleDone ' +
8489
+ 'handler.'
8490
+ )
8491
+ );
8492
+ }
8493
+
7730
8494
  function emptyFn() {}
7731
8495
 
7732
8496
  function QueueRunner(attrs) {
@@ -7741,6 +8505,7 @@ getJasmineRequireObj().QueueRunner = function(j$) {
7741
8505
  fn();
7742
8506
  };
7743
8507
  this.onException = attrs.onException || emptyFn;
8508
+ this.onMultipleDone = attrs.onMultipleDone || fallbackOnMultipleDone;
7744
8509
  this.userContext = attrs.userContext || new j$.UserContext();
7745
8510
  this.timeout = attrs.timeout || {
7746
8511
  setTimeout: setTimeout,
@@ -7798,8 +8563,9 @@ getJasmineRequireObj().QueueRunner = function(j$) {
7798
8563
  var self = this,
7799
8564
  completedSynchronously = true,
7800
8565
  handleError = function handleError(error) {
8566
+ // TODO probably shouldn't next() right away here.
8567
+ // That makes debugging async failures much more confusing.
7801
8568
  onException(error);
7802
- next(error);
7803
8569
  },
7804
8570
  cleanup = once(function cleanup() {
7805
8571
  if (timeoutId !== void 0) {
@@ -7807,31 +8573,52 @@ getJasmineRequireObj().QueueRunner = function(j$) {
7807
8573
  }
7808
8574
  self.globalErrors.popListener(handleError);
7809
8575
  }),
7810
- next = once(function next(err) {
7811
- cleanup();
8576
+ next = once(
8577
+ function next(err) {
8578
+ cleanup();
7812
8579
 
7813
- if (j$.isError_(err)) {
7814
- if (!(err instanceof StopExecutionError) && !err.jasmineMessage) {
7815
- self.fail(err);
8580
+ if (j$.isError_(err)) {
8581
+ if (!(err instanceof StopExecutionError) && !err.jasmineMessage) {
8582
+ self.fail(err);
8583
+ }
8584
+ self.errored = errored = true;
8585
+ } else if (typeof err !== 'undefined' && !self.errored) {
8586
+ self.deprecated(
8587
+ 'Any argument passed to a done callback will be treated as an ' +
8588
+ 'error in a future release. Call the done callback without ' +
8589
+ "arguments if you don't want to trigger a spec failure."
8590
+ );
7816
8591
  }
7817
- self.errored = errored = true;
7818
- }
7819
8592
 
7820
- function runNext() {
7821
- if (self.completeOnFirstError && errored) {
7822
- self.skipToCleanup(iterativeIndex);
7823
- } else {
7824
- self.run(iterativeIndex + 1);
8593
+ function runNext() {
8594
+ if (self.completeOnFirstError && errored) {
8595
+ self.skipToCleanup(iterativeIndex);
8596
+ } else {
8597
+ self.run(iterativeIndex + 1);
8598
+ }
7825
8599
  }
7826
- }
7827
8600
 
7828
- if (completedSynchronously) {
7829
- self.setTimeout(runNext);
7830
- } else {
7831
- runNext();
8601
+ if (completedSynchronously) {
8602
+ self.setTimeout(runNext);
8603
+ } else {
8604
+ runNext();
8605
+ }
8606
+ },
8607
+ function() {
8608
+ try {
8609
+ if (!timedOut) {
8610
+ self.onMultipleDone();
8611
+ }
8612
+ } catch (error) {
8613
+ // Any error we catch here is probably due to a bug in Jasmine,
8614
+ // and it's not likely to end up anywhere useful if we let it
8615
+ // propagate. Log it so it can at least show up when debugging.
8616
+ console.error(error);
8617
+ }
7832
8618
  }
7833
- }),
8619
+ ),
7834
8620
  errored = false,
8621
+ timedOut = false,
7835
8622
  queueableFn = self.queueableFns[iterativeIndex],
7836
8623
  timeoutId,
7837
8624
  maybeThenable;
@@ -7847,6 +8634,7 @@ getJasmineRequireObj().QueueRunner = function(j$) {
7847
8634
  if (queueableFn.timeout !== undefined) {
7848
8635
  var timeoutInterval = queueableFn.timeout || j$.DEFAULT_TIMEOUT_INTERVAL;
7849
8636
  timeoutId = self.setTimeout(function() {
8637
+ timedOut = true;
7850
8638
  var error = new Error(
7851
8639
  'Timeout - Async function did not complete within ' +
7852
8640
  timeoutInterval +
@@ -7855,6 +8643,9 @@ getJasmineRequireObj().QueueRunner = function(j$) {
7855
8643
  ? '(custom timeout)'
7856
8644
  : '(set by jasmine.DEFAULT_TIMEOUT_INTERVAL)')
7857
8645
  );
8646
+ // TODO Need to decide what to do about a successful completion after a
8647
+ // timeout. That should probably not be a deprecation, and maybe not
8648
+ // an error in 4.0. (But a diagnostic of some sort might be helpful.)
7858
8649
  onException(error);
7859
8650
  next();
7860
8651
  }, timeoutInterval);
@@ -7920,30 +8711,39 @@ getJasmineRequireObj().QueueRunner = function(j$) {
7920
8711
 
7921
8712
  this.clearStack(function() {
7922
8713
  self.globalErrors.popListener(self.handleFinalError);
7923
- self.onComplete(self.errored && new StopExecutionError());
8714
+
8715
+ if (self.errored) {
8716
+ self.onComplete(new StopExecutionError());
8717
+ } else {
8718
+ self.onComplete();
8719
+ }
7924
8720
  });
7925
8721
  };
7926
8722
 
7927
8723
  QueueRunner.prototype.diagnoseConflictingAsync_ = function(fn, retval) {
8724
+ var msg;
8725
+
7928
8726
  if (retval && j$.isFunction_(retval.then)) {
7929
- // Issue a warning that matches the user's code
8727
+ // Issue a warning that matches the user's code.
8728
+ // Omit the stack trace because there's almost certainly no user code
8729
+ // on the stack at this point.
7930
8730
  if (j$.isAsyncFunction_(fn)) {
7931
- this.deprecated(
8731
+ msg =
7932
8732
  'An asynchronous before/it/after ' +
7933
- 'function was defined with the async keyword but also took a ' +
7934
- 'done callback. This is not supported and will stop working in' +
7935
- ' the future. Either remove the done callback (recommended) or ' +
7936
- 'remove the async keyword.'
7937
- );
8733
+ 'function was defined with the async keyword but also took a ' +
8734
+ 'done callback. This is not supported and will stop working in' +
8735
+ ' the future. Either remove the done callback (recommended) or ' +
8736
+ 'remove the async keyword.';
7938
8737
  } else {
7939
- this.deprecated(
8738
+ msg =
7940
8739
  'An asynchronous before/it/after ' +
7941
- 'function took a done callback but also returned a promise. ' +
7942
- 'This is not supported and will stop working in the future. ' +
7943
- 'Either remove the done callback (recommended) or change the ' +
7944
- 'function to not return a promise.'
7945
- );
8740
+ 'function took a done callback but also returned a promise. ' +
8741
+ 'This is not supported and will stop working in the future. ' +
8742
+ 'Either remove the done callback (recommended) or change the ' +
8743
+ 'function to not return a promise.';
7946
8744
  }
8745
+
8746
+ this.deprecated(msg, { omitStackTrace: true });
7947
8747
  }
7948
8748
  };
7949
8749
 
@@ -7951,7 +8751,7 @@ getJasmineRequireObj().QueueRunner = function(j$) {
7951
8751
  };
7952
8752
 
7953
8753
  getJasmineRequireObj().ReportDispatcher = function(j$) {
7954
- function ReportDispatcher(methods, queueRunnerFactory) {
8754
+ function ReportDispatcher(methods, queueRunnerFactory, deprecated) {
7955
8755
  var dispatchedMethods = methods || [];
7956
8756
 
7957
8757
  for (var i = 0; i < dispatchedMethods.length; i++) {
@@ -7995,7 +8795,18 @@ getJasmineRequireObj().ReportDispatcher = function(j$) {
7995
8795
  queueRunnerFactory({
7996
8796
  queueableFns: fns,
7997
8797
  onComplete: onComplete,
7998
- isReporter: true
8798
+ isReporter: true,
8799
+ onMultipleDone: function() {
8800
+ deprecated(
8801
+ "An asynchronous reporter callback called its 'done' callback " +
8802
+ 'more than once. This is a bug in the reporter callback in ' +
8803
+ 'question. This will be treated as an error in a future ' +
8804
+ 'version. See' +
8805
+ '<https://jasmine.github.io/tutorials/upgrading_to_Jasmine_4.0#deprecations-due-to-calling-done-multiple-times> ' +
8806
+ 'for more information.',
8807
+ { ignoreRunnable: true }
8808
+ );
8809
+ }
7999
8810
  });
8000
8811
  }
8001
8812
 
@@ -8625,7 +9436,7 @@ getJasmineRequireObj().Spy = function(j$) {
8625
9436
  "Spy '" +
8626
9437
  strategyArgs.name +
8627
9438
  "' received a call with arguments " +
8628
- j$.pp(Array.prototype.slice.call(args)) +
9439
+ j$.basicPrettyPrinter_(Array.prototype.slice.call(args)) +
8629
9440
  ' but all configured strategies specify other arguments.'
8630
9441
  );
8631
9442
  } else {
@@ -9342,6 +10153,7 @@ getJasmineRequireObj().Suite = function(j$) {
9342
10153
  /**
9343
10154
  * @interface Suite
9344
10155
  * @see Env#topSuite
10156
+ * @since 2.0.0
9345
10157
  */
9346
10158
  function Suite(attrs) {
9347
10159
  this.env = attrs.env;
@@ -9350,6 +10162,7 @@ getJasmineRequireObj().Suite = function(j$) {
9350
10162
  * @name Suite#id
9351
10163
  * @readonly
9352
10164
  * @type {string}
10165
+ * @since 2.0.0
9353
10166
  */
9354
10167
  this.id = attrs.id;
9355
10168
  /**
@@ -9364,12 +10177,15 @@ getJasmineRequireObj().Suite = function(j$) {
9364
10177
  * @name Suite#description
9365
10178
  * @readonly
9366
10179
  * @type {string}
10180
+ * @since 2.0.0
9367
10181
  */
9368
10182
  this.description = attrs.description;
9369
10183
  this.expectationFactory = attrs.expectationFactory;
9370
10184
  this.asyncExpectationFactory = attrs.asyncExpectationFactory;
9371
10185
  this.expectationResultFactory = attrs.expectationResultFactory;
9372
10186
  this.throwOnExpectationFailure = !!attrs.throwOnExpectationFailure;
10187
+ this.autoCleanClosures =
10188
+ attrs.autoCleanClosures === undefined ? true : !!attrs.autoCleanClosures;
9373
10189
 
9374
10190
  this.beforeFns = [];
9375
10191
  this.afterFns = [];
@@ -9382,29 +10198,11 @@ getJasmineRequireObj().Suite = function(j$) {
9382
10198
  * The suite's children.
9383
10199
  * @name Suite#children
9384
10200
  * @type {Array.<(Spec|Suite)>}
10201
+ * @since 2.0.0
9385
10202
  */
9386
10203
  this.children = [];
9387
10204
 
9388
- /**
9389
- * @typedef SuiteResult
9390
- * @property {Int} id - The unique id of this suite.
9391
- * @property {String} description - The description text passed to the {@link describe} that made this suite.
9392
- * @property {String} fullName - The full description including all ancestors of this suite.
9393
- * @property {Expectation[]} failedExpectations - The list of expectations that failed in an {@link afterAll} for this suite.
9394
- * @property {Expectation[]} deprecationWarnings - The list of deprecation warnings that occurred on this suite.
9395
- * @property {String} status - Once the suite has completed, this string represents the pass/fail status of this suite.
9396
- * @property {number} duration - The time in ms for Suite execution, including any before/afterAll, before/afterEach.
9397
- * @property {Object} properties - User-supplied properties, if any, that were set using {@link Env#setSuiteProperty}
9398
- */
9399
- this.result = {
9400
- id: this.id,
9401
- description: this.description,
9402
- fullName: this.getFullName(),
9403
- failedExpectations: [],
9404
- deprecationWarnings: [],
9405
- duration: null,
9406
- properties: null
9407
- };
10205
+ this.reset();
9408
10206
  }
9409
10207
 
9410
10208
  Suite.prototype.setSuiteProperty = function(key, value) {
@@ -9425,6 +10223,7 @@ getJasmineRequireObj().Suite = function(j$) {
9425
10223
  * @name Suite#getFullName
9426
10224
  * @function
9427
10225
  * @returns {string}
10226
+ * @since 2.0.0
9428
10227
  */
9429
10228
  Suite.prototype.getFullName = function() {
9430
10229
  var fullName = [];
@@ -9440,10 +10239,22 @@ getJasmineRequireObj().Suite = function(j$) {
9440
10239
  return fullName.join(' ');
9441
10240
  };
9442
10241
 
10242
+ /*
10243
+ * Mark the suite with "pending" status
10244
+ */
9443
10245
  Suite.prototype.pend = function() {
9444
10246
  this.markedPending = true;
9445
10247
  };
9446
10248
 
10249
+ /*
10250
+ * Like {@link Suite#pend}, but pending state will survive {@link Spec#reset}
10251
+ * Useful for fdescribe, xdescribe, where pending state should remain.
10252
+ */
10253
+ Suite.prototype.exclude = function() {
10254
+ this.pend();
10255
+ this.markedExcluding = true;
10256
+ };
10257
+
9447
10258
  Suite.prototype.beforeEach = function(fn) {
9448
10259
  this.beforeFns.unshift(fn);
9449
10260
  };
@@ -9475,10 +10286,40 @@ getJasmineRequireObj().Suite = function(j$) {
9475
10286
  }
9476
10287
 
9477
10288
  Suite.prototype.cleanupBeforeAfter = function() {
9478
- removeFns(this.beforeAllFns);
9479
- removeFns(this.afterAllFns);
9480
- removeFns(this.beforeFns);
9481
- removeFns(this.afterFns);
10289
+ if (this.autoCleanClosures) {
10290
+ removeFns(this.beforeAllFns);
10291
+ removeFns(this.afterAllFns);
10292
+ removeFns(this.beforeFns);
10293
+ removeFns(this.afterFns);
10294
+ }
10295
+ };
10296
+
10297
+ Suite.prototype.reset = function() {
10298
+ /**
10299
+ * @typedef SuiteResult
10300
+ * @property {Int} id - The unique id of this suite.
10301
+ * @property {String} description - The description text passed to the {@link describe} that made this suite.
10302
+ * @property {String} fullName - The full description including all ancestors of this suite.
10303
+ * @property {Expectation[]} failedExpectations - The list of expectations that failed in an {@link afterAll} for this suite.
10304
+ * @property {Expectation[]} deprecationWarnings - The list of deprecation warnings that occurred on this suite.
10305
+ * @property {String} status - Once the suite has completed, this string represents the pass/fail status of this suite.
10306
+ * @property {number} duration - The time in ms for Suite execution, including any before/afterAll, before/afterEach.
10307
+ * @property {Object} properties - User-supplied properties, if any, that were set using {@link Env#setSuiteProperty}
10308
+ * @since 2.0.0
10309
+ */
10310
+ this.result = {
10311
+ id: this.id,
10312
+ description: this.description,
10313
+ fullName: this.getFullName(),
10314
+ failedExpectations: [],
10315
+ deprecationWarnings: [],
10316
+ duration: null,
10317
+ properties: null
10318
+ };
10319
+ this.markedPending = this.markedExcluding;
10320
+ this.children.forEach(function(child) {
10321
+ child.reset();
10322
+ });
9482
10323
  };
9483
10324
 
9484
10325
  Suite.prototype.addChild = function(child) {
@@ -9541,6 +10382,36 @@ getJasmineRequireObj().Suite = function(j$) {
9541
10382
  this.result.failedExpectations.push(failedExpectation);
9542
10383
  };
9543
10384
 
10385
+ Suite.prototype.onMultipleDone = function() {
10386
+ var msg;
10387
+
10388
+ // Issue a deprecation. Include the context ourselves and pass
10389
+ // ignoreRunnable: true, since getting here always means that we've already
10390
+ // moved on and the current runnable isn't the one that caused the problem.
10391
+ if (this.parentSuite) {
10392
+ msg =
10393
+ "An asynchronous function called its 'done' callback more than " +
10394
+ 'once. This is a bug in the spec, beforeAll, beforeEach, afterAll, ' +
10395
+ 'or afterEach function in question. This will be treated as an error ' +
10396
+ 'in a future version. See' +
10397
+ '<https://jasmine.github.io/tutorials/upgrading_to_Jasmine_4.0#deprecations-due-to-calling-done-multiple-times> ' +
10398
+ 'for more information.\n' +
10399
+ '(in suite: ' +
10400
+ this.getFullName() +
10401
+ ')';
10402
+ } else {
10403
+ msg =
10404
+ 'A top-level beforeAll or afterAll function called its ' +
10405
+ "'done' callback more than once. This is a bug in the beforeAll " +
10406
+ 'or afterAll function in question. This will be treated as an ' +
10407
+ 'error in a future version. See' +
10408
+ '<https://jasmine.github.io/tutorials/upgrading_to_Jasmine_4.0#deprecations-due-to-calling-done-multiple-times> ' +
10409
+ 'for more information.';
10410
+ }
10411
+
10412
+ this.env.deprecated(msg, { ignoreRunnable: true });
10413
+ };
10414
+
9544
10415
  Suite.prototype.addExpectationResult = function() {
9545
10416
  if (isFailure(arguments)) {
9546
10417
  var data = arguments[1];
@@ -9643,7 +10514,10 @@ getJasmineRequireObj().TreeProcessor = function() {
9643
10514
  onException: function() {
9644
10515
  tree.onException.apply(tree, arguments);
9645
10516
  },
9646
- onComplete: done
10517
+ onComplete: done,
10518
+ onMultipleDone: tree.onMultipleDone
10519
+ ? tree.onMultipleDone.bind(tree)
10520
+ : null
9647
10521
  });
9648
10522
  };
9649
10523
 
@@ -9815,7 +10689,10 @@ getJasmineRequireObj().TreeProcessor = function() {
9815
10689
  userContext: node.sharedUserContext(),
9816
10690
  onException: function() {
9817
10691
  node.onException.apply(node, arguments);
9818
- }
10692
+ },
10693
+ onMultipleDone: node.onMultipleDone
10694
+ ? node.onMultipleDone.bind(node)
10695
+ : null
9819
10696
  });
9820
10697
  }
9821
10698
  };
@@ -9872,5 +10749,5 @@ getJasmineRequireObj().UserContext = function(j$) {
9872
10749
  };
9873
10750
 
9874
10751
  getJasmineRequireObj().version = function() {
9875
- return '3.9.0';
10752
+ return '3.99.0';
9876
10753
  };