jasmine-core 3.7.1 → 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;
@@ -267,9 +317,21 @@ getJasmineRequireObj().base = function(j$, jasmineGlobal) {
267
317
  };
268
318
 
269
319
  j$.isError_ = function(value) {
320
+ if (!value) {
321
+ return false;
322
+ }
323
+
270
324
  if (value instanceof Error) {
271
325
  return true;
272
326
  }
327
+ if (
328
+ typeof window !== 'undefined' &&
329
+ typeof window.trustedTypes !== 'undefined'
330
+ ) {
331
+ return (
332
+ typeof value.stack === 'string' && typeof value.message === 'string'
333
+ );
334
+ }
273
335
  if (value && value.constructor && value.constructor.constructor) {
274
336
  var valueGlobal = value.constructor.constructor('return this');
275
337
  if (j$.isFunction_(valueGlobal)) {
@@ -371,8 +433,21 @@ getJasmineRequireObj().base = function(j$, jasmineGlobal) {
371
433
  return matches ? matches[1] : '<anonymous>';
372
434
  };
373
435
 
436
+ j$.isPending_ = function(promise) {
437
+ var sentinel = {};
438
+ // eslint-disable-next-line compat/compat
439
+ return Promise.race([promise, Promise.resolve(sentinel)]).then(
440
+ function(result) {
441
+ return result === sentinel;
442
+ },
443
+ function() {
444
+ return false;
445
+ }
446
+ );
447
+ };
448
+
374
449
  /**
375
- * 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}),
376
451
  * that will succeed if the actual value being compared is an instance of the specified class/constructor.
377
452
  * @name jasmine.any
378
453
  * @since 1.3.0
@@ -384,7 +459,7 @@ getJasmineRequireObj().base = function(j$, jasmineGlobal) {
384
459
  };
385
460
 
386
461
  /**
387
- * 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}),
388
463
  * that will succeed if the actual value being compared is not `null` and not `undefined`.
389
464
  * @name jasmine.anything
390
465
  * @since 2.2.0
@@ -395,7 +470,7 @@ getJasmineRequireObj().base = function(j$, jasmineGlobal) {
395
470
  };
396
471
 
397
472
  /**
398
- * 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}),
399
474
  * that will succeed if the actual value being compared is `true` or anything truthy.
400
475
  * @name jasmine.truthy
401
476
  * @since 3.1.0
@@ -406,7 +481,7 @@ getJasmineRequireObj().base = function(j$, jasmineGlobal) {
406
481
  };
407
482
 
408
483
  /**
409
- * 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}),
410
485
  * that will succeed if the actual value being compared is `null`, `undefined`, `0`, `false` or anything falsey.
411
486
  * @name jasmine.falsy
412
487
  * @since 3.1.0
@@ -417,7 +492,7 @@ getJasmineRequireObj().base = function(j$, jasmineGlobal) {
417
492
  };
418
493
 
419
494
  /**
420
- * 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}),
421
496
  * that will succeed if the actual value being compared is empty.
422
497
  * @name jasmine.empty
423
498
  * @since 3.1.0
@@ -428,7 +503,7 @@ getJasmineRequireObj().base = function(j$, jasmineGlobal) {
428
503
  };
429
504
 
430
505
  /**
431
- * 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}),
432
507
  * that will succeed if the actual value being compared is not empty.
433
508
  * @name jasmine.notEmpty
434
509
  * @since 3.1.0
@@ -439,7 +514,7 @@ getJasmineRequireObj().base = function(j$, jasmineGlobal) {
439
514
  };
440
515
 
441
516
  /**
442
- * 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}),
443
518
  * that will succeed if the actual value being compared contains at least the keys and values.
444
519
  * @name jasmine.objectContaining
445
520
  * @since 1.3.0
@@ -451,7 +526,7 @@ getJasmineRequireObj().base = function(j$, jasmineGlobal) {
451
526
  };
452
527
 
453
528
  /**
454
- * 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}),
455
530
  * that will succeed if the actual value is a `String` that matches the `RegExp` or `String`.
456
531
  * @name jasmine.stringMatching
457
532
  * @since 2.2.0
@@ -463,7 +538,19 @@ getJasmineRequireObj().base = function(j$, jasmineGlobal) {
463
538
  };
464
539
 
465
540
  /**
466
- * 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}),
467
554
  * that will succeed if the actual value is an `Array` that contains at least the elements in the sample.
468
555
  * @name jasmine.arrayContaining
469
556
  * @since 2.2.0
@@ -475,7 +562,7 @@ getJasmineRequireObj().base = function(j$, jasmineGlobal) {
475
562
  };
476
563
 
477
564
  /**
478
- * 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}),
479
566
  * that will succeed if the actual value is an `Array` that contains all of the elements in the sample in any order.
480
567
  * @name jasmine.arrayWithExactContents
481
568
  * @since 2.8.0
@@ -487,7 +574,7 @@ getJasmineRequireObj().base = function(j$, jasmineGlobal) {
487
574
  };
488
575
 
489
576
  /**
490
- * 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}),
491
578
  * that will succeed if every key/value pair in the sample passes the deep equality comparison
492
579
  * with at least one key/value pair in the actual value being compared
493
580
  * @name jasmine.mapContaining
@@ -500,7 +587,7 @@ getJasmineRequireObj().base = function(j$, jasmineGlobal) {
500
587
  };
501
588
 
502
589
  /**
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}),
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}),
504
591
  * that will succeed if every item in the sample passes the deep equality comparison
505
592
  * with at least one item in the actual value being compared
506
593
  * @name jasmine.setContaining
@@ -675,15 +762,49 @@ getJasmineRequireObj().util = function(j$) {
675
762
  }
676
763
  };
677
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
+
678
780
  return util;
679
781
  };
680
782
 
681
783
  getJasmineRequireObj().Spec = function(j$) {
784
+ /**
785
+ * @interface Spec
786
+ * @see Configuration#specFilter
787
+ * @since 2.0.0
788
+ */
682
789
  function Spec(attrs) {
683
790
  this.expectationFactory = attrs.expectationFactory;
684
791
  this.asyncExpectationFactory = attrs.asyncExpectationFactory;
685
792
  this.resultCallback = attrs.resultCallback || function() {};
793
+ /**
794
+ * The unique ID of this spec.
795
+ * @name Spec#id
796
+ * @readonly
797
+ * @type {string}
798
+ * @since 2.0.0
799
+ */
686
800
  this.id = attrs.id;
801
+ /**
802
+ * The description passed to the {@link it} that created this spec.
803
+ * @name Spec#description
804
+ * @readonly
805
+ * @type {string}
806
+ * @since 2.0.0
807
+ */
687
808
  this.description = attrs.description || '';
688
809
  this.queueableFn = attrs.queueableFn;
689
810
  this.beforeAndAfterFns =
@@ -697,6 +818,8 @@ getJasmineRequireObj().Spec = function(j$) {
697
818
  return {};
698
819
  };
699
820
  this.onStart = attrs.onStart || function() {};
821
+ this.autoCleanClosures =
822
+ attrs.autoCleanClosures === undefined ? true : !!attrs.autoCleanClosures;
700
823
  this.getSpecName =
701
824
  attrs.getSpecName ||
702
825
  function() {
@@ -704,6 +827,7 @@ getJasmineRequireObj().Spec = function(j$) {
704
827
  };
705
828
  this.expectationResultFactory =
706
829
  attrs.expectationResultFactory || function() {};
830
+ this.deprecated = attrs.deprecated || function() {};
707
831
  this.queueRunnerFactory = attrs.queueRunnerFactory || function() {};
708
832
  this.catchingExceptions =
709
833
  attrs.catchingExceptions ||
@@ -714,7 +838,7 @@ getJasmineRequireObj().Spec = function(j$) {
714
838
  this.timer = attrs.timer || new j$.Timer();
715
839
 
716
840
  if (!this.queueableFn.fn) {
717
- this.pend();
841
+ this.exclude();
718
842
  }
719
843
 
720
844
  /**
@@ -729,7 +853,8 @@ getJasmineRequireObj().Spec = function(j$) {
729
853
  * @property {String} status - Once the spec has completed, this string represents the pass/fail status of this spec.
730
854
  * @property {number} duration - The time in ms used by the spec execution, including any before/afterEach.
731
855
  * @property {Object} properties - User-supplied properties, if any, that were set using {@link Env#setSpecProperty}
732
- */
856
+ * @since 2.0.0
857
+ x */
733
858
  this.result = {
734
859
  id: this.id,
735
860
  description: this.description,
@@ -781,7 +906,9 @@ getJasmineRequireObj().Spec = function(j$) {
781
906
 
782
907
  var complete = {
783
908
  fn: function(done) {
784
- self.queueableFn.fn = null;
909
+ if (self.autoCleanClosures) {
910
+ self.queueableFn.fn = null;
911
+ }
785
912
  self.result.status = self.status(excluded, failSpecWithNoExp);
786
913
  self.result.duration = self.timer.elapsed();
787
914
  self.resultCallback(self.result, done);
@@ -798,13 +925,32 @@ getJasmineRequireObj().Spec = function(j$) {
798
925
  onException: function() {
799
926
  self.onException.apply(self, arguments);
800
927
  },
801
- onComplete: function() {
802
- onComplete(
803
- self.result.status === 'failed' &&
804
- 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 }
805
943
  );
806
944
  },
807
- 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)
808
954
  };
809
955
 
810
956
  if (this.markedPending || excluded === true) {
@@ -818,6 +964,36 @@ getJasmineRequireObj().Spec = function(j$) {
818
964
  this.queueRunnerFactory(runnerConfig);
819
965
  };
820
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
+
821
997
  Spec.prototype.onException = function onException(e) {
822
998
  if (Spec.isPendingSpecException(e)) {
823
999
  this.pend(extractCustomPendingMessage(e));
@@ -841,6 +1017,10 @@ getJasmineRequireObj().Spec = function(j$) {
841
1017
  );
842
1018
  };
843
1019
 
1020
+ /*
1021
+ * Marks state as pending
1022
+ * @param {string} [message] An optional reason message
1023
+ */
844
1024
  Spec.prototype.pend = function(message) {
845
1025
  this.markedPending = true;
846
1026
  if (message) {
@@ -848,6 +1028,19 @@ getJasmineRequireObj().Spec = function(j$) {
848
1028
  }
849
1029
  };
850
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
+
851
1044
  Spec.prototype.getResult = function() {
852
1045
  this.result.status = this.status();
853
1046
  return this.result;
@@ -875,6 +1068,13 @@ getJasmineRequireObj().Spec = function(j$) {
875
1068
  return 'passed';
876
1069
  };
877
1070
 
1071
+ /**
1072
+ * The full description including all ancestors of this spec.
1073
+ * @name Spec#getFullName
1074
+ * @function
1075
+ * @returns {string}
1076
+ * @since 2.0.0
1077
+ */
878
1078
  Spec.prototype.getFullName = function() {
879
1079
  return this.getSpecName(this);
880
1080
  };
@@ -963,11 +1163,12 @@ getJasmineRequireObj().Order = function() {
963
1163
 
964
1164
  getJasmineRequireObj().Env = function(j$) {
965
1165
  /**
966
- * _Note:_ Do not construct this directly, Jasmine will make one during booting.
967
- * @name Env
1166
+ * @class Env
968
1167
  * @since 2.0.0
969
- * @classdesc The Jasmine environment
970
- * @constructor
1168
+ * @classdesc The Jasmine environment.<br>
1169
+ * _Note:_ Do not construct this directly. You can obtain the Env instance by
1170
+ * calling {@link jasmine.getEnv}.
1171
+ * @hideconstructor
971
1172
  */
972
1173
  function Env(options) {
973
1174
  options = options || {};
@@ -998,7 +1199,8 @@ getJasmineRequireObj().Env = function(j$) {
998
1199
 
999
1200
  /**
1000
1201
  * This represents the available options to configure Jasmine.
1001
- * Options that are not provided will use their default values
1202
+ * Options that are not provided will use their default values.
1203
+ * @see Env#configure
1002
1204
  * @interface Configuration
1003
1205
  * @since 3.3.0
1004
1206
  */
@@ -1016,7 +1218,7 @@ getJasmineRequireObj().Env = function(j$) {
1016
1218
  * Null causes the seed to be determined randomly at the start of execution.
1017
1219
  * @name Configuration#seed
1018
1220
  * @since 3.3.0
1019
- * @type function
1221
+ * @type (number|string)
1020
1222
  * @default null
1021
1223
  */
1022
1224
  seed: null,
@@ -1026,8 +1228,17 @@ getJasmineRequireObj().Env = function(j$) {
1026
1228
  * @since 3.3.0
1027
1229
  * @type Boolean
1028
1230
  * @default false
1231
+ * @deprecated Use the `stopOnSpecFailure` config property instead.
1029
1232
  */
1030
1233
  failFast: false,
1234
+ /**
1235
+ * Whether to stop execution of the suite after the first spec failure
1236
+ * @name Configuration#stopOnSpecFailure
1237
+ * @since 3.9.0
1238
+ * @type Boolean
1239
+ * @default false
1240
+ */
1241
+ stopOnSpecFailure: false,
1031
1242
  /**
1032
1243
  * Whether to fail the spec if it ran no expectations. By default
1033
1244
  * a spec that ran no expectations is reported as passed. Setting this
@@ -1044,14 +1255,30 @@ getJasmineRequireObj().Env = function(j$) {
1044
1255
  * @since 3.3.0
1045
1256
  * @type Boolean
1046
1257
  * @default false
1258
+ * @deprecated Use the `stopSpecOnExpectationFailure` config property instead.
1047
1259
  */
1048
1260
  oneFailurePerSpec: false,
1261
+ /**
1262
+ * Whether to cause specs to only have one expectation failure.
1263
+ * @name Configuration#stopSpecOnExpectationFailure
1264
+ * @since 3.3.0
1265
+ * @type Boolean
1266
+ * @default false
1267
+ */
1268
+ stopSpecOnExpectationFailure: false,
1269
+ /**
1270
+ * A function that takes a spec and returns true if it should be executed
1271
+ * or false if it should be skipped.
1272
+ * @callback SpecFilter
1273
+ * @param {Spec} spec - The spec that the filter is being applied to.
1274
+ * @return boolean
1275
+ */
1049
1276
  /**
1050
1277
  * Function to use to filter specs
1051
1278
  * @name Configuration#specFilter
1052
1279
  * @since 3.3.0
1053
- * @type function
1054
- * @default true
1280
+ * @type SpecFilter
1281
+ * @default A function that always returns true.
1055
1282
  */
1056
1283
  specFilter: function() {
1057
1284
  return true;
@@ -1073,8 +1300,31 @@ getJasmineRequireObj().Env = function(j$) {
1073
1300
  * @since 3.5.0
1074
1301
  * @type function
1075
1302
  * @default undefined
1303
+ * @deprecated In a future version, Jasmine will ignore the Promise config
1304
+ * property and always create native promises instead.
1305
+ */
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
1076
1326
  */
1077
- Promise: undefined
1327
+ verboseDeprecations: false
1078
1328
  };
1079
1329
 
1080
1330
  var currentSuite = function() {
@@ -1124,33 +1374,89 @@ getJasmineRequireObj().Env = function(j$) {
1124
1374
  * @function
1125
1375
  */
1126
1376
  this.configure = function(configuration) {
1127
- if (configuration.specFilter) {
1128
- config.specFilter = configuration.specFilter;
1129
- }
1377
+ var booleanProps = [
1378
+ 'random',
1379
+ 'failSpecWithNoExpectations',
1380
+ 'hideDisabled',
1381
+ 'autoCleanClosures'
1382
+ ];
1383
+
1384
+ booleanProps.forEach(function(prop) {
1385
+ if (typeof configuration[prop] !== 'undefined') {
1386
+ config[prop] = !!configuration[prop];
1387
+ }
1388
+ });
1130
1389
 
1131
- if (configuration.hasOwnProperty('random')) {
1132
- config.random = !!configuration.random;
1133
- }
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
+ }
1134
1402
 
1135
- if (configuration.hasOwnProperty('seed')) {
1136
- config.seed = configuration.seed;
1137
- }
1403
+ if (typeof configuration.stopOnSpecFailure !== 'undefined') {
1404
+ if (configuration.stopOnSpecFailure !== configuration.failFast) {
1405
+ throw new Error(
1406
+ 'stopOnSpecFailure and failFast are aliases for ' +
1407
+ "each other. Don't set failFast if you also set stopOnSpecFailure."
1408
+ );
1409
+ }
1410
+ }
1138
1411
 
1139
- if (configuration.hasOwnProperty('failFast')) {
1140
1412
  config.failFast = configuration.failFast;
1141
- }
1413
+ config.stopOnSpecFailure = configuration.failFast;
1414
+ } else if (typeof configuration.stopOnSpecFailure !== 'undefined') {
1415
+ config.failFast = configuration.stopOnSpecFailure;
1416
+ config.stopOnSpecFailure = configuration.stopOnSpecFailure;
1417
+ }
1418
+
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
+ }
1142
1431
 
1143
- if (configuration.hasOwnProperty('failSpecWithNoExpectations')) {
1144
- config.failSpecWithNoExpectations =
1145
- configuration.failSpecWithNoExpectations;
1146
- }
1432
+ if (typeof configuration.stopSpecOnExpectationFailure !== 'undefined') {
1433
+ if (
1434
+ configuration.stopSpecOnExpectationFailure !==
1435
+ configuration.oneFailurePerSpec
1436
+ ) {
1437
+ throw new Error(
1438
+ 'stopSpecOnExpectationFailure and oneFailurePerSpec are aliases for ' +
1439
+ "each other. Don't set oneFailurePerSpec if you also set stopSpecOnExpectationFailure."
1440
+ );
1441
+ }
1442
+ }
1147
1443
 
1148
- if (configuration.hasOwnProperty('oneFailurePerSpec')) {
1149
1444
  config.oneFailurePerSpec = configuration.oneFailurePerSpec;
1445
+ config.stopSpecOnExpectationFailure = configuration.oneFailurePerSpec;
1446
+ } else if (
1447
+ typeof configuration.stopSpecOnExpectationFailure !== 'undefined'
1448
+ ) {
1449
+ config.oneFailurePerSpec = configuration.stopSpecOnExpectationFailure;
1450
+ config.stopSpecOnExpectationFailure =
1451
+ configuration.stopSpecOnExpectationFailure;
1452
+ }
1453
+
1454
+ if (configuration.specFilter) {
1455
+ config.specFilter = configuration.specFilter;
1150
1456
  }
1151
1457
 
1152
- if (configuration.hasOwnProperty('hideDisabled')) {
1153
- config.hideDisabled = configuration.hideDisabled;
1458
+ if (typeof configuration.seed !== 'undefined') {
1459
+ config.seed = configuration.seed;
1154
1460
  }
1155
1461
 
1156
1462
  // Don't use hasOwnProperty to check for Promise existence because Promise
@@ -1162,12 +1468,22 @@ getJasmineRequireObj().Env = function(j$) {
1162
1468
  typeof configuration.Promise.reject === 'function'
1163
1469
  ) {
1164
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
+ );
1165
1476
  } else {
1166
1477
  throw new Error(
1167
1478
  'Custom promise library missing `resolve`/`reject` functions'
1168
1479
  );
1169
1480
  }
1170
1481
  }
1482
+
1483
+ if (configuration.hasOwnProperty('verboseDeprecations')) {
1484
+ config.verboseDeprecations = configuration.verboseDeprecations;
1485
+ deprecator.verboseDeprecations(config.verboseDeprecations);
1486
+ }
1171
1487
  };
1172
1488
 
1173
1489
  /**
@@ -1188,13 +1504,19 @@ getJasmineRequireObj().Env = function(j$) {
1188
1504
  Object.defineProperty(this, 'specFilter', {
1189
1505
  get: function() {
1190
1506
  self.deprecated(
1191
- '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 }
1192
1511
  );
1193
1512
  return config.specFilter;
1194
1513
  },
1195
1514
  set: function(val) {
1196
1515
  self.deprecated(
1197
- '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 }
1198
1520
  );
1199
1521
  config.specFilter = val;
1200
1522
  }
@@ -1241,6 +1563,17 @@ getJasmineRequireObj().Env = function(j$) {
1241
1563
  runnableResources[currentRunnable().id].customMatchers;
1242
1564
 
1243
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
+
1244
1577
  customMatchers[matcherName] = matchersToAdd[matcherName];
1245
1578
  }
1246
1579
  };
@@ -1255,6 +1588,17 @@ getJasmineRequireObj().Env = function(j$) {
1255
1588
  runnableResources[currentRunnable().id].customAsyncMatchers;
1256
1589
 
1257
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
+
1258
1602
  customAsyncMatchers[matcherName] = matchersToAdd[matcherName];
1259
1603
  }
1260
1604
  };
@@ -1337,7 +1681,9 @@ getJasmineRequireObj().Env = function(j$) {
1337
1681
  }
1338
1682
 
1339
1683
  delayedExpectationResult.message +=
1340
- '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()?';
1341
1687
 
1342
1688
  topSuite.result.failedExpectations.push(delayedExpectationResult);
1343
1689
  }
@@ -1402,10 +1748,11 @@ getJasmineRequireObj().Env = function(j$) {
1402
1748
  delete runnableResources[id];
1403
1749
  };
1404
1750
 
1405
- var beforeAndAfterFns = function(suite) {
1751
+ var beforeAndAfterFns = function(targetSuite) {
1406
1752
  return function() {
1407
1753
  var befores = [],
1408
- afters = [];
1754
+ afters = [],
1755
+ suite = targetSuite;
1409
1756
 
1410
1757
  while (suite) {
1411
1758
  befores = befores.concat(suite.beforeFns);
@@ -1448,18 +1795,24 @@ getJasmineRequireObj().Env = function(j$) {
1448
1795
  * @since 2.3.0
1449
1796
  * @function
1450
1797
  * @param {Boolean} value Whether to throw when a expectation fails
1451
- * @deprecated Use the `oneFailurePerSpec` option with {@link Env#configure}
1798
+ * @deprecated Use the `stopSpecOnExpectationFailure` option with {@link Env#configure}
1452
1799
  */
1453
1800
  this.throwOnExpectationFailure = function(value) {
1454
1801
  this.deprecated(
1455
- 'Setting throwOnExpectationFailure directly on Env is deprecated and will be removed in a future version of Jasmine, please use the oneFailurePerSpec option in `configure`'
1802
+ 'Setting throwOnExpectationFailure directly on Env is deprecated and ' +
1803
+ 'will be removed in a future version of Jasmine. Please use the ' +
1804
+ 'stopSpecOnExpectationFailure option in `configure`.',
1805
+ { ignoreRunnable: true }
1456
1806
  );
1457
1807
  this.configure({ oneFailurePerSpec: !!value });
1458
1808
  };
1459
1809
 
1460
1810
  this.throwingExpectationFailures = function() {
1461
1811
  this.deprecated(
1462
- 'Getting throwingExpectationFailures directly from Env is deprecated and will be removed in a future version of Jasmine, please check the oneFailurePerSpec option from `configuration`'
1812
+ 'Getting throwingExpectationFailures directly from Env is deprecated ' +
1813
+ 'and will be removed in a future version of Jasmine. Please check ' +
1814
+ 'the stopSpecOnExpectationFailure option from `configuration`.',
1815
+ { ignoreRunnable: true }
1463
1816
  );
1464
1817
  return config.oneFailurePerSpec;
1465
1818
  };
@@ -1470,18 +1823,24 @@ getJasmineRequireObj().Env = function(j$) {
1470
1823
  * @since 2.7.0
1471
1824
  * @function
1472
1825
  * @param {Boolean} value Whether to stop suite execution when a spec fails
1473
- * @deprecated Use the `failFast` option with {@link Env#configure}
1826
+ * @deprecated Use the `stopOnSpecFailure` option with {@link Env#configure}
1474
1827
  */
1475
1828
  this.stopOnSpecFailure = function(value) {
1476
1829
  this.deprecated(
1477
- 'Setting stopOnSpecFailure directly is deprecated and will be removed in a future version of Jasmine, please use the failFast option in `configure`'
1830
+ 'Setting stopOnSpecFailure directly is deprecated and will be ' +
1831
+ 'removed in a future version of Jasmine. Please use the ' +
1832
+ 'stopOnSpecFailure option in `configure`.',
1833
+ { ignoreRunnable: true }
1478
1834
  );
1479
- this.configure({ failFast: !!value });
1835
+ this.configure({ stopOnSpecFailure: !!value });
1480
1836
  };
1481
1837
 
1482
1838
  this.stoppingOnSpecFailure = function() {
1483
1839
  this.deprecated(
1484
- 'Getting stoppingOnSpecFailure directly from Env is deprecated and will be removed in a future version of Jasmine, please check the failFast option from `configuration`'
1840
+ 'Getting stoppingOnSpecFailure directly from Env is deprecated and ' +
1841
+ 'will be removed in a future version of Jasmine. Please check the ' +
1842
+ 'stopOnSpecFailure option from `configuration`.',
1843
+ { ignoreRunnable: true }
1485
1844
  );
1486
1845
  return config.failFast;
1487
1846
  };
@@ -1496,14 +1855,20 @@ getJasmineRequireObj().Env = function(j$) {
1496
1855
  */
1497
1856
  this.randomizeTests = function(value) {
1498
1857
  this.deprecated(
1499
- '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 }
1500
1862
  );
1501
1863
  config.random = !!value;
1502
1864
  };
1503
1865
 
1504
1866
  this.randomTests = function() {
1505
1867
  this.deprecated(
1506
- '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 }
1507
1872
  );
1508
1873
  return config.random;
1509
1874
  };
@@ -1518,7 +1883,10 @@ getJasmineRequireObj().Env = function(j$) {
1518
1883
  */
1519
1884
  this.seed = function(value) {
1520
1885
  this.deprecated(
1521
- '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 }
1522
1890
  );
1523
1891
  if (value) {
1524
1892
  config.seed = value;
@@ -1528,7 +1896,10 @@ getJasmineRequireObj().Env = function(j$) {
1528
1896
 
1529
1897
  this.hidingDisabled = function(value) {
1530
1898
  this.deprecated(
1531
- '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 }
1532
1903
  );
1533
1904
  return config.hideDisabled;
1534
1905
  };
@@ -1537,41 +1908,51 @@ getJasmineRequireObj().Env = function(j$) {
1537
1908
  * @name Env#hideDisabled
1538
1909
  * @since 3.2.0
1539
1910
  * @function
1911
+ * @deprecated Use the `hideDisabled` option with {@link Env#configure}
1540
1912
  */
1541
1913
  this.hideDisabled = function(value) {
1542
1914
  this.deprecated(
1543
- '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 }
1544
1919
  );
1545
1920
  config.hideDisabled = !!value;
1546
1921
  };
1547
1922
 
1548
- 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) {
1549
1946
  var runnable = currentRunnable() || topSuite;
1550
- var context;
1551
-
1552
- if (runnable === topSuite) {
1553
- context = '';
1554
- } else if (runnable === currentSuite()) {
1555
- context = ' (in suite: ' + runnable.getFullName() + ')';
1556
- } else {
1557
- context = ' (in spec: ' + runnable.getFullName() + ')';
1558
- }
1559
-
1560
- runnable.addDeprecationWarning(deprecation);
1561
- if (
1562
- typeof console !== 'undefined' &&
1563
- typeof console.error === 'function'
1564
- ) {
1565
- console.error('DEPRECATION: ' + deprecation + context);
1566
- }
1947
+ deprecator.addDeprecationWarning(runnable, deprecation, options);
1567
1948
  };
1568
1949
 
1569
1950
  var queueRunnerFactory = function(options, args) {
1570
1951
  var failFast = false;
1571
1952
  if (options.isLeaf) {
1572
- failFast = config.oneFailurePerSpec;
1953
+ failFast = config.stopSpecOnExpectationFailure;
1573
1954
  } else if (!options.isReporter) {
1574
- failFast = config.failFast;
1955
+ failFast = config.stopOnSpecFailure;
1575
1956
  }
1576
1957
  options.clearStack = options.clearStack || clearStack;
1577
1958
  options.timeout = {
@@ -1597,13 +1978,22 @@ getJasmineRequireObj().Env = function(j$) {
1597
1978
  description: 'Jasmine__TopLevel__Suite',
1598
1979
  expectationFactory: expectationFactory,
1599
1980
  asyncExpectationFactory: suiteAsyncExpectationFactory,
1600
- expectationResultFactory: expectationResultFactory
1981
+ expectationResultFactory: expectationResultFactory,
1982
+ autoCleanClosures: config.autoCleanClosures
1601
1983
  });
1602
- defaultResourcesForRunnable(topSuite.id);
1984
+ var deprecator = new j$.Deprecator(topSuite);
1603
1985
  currentDeclarationSuite = topSuite;
1604
1986
 
1987
+ /**
1988
+ * Provides the root suite, through which all suites and specs can be
1989
+ * accessed.
1990
+ * @function
1991
+ * @name Env#topSuite
1992
+ * @return {Suite} the root suite
1993
+ * @since 2.0.0
1994
+ */
1605
1995
  this.topSuite = function() {
1606
- return topSuite;
1996
+ return j$.deprecatingSuiteProxy(topSuite, null, this);
1607
1997
  };
1608
1998
 
1609
1999
  /**
@@ -1678,11 +2068,43 @@ getJasmineRequireObj().Env = function(j$) {
1678
2068
  */
1679
2069
  'specDone'
1680
2070
  ],
1681
- queueRunnerFactory
2071
+ queueRunnerFactory,
2072
+ self.deprecated
1682
2073
  );
1683
2074
 
1684
- // Both params are optional.
2075
+ /**
2076
+ * Executes the specs.
2077
+ *
2078
+ * If called with no parameters or with a falsy value as the first parameter,
2079
+ * all specs will be executed except those that are excluded by a
2080
+ * [spec filter]{@link Configuration#specFilter} or other mechanism. If the
2081
+ * first parameter is a list of spec/suite IDs, only those specs/suites will
2082
+ * be run.
2083
+ *
2084
+ * Both parameters are optional, but a completion callback is only valid as
2085
+ * the second parameter. To specify a completion callback but not a list of
2086
+ * specs/suites to run, pass null or undefined as the first parameter.
2087
+ *
2088
+ * execute should not be called more than once.
2089
+ *
2090
+ * If the environment supports promises, execute will return a promise that
2091
+ * is resolved after the suite finishes executing. The promise will be
2092
+ * resolved (not rejected) as long as the suite runs to completion. Use a
2093
+ * {@link Reporter} to determine whether or not the suite passed.
2094
+ *
2095
+ * @name Env#execute
2096
+ * @since 2.0.0
2097
+ * @function
2098
+ * @param {(string[])=} runnablesToRun IDs of suites and/or specs to run
2099
+ * @param {Function=} onComplete Function that will be called after all specs have run
2100
+ * @return {Promise<undefined>}
2101
+ */
1685
2102
  this.execute = function(runnablesToRun, onComplete) {
2103
+ if (this._executedBefore) {
2104
+ topSuite.reset();
2105
+ }
2106
+ this._executedBefore = true;
2107
+ defaultResourcesForRunnable(topSuite.id);
1686
2108
  installGlobalErrors();
1687
2109
 
1688
2110
  if (!runnablesToRun) {
@@ -1740,65 +2162,88 @@ getJasmineRequireObj().Env = function(j$) {
1740
2162
  var jasmineTimer = new j$.Timer();
1741
2163
  jasmineTimer.start();
1742
2164
 
1743
- /**
1744
- * Information passed to the {@link Reporter#jasmineStarted} event.
1745
- * @typedef JasmineStartedInfo
1746
- * @property {Int} totalSpecsDefined - The total number of specs defined in this suite.
1747
- * @property {Order} order - Information about the ordering (random or not) of this execution of the suite.
1748
- */
1749
- reporter.jasmineStarted(
1750
- {
1751
- totalSpecsDefined: totalSpecsDefined,
1752
- order: order
1753
- },
1754
- function() {
1755
- currentlyExecutingSuites.push(topSuite);
1756
-
1757
- processor.execute(function() {
1758
- clearResourcesForRunnable(topSuite.id);
1759
- currentlyExecutingSuites.pop();
1760
- var overallStatus, incompleteReason;
1761
-
1762
- if (hasFailures || topSuite.result.failedExpectations.length > 0) {
1763
- overallStatus = 'failed';
1764
- } else if (focusedRunnables.length > 0) {
1765
- overallStatus = 'incomplete';
1766
- incompleteReason = 'fit() or fdescribe() was found';
1767
- } else if (totalSpecsDefined === 0) {
1768
- overallStatus = 'incomplete';
1769
- incompleteReason = 'No specs found';
1770
- } else {
1771
- overallStatus = 'passed';
2165
+ var Promise = customPromise || global.Promise;
2166
+
2167
+ if (Promise) {
2168
+ return new Promise(function(resolve) {
2169
+ runAll(function() {
2170
+ if (onComplete) {
2171
+ onComplete();
1772
2172
  }
1773
2173
 
1774
- /**
1775
- * Information passed to the {@link Reporter#jasmineDone} event.
1776
- * @typedef JasmineDoneInfo
1777
- * @property {OverallStatus} overallStatus - The overall result of the suite: 'passed', 'failed', or 'incomplete'.
1778
- * @property {Int} totalTime - The total time (in ms) that it took to execute the suite
1779
- * @property {IncompleteReason} incompleteReason - Explanation of why the suite was incomplete.
1780
- * @property {Order} order - Information about the ordering (random or not) of this execution of the suite.
1781
- * @property {Expectation[]} failedExpectations - List of expectations that failed in an {@link afterAll} at the global level.
1782
- * @property {Expectation[]} deprecationWarnings - List of deprecation warnings that occurred at the global level.
1783
- */
1784
- reporter.jasmineDone(
1785
- {
1786
- overallStatus: overallStatus,
1787
- totalTime: jasmineTimer.elapsed(),
1788
- incompleteReason: incompleteReason,
1789
- order: order,
1790
- failedExpectations: topSuite.result.failedExpectations,
1791
- deprecationWarnings: topSuite.result.deprecationWarnings
1792
- },
1793
- function() {
1794
- if (onComplete) {
1795
- onComplete();
1796
- }
1797
- }
1798
- );
2174
+ resolve();
1799
2175
  });
1800
- }
1801
- );
2176
+ });
2177
+ } else {
2178
+ runAll(function() {
2179
+ if (onComplete) {
2180
+ onComplete();
2181
+ }
2182
+ });
2183
+ }
2184
+
2185
+ function runAll(done) {
2186
+ /**
2187
+ * Information passed to the {@link Reporter#jasmineStarted} event.
2188
+ * @typedef JasmineStartedInfo
2189
+ * @property {Int} totalSpecsDefined - The total number of specs defined in this suite.
2190
+ * @property {Order} order - Information about the ordering (random or not) of this execution of the suite.
2191
+ * @since 2.0.0
2192
+ */
2193
+ reporter.jasmineStarted(
2194
+ {
2195
+ totalSpecsDefined: totalSpecsDefined,
2196
+ order: order
2197
+ },
2198
+ function() {
2199
+ currentlyExecutingSuites.push(topSuite);
2200
+
2201
+ processor.execute(function() {
2202
+ clearResourcesForRunnable(topSuite.id);
2203
+ currentlyExecutingSuites.pop();
2204
+ var overallStatus, incompleteReason;
2205
+
2206
+ if (
2207
+ hasFailures ||
2208
+ topSuite.result.failedExpectations.length > 0
2209
+ ) {
2210
+ overallStatus = 'failed';
2211
+ } else if (focusedRunnables.length > 0) {
2212
+ overallStatus = 'incomplete';
2213
+ incompleteReason = 'fit() or fdescribe() was found';
2214
+ } else if (totalSpecsDefined === 0) {
2215
+ overallStatus = 'incomplete';
2216
+ incompleteReason = 'No specs found';
2217
+ } else {
2218
+ overallStatus = 'passed';
2219
+ }
2220
+
2221
+ /**
2222
+ * Information passed to the {@link Reporter#jasmineDone} event.
2223
+ * @typedef JasmineDoneInfo
2224
+ * @property {OverallStatus} overallStatus - The overall result of the suite: 'passed', 'failed', or 'incomplete'.
2225
+ * @property {Int} totalTime - The total time (in ms) that it took to execute the suite
2226
+ * @property {IncompleteReason} incompleteReason - Explanation of why the suite was incomplete.
2227
+ * @property {Order} order - Information about the ordering (random or not) of this execution of the suite.
2228
+ * @property {Expectation[]} failedExpectations - List of expectations that failed in an {@link afterAll} at the global level.
2229
+ * @property {Expectation[]} deprecationWarnings - List of deprecation warnings that occurred at the global level.
2230
+ * @since 2.4.0
2231
+ */
2232
+ reporter.jasmineDone(
2233
+ {
2234
+ overallStatus: overallStatus,
2235
+ totalTime: jasmineTimer.elapsed(),
2236
+ incompleteReason: incompleteReason,
2237
+ order: order,
2238
+ failedExpectations: topSuite.result.failedExpectations,
2239
+ deprecationWarnings: topSuite.result.deprecationWarnings
2240
+ },
2241
+ done
2242
+ );
2243
+ });
2244
+ }
2245
+ );
2246
+ }
1802
2247
  };
1803
2248
 
1804
2249
  /**
@@ -1873,6 +2318,15 @@ getJasmineRequireObj().Env = function(j$) {
1873
2318
  }
1874
2319
  });
1875
2320
 
2321
+ /**
2322
+ * Configures whether Jasmine should allow the same function to be spied on
2323
+ * more than once during the execution of a spec. By default, spying on
2324
+ * a function that is already a spy will cause an error.
2325
+ * @name Env#allowRespy
2326
+ * @function
2327
+ * @since 2.5.0
2328
+ * @param {boolean} allow Whether to allow respying
2329
+ */
1876
2330
  this.allowRespy = function(allow) {
1877
2331
  spyRegistry.allowRespy(allow);
1878
2332
  };
@@ -1937,7 +2391,8 @@ getJasmineRequireObj().Env = function(j$) {
1937
2391
  expectationFactory: expectationFactory,
1938
2392
  asyncExpectationFactory: suiteAsyncExpectationFactory,
1939
2393
  expectationResultFactory: expectationResultFactory,
1940
- throwOnExpectationFailure: config.oneFailurePerSpec
2394
+ throwOnExpectationFailure: config.oneFailurePerSpec,
2395
+ autoCleanClosures: config.autoCleanClosures
1941
2396
  });
1942
2397
 
1943
2398
  return suite;
@@ -1950,20 +2405,27 @@ getJasmineRequireObj().Env = function(j$) {
1950
2405
  if (specDefinitions.length > 0) {
1951
2406
  throw new Error('describe does not expect any arguments');
1952
2407
  }
1953
- if (currentDeclarationSuite.markedPending) {
1954
- suite.pend();
2408
+ if (currentDeclarationSuite.markedExcluding) {
2409
+ suite.exclude();
1955
2410
  }
1956
2411
  addSpecsToSuite(suite, specDefinitions);
1957
- 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);
1958
2420
  };
1959
2421
 
1960
2422
  this.xdescribe = function(description, specDefinitions) {
1961
2423
  ensureIsNotNested('xdescribe');
1962
2424
  ensureIsFunction(specDefinitions, 'xdescribe');
1963
2425
  var suite = suiteFactory(description);
1964
- suite.pend();
2426
+ suite.exclude();
1965
2427
  addSpecsToSuite(suite, specDefinitions);
1966
- return suite;
2428
+ return j$.deprecatingSuiteProxy(suite, suite.parentSuite, this);
1967
2429
  };
1968
2430
 
1969
2431
  var focusedRunnables = [];
@@ -1978,7 +2440,7 @@ getJasmineRequireObj().Env = function(j$) {
1978
2440
  unfocusAncestor();
1979
2441
  addSpecsToSuite(suite, specDefinitions);
1980
2442
 
1981
- return suite;
2443
+ return j$.deprecatingSuiteProxy(suite, suite.parentSuite, this);
1982
2444
  };
1983
2445
 
1984
2446
  function addSpecsToSuite(suite, specDefinitions) {
@@ -1988,7 +2450,7 @@ getJasmineRequireObj().Env = function(j$) {
1988
2450
 
1989
2451
  var declarationError = null;
1990
2452
  try {
1991
- specDefinitions.call(suite);
2453
+ specDefinitions.call(j$.deprecatingThisProxy(suite, self));
1992
2454
  } catch (e) {
1993
2455
  declarationError = e;
1994
2456
  }
@@ -2030,6 +2492,7 @@ getJasmineRequireObj().Env = function(j$) {
2030
2492
  beforeAndAfterFns: beforeAndAfterFns(suite),
2031
2493
  expectationFactory: expectationFactory,
2032
2494
  asyncExpectationFactory: specAsyncExpectationFactory,
2495
+ deprecated: self.deprecated,
2033
2496
  resultCallback: specResultCallback,
2034
2497
  getSpecName: function(spec) {
2035
2498
  return getSpecName(spec, suite);
@@ -2046,6 +2509,7 @@ getJasmineRequireObj().Env = function(j$) {
2046
2509
  timeout: timeout || 0
2047
2510
  },
2048
2511
  throwOnExpectationFailure: config.oneFailurePerSpec,
2512
+ autoCleanClosures: config.autoCleanClosures,
2049
2513
  timer: new j$.Timer()
2050
2514
  });
2051
2515
  return spec;
@@ -2068,21 +2532,32 @@ getJasmineRequireObj().Env = function(j$) {
2068
2532
  }
2069
2533
  };
2070
2534
 
2071
- this.it = function(description, fn, timeout) {
2535
+ this.it_ = function(description, fn, timeout) {
2072
2536
  ensureIsNotNested('it');
2073
2537
  // it() sometimes doesn't have a fn argument, so only check the type if
2074
2538
  // it's given.
2075
2539
  if (arguments.length > 1 && typeof fn !== 'undefined') {
2076
2540
  ensureIsFunctionOrAsync(fn, 'it');
2077
2541
  }
2542
+
2543
+ if (timeout) {
2544
+ j$.util.validateTimeout(timeout);
2545
+ }
2546
+
2078
2547
  var spec = specFactory(description, fn, currentDeclarationSuite, timeout);
2079
- if (currentDeclarationSuite.markedPending) {
2080
- spec.pend();
2548
+ if (currentDeclarationSuite.markedExcluding) {
2549
+ spec.exclude();
2081
2550
  }
2082
2551
  currentDeclarationSuite.addChild(spec);
2552
+
2083
2553
  return spec;
2084
2554
  };
2085
2555
 
2556
+ this.it = function(description, fn, timeout) {
2557
+ var spec = this.it_(description, fn, timeout);
2558
+ return j$.deprecatingSpecProxy(spec, this);
2559
+ };
2560
+
2086
2561
  this.xit = function(description, fn, timeout) {
2087
2562
  ensureIsNotNested('xit');
2088
2563
  // xit(), like it(), doesn't always have a fn argument, so only check the
@@ -2090,19 +2565,23 @@ getJasmineRequireObj().Env = function(j$) {
2090
2565
  if (arguments.length > 1 && typeof fn !== 'undefined') {
2091
2566
  ensureIsFunctionOrAsync(fn, 'xit');
2092
2567
  }
2093
- var spec = this.it.apply(this, arguments);
2094
- spec.pend('Temporarily disabled with xit');
2095
- return spec;
2568
+ var spec = this.it_.apply(this, arguments);
2569
+ spec.exclude('Temporarily disabled with xit');
2570
+ return j$.deprecatingSpecProxy(spec, this);
2096
2571
  };
2097
2572
 
2098
2573
  this.fit = function(description, fn, timeout) {
2099
2574
  ensureIsNotNested('fit');
2100
2575
  ensureIsFunctionOrAsync(fn, 'fit');
2576
+
2577
+ if (timeout) {
2578
+ j$.util.validateTimeout(timeout);
2579
+ }
2101
2580
  var spec = specFactory(description, fn, currentDeclarationSuite, timeout);
2102
2581
  currentDeclarationSuite.addChild(spec);
2103
2582
  focusedRunnables.push(spec.id);
2104
2583
  unfocusAncestor();
2105
- return spec;
2584
+ return j$.deprecatingSpecProxy(spec, this);
2106
2585
  };
2107
2586
 
2108
2587
  /**
@@ -2162,6 +2641,11 @@ getJasmineRequireObj().Env = function(j$) {
2162
2641
  this.beforeEach = function(beforeEachFunction, timeout) {
2163
2642
  ensureIsNotNested('beforeEach');
2164
2643
  ensureIsFunctionOrAsync(beforeEachFunction, 'beforeEach');
2644
+
2645
+ if (timeout) {
2646
+ j$.util.validateTimeout(timeout);
2647
+ }
2648
+
2165
2649
  currentDeclarationSuite.beforeEach({
2166
2650
  fn: beforeEachFunction,
2167
2651
  timeout: timeout || 0
@@ -2171,6 +2655,11 @@ getJasmineRequireObj().Env = function(j$) {
2171
2655
  this.beforeAll = function(beforeAllFunction, timeout) {
2172
2656
  ensureIsNotNested('beforeAll');
2173
2657
  ensureIsFunctionOrAsync(beforeAllFunction, 'beforeAll');
2658
+
2659
+ if (timeout) {
2660
+ j$.util.validateTimeout(timeout);
2661
+ }
2662
+
2174
2663
  currentDeclarationSuite.beforeAll({
2175
2664
  fn: beforeAllFunction,
2176
2665
  timeout: timeout || 0
@@ -2180,6 +2669,11 @@ getJasmineRequireObj().Env = function(j$) {
2180
2669
  this.afterEach = function(afterEachFunction, timeout) {
2181
2670
  ensureIsNotNested('afterEach');
2182
2671
  ensureIsFunctionOrAsync(afterEachFunction, 'afterEach');
2672
+
2673
+ if (timeout) {
2674
+ j$.util.validateTimeout(timeout);
2675
+ }
2676
+
2183
2677
  afterEachFunction.isCleanup = true;
2184
2678
  currentDeclarationSuite.afterEach({
2185
2679
  fn: afterEachFunction,
@@ -2190,6 +2684,11 @@ getJasmineRequireObj().Env = function(j$) {
2190
2684
  this.afterAll = function(afterAllFunction, timeout) {
2191
2685
  ensureIsNotNested('afterAll');
2192
2686
  ensureIsFunctionOrAsync(afterAllFunction, 'afterAll');
2687
+
2688
+ if (timeout) {
2689
+ j$.util.validateTimeout(timeout);
2690
+ }
2691
+
2193
2692
  currentDeclarationSuite.afterAll({
2194
2693
  fn: afterAllFunction,
2195
2694
  timeout: timeout || 0
@@ -2450,7 +2949,7 @@ getJasmineRequireObj().ArrayContaining = function(j$) {
2450
2949
  if (!j$.isArray_(this.sample)) {
2451
2950
  throw new Error(
2452
2951
  'You must provide an array to arrayContaining, not ' +
2453
- j$.pp(this.sample) +
2952
+ j$.basicPrettyPrinter_(this.sample) +
2454
2953
  '.'
2455
2954
  );
2456
2955
  }
@@ -2491,7 +2990,7 @@ getJasmineRequireObj().ArrayWithExactContents = function(j$) {
2491
2990
  if (!j$.isArray_(this.sample)) {
2492
2991
  throw new Error(
2493
2992
  'You must provide an array to arrayWithExactContents, not ' +
2494
- j$.pp(this.sample) +
2993
+ j$.basicPrettyPrinter_(this.sample) +
2495
2994
  '.'
2496
2995
  );
2497
2996
  }
@@ -2560,7 +3059,8 @@ getJasmineRequireObj().MapContaining = function(j$) {
2560
3059
  function MapContaining(sample) {
2561
3060
  if (!j$.isMap(sample)) {
2562
3061
  throw new Error(
2563
- 'You must provide a map to `mapContaining`, not ' + j$.pp(sample)
3062
+ 'You must provide a map to `mapContaining`, not ' +
3063
+ j$.basicPrettyPrinter_(sample)
2564
3064
  );
2565
3065
  }
2566
3066
 
@@ -2711,7 +3211,8 @@ getJasmineRequireObj().SetContaining = function(j$) {
2711
3211
  function SetContaining(sample) {
2712
3212
  if (!j$.isSet(sample)) {
2713
3213
  throw new Error(
2714
- 'You must provide a set to `setContaining`, not ' + j$.pp(sample)
3214
+ 'You must provide a set to `setContaining`, not ' +
3215
+ j$.basicPrettyPrinter_(sample)
2715
3216
  );
2716
3217
  }
2717
3218
 
@@ -2749,6 +3250,31 @@ getJasmineRequireObj().SetContaining = function(j$) {
2749
3250
  return SetContaining;
2750
3251
  };
2751
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
+
2752
3278
  getJasmineRequireObj().StringMatching = function(j$) {
2753
3279
  function StringMatching(expected) {
2754
3280
  if (!j$.isString_(expected) && !j$.isA_('RegExp', expected)) {
@@ -2836,34 +3362,49 @@ getJasmineRequireObj().asymmetricEqualityTesterArgCompatShim = function(j$) {
2836
3362
  matchersUtil,
2837
3363
  customEqualityTesters
2838
3364
  ) {
2839
- var self = Object.create(matchersUtil),
2840
- props,
2841
- i,
2842
- k;
3365
+ var self = Object.create(matchersUtil);
2843
3366
 
2844
- copy(self, customEqualityTesters, 'length');
3367
+ copyAndDeprecate(self, customEqualityTesters, 'length');
2845
3368
 
2846
3369
  for (i = 0; i < customEqualityTesters.length; i++) {
2847
- copy(self, customEqualityTesters, i);
3370
+ copyAndDeprecate(self, customEqualityTesters, i);
2848
3371
  }
2849
3372
 
2850
- var props = arrayProps();
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);
3377
+ }
3378
+
3379
+ self.isAsymmetricEqualityTesterArgCompatShim_ = true;
3380
+ return self;
3381
+ }
3382
+
3383
+ function copyAndDeprecateArrayMethods(dest) {
3384
+ var props = arrayProps(),
3385
+ i,
3386
+ k;
2851
3387
 
2852
3388
  for (i = 0; i < props.length; i++) {
2853
3389
  k = props[i];
3390
+
2854
3391
  // Skip length (dealt with above), and anything that collides with
2855
3392
  // MatchesUtil e.g. an Array.prototype.contains method added by user code
2856
- if (k !== 'length' && !self[k]) {
2857
- copy(self, Array.prototype, k);
3393
+ if (k !== 'length' && !dest[k]) {
3394
+ copyAndDeprecate(dest, Array.prototype, k);
2858
3395
  }
2859
3396
  }
2860
-
2861
- return self;
2862
3397
  }
2863
3398
 
2864
- function copy(dest, src, propName) {
3399
+ function copyAndDeprecate(dest, src, propName) {
2865
3400
  Object.defineProperty(dest, propName, {
2866
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
+ );
2867
3408
  return src[propName];
2868
3409
  }
2869
3410
  });
@@ -2942,6 +3483,19 @@ getJasmineRequireObj().CallTracker = function(j$) {
2942
3483
  return call ? call.args : [];
2943
3484
  };
2944
3485
 
3486
+ /**
3487
+ * Get the "this" object that was passed to a specific invocation of this spy.
3488
+ * @name Spy#calls#thisFor
3489
+ * @since 3.8.0
3490
+ * @function
3491
+ * @param {Integer} index The 0-based invocation index.
3492
+ * @return {Object?}
3493
+ */
3494
+ this.thisFor = function(index) {
3495
+ var call = calls[index];
3496
+ return call ? call.object : undefined;
3497
+ };
3498
+
2945
3499
  /**
2946
3500
  * Get the raw calls array for this spy.
2947
3501
  * @name Spy#calls#all
@@ -3093,9 +3647,12 @@ getJasmineRequireObj().Clock = function() {
3093
3647
  typeof process.versions.node === 'string';
3094
3648
 
3095
3649
  /**
3096
- * _Note:_ Do not construct this directly, Jasmine will make one during booting. You can get the current clock with {@link jasmine.clock}.
3097
3650
  * @class Clock
3098
- * @classdesc Jasmine's mock clock is used when testing time dependent code.
3651
+ * @since 1.3.0
3652
+ * @classdesc Jasmine's mock clock is used when testing time dependent code.<br>
3653
+ * _Note:_ Do not construct this directly. You can get the current clock with
3654
+ * {@link jasmine.clock}.
3655
+ * @hideconstructor
3099
3656
  */
3100
3657
  function Clock(global, delayedFunctionSchedulerFactory, mockDate) {
3101
3658
  var self = this,
@@ -3322,13 +3879,31 @@ getJasmineRequireObj().DelayedFunctionScheduler = function(j$) {
3322
3879
  var currentTime = 0;
3323
3880
  var delayedFnCount = 0;
3324
3881
  var deletedKeys = [];
3882
+ var ticking = false;
3325
3883
 
3326
3884
  self.tick = function(millis, tickDate) {
3327
- millis = millis || 0;
3328
- 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;
3329
3897
 
3330
- runScheduledFunctions(endTime, tickDate);
3331
- currentTime = endTime;
3898
+ try {
3899
+ millis = millis || 0;
3900
+ var endTime = currentTime + millis;
3901
+
3902
+ runScheduledFunctions(endTime, tickDate);
3903
+ currentTime = endTime;
3904
+ } finally {
3905
+ ticking = false;
3906
+ }
3332
3907
  };
3333
3908
 
3334
3909
  self.scheduleFunction = function(
@@ -3455,42 +4030,338 @@ getJasmineRequireObj().DelayedFunctionScheduler = function(j$) {
3455
4030
  var newCurrentTime = scheduledLookup.shift();
3456
4031
  tickDate(newCurrentTime - currentTime);
3457
4032
 
3458
- currentTime = newCurrentTime;
4033
+ currentTime = newCurrentTime;
4034
+
4035
+ var funcsToRun = scheduledFunctions[currentTime];
4036
+
4037
+ delete scheduledFunctions[currentTime];
4038
+
4039
+ forEachFunction(funcsToRun, function(funcToRun) {
4040
+ if (funcToRun.recurring) {
4041
+ reschedule(funcToRun);
4042
+ }
4043
+ });
4044
+
4045
+ forEachFunction(funcsToRun, function(funcToRun) {
4046
+ if (j$.util.arrayContains(deletedKeys, funcToRun.timeoutKey)) {
4047
+ // skip a timeoutKey deleted whilst we were running
4048
+ return;
4049
+ }
4050
+ funcToRun.funcToCall.apply(null, funcToRun.params || []);
4051
+ });
4052
+ deletedKeys = [];
4053
+ } while (
4054
+ scheduledLookup.length > 0 &&
4055
+ // checking first if we're out of time prevents setTimeout(0)
4056
+ // scheduled in a funcToRun from forcing an extra iteration
4057
+ currentTime !== endTime &&
4058
+ scheduledLookup[0] <= endTime
4059
+ );
4060
+
4061
+ // ran out of functions to call, but still time left on the clock
4062
+ if (currentTime !== endTime) {
4063
+ tickDate(endTime - currentTime);
4064
+ }
4065
+ }
4066
+ }
4067
+
4068
+ return DelayedFunctionScheduler;
4069
+ };
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
+ }
3459
4331
 
3460
- var funcsToRun = scheduledFunctions[currentTime];
4332
+ if (!this.verbose_) {
4333
+ context += '\n' + verboseNote;
4334
+ }
3461
4335
 
3462
- delete scheduledFunctions[currentTime];
4336
+ console.error('DEPRECATION: ' + deprecation + context);
4337
+ };
3463
4338
 
3464
- forEachFunction(funcsToRun, function(funcToRun) {
3465
- if (funcToRun.recurring) {
3466
- reschedule(funcToRun);
3467
- }
3468
- });
4339
+ Deprecator.prototype.stackTrace_ = function() {
4340
+ var formatter = new j$.ExceptionFormatter();
4341
+ return formatter.stack(j$.util.errorWithStack()).replace(/^Error\n/m, '');
4342
+ };
3469
4343
 
3470
- forEachFunction(funcsToRun, function(funcToRun) {
3471
- if (j$.util.arrayContains(deletedKeys, funcToRun.timeoutKey)) {
3472
- // skip a timeoutKey deleted whilst we were running
3473
- return;
3474
- }
3475
- funcToRun.funcToCall.apply(null, funcToRun.params || []);
3476
- });
3477
- deletedKeys = [];
3478
- } while (
3479
- scheduledLookup.length > 0 &&
3480
- // checking first if we're out of time prevents setTimeout(0)
3481
- // scheduled in a funcToRun from forcing an extra iteration
3482
- currentTime !== endTime &&
3483
- scheduledLookup[0] <= endTime
3484
- );
4344
+ Deprecator.prototype.report_ = function(runnable, deprecation, options) {
4345
+ if (options.ignoreRunnable) {
4346
+ runnable = this.topSuite_;
4347
+ }
3485
4348
 
3486
- // ran out of functions to call, but still time left on the clock
3487
- if (currentTime !== endTime) {
3488
- tickDate(endTime - currentTime);
3489
- }
4349
+ if (j$.isError_(deprecation)) {
4350
+ runnable.addDeprecationWarning(deprecation);
4351
+ return;
3490
4352
  }
3491
- }
3492
4353
 
3493
- return DelayedFunctionScheduler;
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;
3494
4365
  };
3495
4366
 
3496
4367
  getJasmineRequireObj().errors = function() {
@@ -3596,7 +4467,7 @@ getJasmineRequireObj().ExceptionFormatter = function(j$) {
3596
4467
  }
3597
4468
 
3598
4469
  if (!empty) {
3599
- return 'error properties: ' + j$.pp(result) + '\n';
4470
+ return 'error properties: ' + j$.basicPrettyPrinter_(result) + '\n';
3600
4471
  }
3601
4472
 
3602
4473
  return '';
@@ -3651,7 +4522,35 @@ getJasmineRequireObj().Expectation = function(j$) {
3651
4522
  });
3652
4523
 
3653
4524
  /**
3654
- * Asynchronous matchers.
4525
+ * Asynchronous matchers that operate on an actual value which is a promise,
4526
+ * and return a promise.
4527
+ *
4528
+ * Most async matchers will wait indefinitely for the promise to be resolved
4529
+ * or rejected, resulting in a spec timeout if that never happens. If you
4530
+ * expect that the promise will already be resolved or rejected at the time
4531
+ * the matcher is called, you can use the {@link async-matchers#already}
4532
+ * modifier to get a faster failure with a more helpful message.
4533
+ *
4534
+ * Note: Specs must await the result of each async matcher, return the
4535
+ * promise returned by the matcher, or return a promise that's derived from
4536
+ * the one returned by the matcher. Otherwise the matcher will not be
4537
+ * evaluated before the spec completes.
4538
+ *
4539
+ * @example
4540
+ * // Good
4541
+ * await expectAsync(aPromise).toBeResolved();
4542
+ * @example
4543
+ * // Good
4544
+ * return expectAsync(aPromise).toBeResolved();
4545
+ * @example
4546
+ * // Good
4547
+ * return expectAsync(aPromise).toBeResolved()
4548
+ * .then(function() {
4549
+ * // more spec code
4550
+ * });
4551
+ * @example
4552
+ * // Bad
4553
+ * expectAsync(aPromise).toBeResolved();
3655
4554
  * @namespace async-matchers
3656
4555
  */
3657
4556
  function AsyncExpectation(options) {
@@ -3701,6 +4600,24 @@ getJasmineRequireObj().Expectation = function(j$) {
3701
4600
  }
3702
4601
  });
3703
4602
 
4603
+ /**
4604
+ * Fail as soon as possible if the actual is pending.
4605
+ * Otherwise evaluate the matcher.
4606
+ * @member
4607
+ * @name async-matchers#already
4608
+ * @since 3.8.0
4609
+ * @type {async-matchers}
4610
+ * @example
4611
+ * await expectAsync(myPromise).already.toBeResolved();
4612
+ * @example
4613
+ * return expectAsync(myPromise).already.toBeResolved();
4614
+ */
4615
+ Object.defineProperty(AsyncExpectation.prototype, 'already', {
4616
+ get: function() {
4617
+ return addFilter(this, expectSettledPromiseFilter);
4618
+ }
4619
+ });
4620
+
3704
4621
  function wrapSyncCompare(name, matcherFactory) {
3705
4622
  return function() {
3706
4623
  var result = this.expector.compare(name, matcherFactory, arguments);
@@ -3779,6 +4696,27 @@ getJasmineRequireObj().Expectation = function(j$) {
3779
4696
  buildFailureMessage: negatedFailureMessage
3780
4697
  };
3781
4698
 
4699
+ var expectSettledPromiseFilter = {
4700
+ selectComparisonFunc: function(matcher) {
4701
+ return function(actual) {
4702
+ var matcherArgs = arguments;
4703
+
4704
+ return j$.isPending_(actual).then(function(isPending) {
4705
+ if (isPending) {
4706
+ return {
4707
+ pass: false,
4708
+ message:
4709
+ 'Expected a promise to be settled (via ' +
4710
+ 'expectAsync(...).already) but it was pending.'
4711
+ };
4712
+ } else {
4713
+ return matcher.compare.apply(null, matcherArgs);
4714
+ }
4715
+ });
4716
+ };
4717
+ }
4718
+ };
4719
+
3782
4720
  function ContextAddingFilter(message) {
3783
4721
  this.message = message;
3784
4722
  }
@@ -3883,7 +4821,7 @@ getJasmineRequireObj().buildExpectationResult = function(j$) {
3883
4821
  var result = {
3884
4822
  matcherName: options.matcherName,
3885
4823
  message: message(),
3886
- stack: stack(),
4824
+ stack: options.omitStackTrace ? '' : stack(),
3887
4825
  passed: options.passed
3888
4826
  };
3889
4827
 
@@ -3969,7 +4907,15 @@ getJasmineRequireObj().Expector = function(j$) {
3969
4907
 
3970
4908
  this.args.unshift(this.actual);
3971
4909
 
3972
- 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
+
3973
4919
  var comparisonFunc = this.filters.selectComparisonFunc(matcher);
3974
4920
  return comparisonFunc || matcher.compare;
3975
4921
  };
@@ -4074,7 +5020,28 @@ getJasmineRequireObj().GlobalErrors = function(j$) {
4074
5020
  this.jasmineHandlers = {};
4075
5021
  this.installOne_ = function installOne_(errorType, jasmineMessage) {
4076
5022
  function taggedOnError(error) {
4077
- error.jasmineMessage = jasmineMessage + ': ' + error;
5023
+ var substituteMsg;
5024
+
5025
+ if (j$.isError_(error)) {
5026
+ error.jasmineMessage = jasmineMessage + ': ' + error;
5027
+ } else {
5028
+ if (error) {
5029
+ substituteMsg = jasmineMessage + ': ' + error;
5030
+ } else {
5031
+ substituteMsg = jasmineMessage + ' with no error or message';
5032
+ }
5033
+
5034
+ if (errorType === 'unhandledRejection') {
5035
+ substituteMsg +=
5036
+ '\n' +
5037
+ '(Tip: to get a useful stack trace, use ' +
5038
+ 'Promise.reject(new Error(...)) instead of Promise.reject(' +
5039
+ (error ? '...' : '') +
5040
+ ').)';
5041
+ }
5042
+
5043
+ error = new Error(substituteMsg);
5044
+ }
4078
5045
 
4079
5046
  var handler = handlers[handlers.length - 1];
4080
5047
 
@@ -4423,7 +5390,7 @@ getJasmineRequireObj().toBeResolved = function(j$) {
4423
5390
  * @example
4424
5391
  * return expectAsync(aPromise).toBeResolved();
4425
5392
  */
4426
- return function toBeResolved() {
5393
+ return function toBeResolved(matchersUtil) {
4427
5394
  return {
4428
5395
  compare: function(actual) {
4429
5396
  if (!j$.isPromiseLike(actual)) {
@@ -4434,8 +5401,15 @@ getJasmineRequireObj().toBeResolved = function(j$) {
4434
5401
  function() {
4435
5402
  return { pass: true };
4436
5403
  },
4437
- function() {
4438
- return { pass: false };
5404
+ function(e) {
5405
+ return {
5406
+ pass: false,
5407
+ message:
5408
+ 'Expected a promise to be resolved but it was ' +
5409
+ 'rejected with ' +
5410
+ matchersUtil.pp(e) +
5411
+ '.'
5412
+ };
4439
5413
  }
4440
5414
  );
4441
5415
  }
@@ -4490,10 +5464,14 @@ getJasmineRequireObj().toBeResolvedTo = function(j$) {
4490
5464
  };
4491
5465
  }
4492
5466
  },
4493
- function() {
5467
+ function(e) {
4494
5468
  return {
4495
5469
  pass: false,
4496
- message: prefix(false) + ' but it was rejected.'
5470
+ message:
5471
+ prefix(false) +
5472
+ ' but it was rejected with ' +
5473
+ matchersUtil.pp(e) +
5474
+ '.'
4497
5475
  };
4498
5476
  }
4499
5477
  );
@@ -4622,14 +5600,12 @@ getJasmineRequireObj().DiffBuilder = function(j$) {
4622
5600
  };
4623
5601
 
4624
5602
  getJasmineRequireObj().MatchersUtil = function(j$) {
4625
- // TODO: convert all uses of j$.pp to use the injected pp
4626
-
4627
5603
  /**
5604
+ * @class MatchersUtil
5605
+ * @classdesc Utilities for use in implementing matchers.<br>
4628
5606
  * _Note:_ Do not construct this directly. Jasmine will construct one and
4629
5607
  * pass it to matchers and asymmetric equality testers.
4630
- * @name MatchersUtil
4631
- * @classdesc Utilities for use in implementing matchers
4632
- * @constructor
5608
+ * @hideconstructor
4633
5609
  */
4634
5610
  function MatchersUtil(options) {
4635
5611
  options = options || {};
@@ -4654,10 +5630,19 @@ getJasmineRequireObj().MatchersUtil = function(j$) {
4654
5630
  * @since 2.0.0
4655
5631
  * @param {*} haystack The collection to search
4656
5632
  * @param {*} needle The value to search for
4657
- * @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.
4658
5635
  * @returns {boolean} True if `needle` was found in `haystack`
4659
5636
  */
4660
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
+
4661
5646
  if (j$.isSet(haystack)) {
4662
5647
  return haystack.has(needle);
4663
5648
  }
@@ -4667,8 +5652,13 @@ getJasmineRequireObj().MatchersUtil = function(j$) {
4667
5652
  (!!haystack && !haystack.indexOf)
4668
5653
  ) {
4669
5654
  for (var i = 0; i < haystack.length; i++) {
4670
- if (this.equals(haystack[i], needle, customTesters)) {
4671
- 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;
4672
5662
  }
4673
5663
  }
4674
5664
  return false;
@@ -4772,7 +5762,8 @@ getJasmineRequireObj().MatchersUtil = function(j$) {
4772
5762
  * @since 2.0.0
4773
5763
  * @param {*} a The first value to compare
4774
5764
  * @param {*} b The second value to compare
4775
- * @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.
4776
5767
  * @returns {boolean} True if the values are equal
4777
5768
  */
4778
5769
  MatchersUtil.prototype.equals = function(
@@ -4786,6 +5777,22 @@ getJasmineRequireObj().MatchersUtil = function(j$) {
4786
5777
  if (isDiffBuilder(customTestersOrDiffBuilder)) {
4787
5778
  diffBuilder = customTestersOrDiffBuilder;
4788
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
+
4789
5796
  customTesters = customTestersOrDiffBuilder;
4790
5797
  diffBuilder = diffBuilderOrNothing;
4791
5798
  }
@@ -4892,6 +5899,17 @@ getJasmineRequireObj().MatchersUtil = function(j$) {
4892
5899
  diffBuilder.recordMismatch();
4893
5900
  }
4894
5901
  return result;
5902
+ case '[object ArrayBuffer]':
5903
+ // If we have an instance of ArrayBuffer the Uint8Array ctor
5904
+ // will be defined as well
5905
+ return self.eq_(
5906
+ new Uint8Array(a), // eslint-disable-line compat/compat
5907
+ new Uint8Array(b), // eslint-disable-line compat/compat
5908
+ aStack,
5909
+ bStack,
5910
+ customTesters,
5911
+ diffBuilder
5912
+ );
4895
5913
  // RegExps are compared by their source patterns and flags.
4896
5914
  case '[object RegExp]':
4897
5915
  return (
@@ -5268,6 +6286,55 @@ getJasmineRequireObj().MatchersUtil = function(j$) {
5268
6286
  return MatchersUtil;
5269
6287
  };
5270
6288
 
6289
+ /**
6290
+ * @interface AsymmetricEqualityTester
6291
+ * @classdesc An asymmetric equality tester is an object that can match multiple
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)}));
6319
+ * @see custom_asymmetric_equality_testers
6320
+ * @since 2.0.0
6321
+ */
6322
+ /**
6323
+ * Determines whether a value matches this tester
6324
+ * @function
6325
+ * @name AsymmetricEqualityTester#asymmetricMatch
6326
+ * @param value {any} The value to test
6327
+ * @param matchersUtil {MatchersUtil} utilities for testing equality, etc
6328
+ * @return {Boolean}
6329
+ */
6330
+ /**
6331
+ * Returns a string representation of this tester to use in matcher failure messages
6332
+ * @function
6333
+ * @name AsymmetricEqualityTester#jasmineToString
6334
+ * @param pp {function} Function that takes a value and returns a pretty-printed representation
6335
+ * @return {String}
6336
+ */
6337
+
5271
6338
  getJasmineRequireObj().MismatchTree = function(j$) {
5272
6339
  /*
5273
6340
  To be able to apply custom object formatters at all possible levels of an
@@ -6871,7 +7938,7 @@ getJasmineRequireObj().toThrowMatching = function(j$) {
6871
7938
  return toThrowMatching;
6872
7939
  };
6873
7940
 
6874
- getJasmineRequireObj().MockDate = function() {
7941
+ getJasmineRequireObj().MockDate = function(j$) {
6875
7942
  function MockDate(global) {
6876
7943
  var self = this;
6877
7944
  var currentTime = 0;
@@ -6889,6 +7956,14 @@ getJasmineRequireObj().MockDate = function() {
6889
7956
  if (mockDate instanceof GlobalDate) {
6890
7957
  currentTime = mockDate.getTime();
6891
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
+
6892
7967
  currentTime = new GlobalDate().getTime();
6893
7968
  }
6894
7969
 
@@ -7390,10 +8465,14 @@ getJasmineRequireObj().QueueRunner = function(j$) {
7390
8465
  StopExecutionError.prototype = new Error();
7391
8466
  j$.StopExecutionError = StopExecutionError;
7392
8467
 
7393
- function once(fn) {
8468
+ function once(fn, onTwice) {
7394
8469
  var called = false;
7395
8470
  return function(arg) {
7396
- if (!called) {
8471
+ if (called) {
8472
+ if (onTwice) {
8473
+ onTwice();
8474
+ }
8475
+ } else {
7397
8476
  called = true;
7398
8477
  // Direct call using single parameter, because cleanup/next does not need more
7399
8478
  fn(arg);
@@ -7402,6 +8481,16 @@ getJasmineRequireObj().QueueRunner = function(j$) {
7402
8481
  };
7403
8482
  }
7404
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
+
7405
8494
  function emptyFn() {}
7406
8495
 
7407
8496
  function QueueRunner(attrs) {
@@ -7416,6 +8505,7 @@ getJasmineRequireObj().QueueRunner = function(j$) {
7416
8505
  fn();
7417
8506
  };
7418
8507
  this.onException = attrs.onException || emptyFn;
8508
+ this.onMultipleDone = attrs.onMultipleDone || fallbackOnMultipleDone;
7419
8509
  this.userContext = attrs.userContext || new j$.UserContext();
7420
8510
  this.timeout = attrs.timeout || {
7421
8511
  setTimeout: setTimeout,
@@ -7473,8 +8563,9 @@ getJasmineRequireObj().QueueRunner = function(j$) {
7473
8563
  var self = this,
7474
8564
  completedSynchronously = true,
7475
8565
  handleError = function handleError(error) {
8566
+ // TODO probably shouldn't next() right away here.
8567
+ // That makes debugging async failures much more confusing.
7476
8568
  onException(error);
7477
- next(error);
7478
8569
  },
7479
8570
  cleanup = once(function cleanup() {
7480
8571
  if (timeoutId !== void 0) {
@@ -7482,31 +8573,52 @@ getJasmineRequireObj().QueueRunner = function(j$) {
7482
8573
  }
7483
8574
  self.globalErrors.popListener(handleError);
7484
8575
  }),
7485
- next = once(function next(err) {
7486
- cleanup();
8576
+ next = once(
8577
+ function next(err) {
8578
+ cleanup();
7487
8579
 
7488
- if (j$.isError_(err)) {
7489
- if (!(err instanceof StopExecutionError) && !err.jasmineMessage) {
7490
- 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
+ );
7491
8591
  }
7492
- self.errored = errored = true;
7493
- }
7494
8592
 
7495
- function runNext() {
7496
- if (self.completeOnFirstError && errored) {
7497
- self.skipToCleanup(iterativeIndex);
7498
- } else {
7499
- self.run(iterativeIndex + 1);
8593
+ function runNext() {
8594
+ if (self.completeOnFirstError && errored) {
8595
+ self.skipToCleanup(iterativeIndex);
8596
+ } else {
8597
+ self.run(iterativeIndex + 1);
8598
+ }
7500
8599
  }
7501
- }
7502
8600
 
7503
- if (completedSynchronously) {
7504
- self.setTimeout(runNext);
7505
- } else {
7506
- 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
+ }
7507
8618
  }
7508
- }),
8619
+ ),
7509
8620
  errored = false,
8621
+ timedOut = false,
7510
8622
  queueableFn = self.queueableFns[iterativeIndex],
7511
8623
  timeoutId,
7512
8624
  maybeThenable;
@@ -7522,6 +8634,7 @@ getJasmineRequireObj().QueueRunner = function(j$) {
7522
8634
  if (queueableFn.timeout !== undefined) {
7523
8635
  var timeoutInterval = queueableFn.timeout || j$.DEFAULT_TIMEOUT_INTERVAL;
7524
8636
  timeoutId = self.setTimeout(function() {
8637
+ timedOut = true;
7525
8638
  var error = new Error(
7526
8639
  'Timeout - Async function did not complete within ' +
7527
8640
  timeoutInterval +
@@ -7530,6 +8643,9 @@ getJasmineRequireObj().QueueRunner = function(j$) {
7530
8643
  ? '(custom timeout)'
7531
8644
  : '(set by jasmine.DEFAULT_TIMEOUT_INTERVAL)')
7532
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.)
7533
8649
  onException(error);
7534
8650
  next();
7535
8651
  }, timeoutInterval);
@@ -7595,30 +8711,39 @@ getJasmineRequireObj().QueueRunner = function(j$) {
7595
8711
 
7596
8712
  this.clearStack(function() {
7597
8713
  self.globalErrors.popListener(self.handleFinalError);
7598
- self.onComplete(self.errored && new StopExecutionError());
8714
+
8715
+ if (self.errored) {
8716
+ self.onComplete(new StopExecutionError());
8717
+ } else {
8718
+ self.onComplete();
8719
+ }
7599
8720
  });
7600
8721
  };
7601
8722
 
7602
8723
  QueueRunner.prototype.diagnoseConflictingAsync_ = function(fn, retval) {
8724
+ var msg;
8725
+
7603
8726
  if (retval && j$.isFunction_(retval.then)) {
7604
- // 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.
7605
8730
  if (j$.isAsyncFunction_(fn)) {
7606
- this.deprecated(
8731
+ msg =
7607
8732
  'An asynchronous before/it/after ' +
7608
- 'function was defined with the async keyword but also took a ' +
7609
- 'done callback. This is not supported and will stop working in' +
7610
- ' the future. Either remove the done callback (recommended) or ' +
7611
- 'remove the async keyword.'
7612
- );
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.';
7613
8737
  } else {
7614
- this.deprecated(
8738
+ msg =
7615
8739
  'An asynchronous before/it/after ' +
7616
- 'function took a done callback but also returned a promise. ' +
7617
- 'This is not supported and will stop working in the future. ' +
7618
- 'Either remove the done callback (recommended) or change the ' +
7619
- 'function to not return a promise.'
7620
- );
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.';
7621
8744
  }
8745
+
8746
+ this.deprecated(msg, { omitStackTrace: true });
7622
8747
  }
7623
8748
  };
7624
8749
 
@@ -7626,7 +8751,7 @@ getJasmineRequireObj().QueueRunner = function(j$) {
7626
8751
  };
7627
8752
 
7628
8753
  getJasmineRequireObj().ReportDispatcher = function(j$) {
7629
- function ReportDispatcher(methods, queueRunnerFactory) {
8754
+ function ReportDispatcher(methods, queueRunnerFactory, deprecated) {
7630
8755
  var dispatchedMethods = methods || [];
7631
8756
 
7632
8757
  for (var i = 0; i < dispatchedMethods.length; i++) {
@@ -7670,7 +8795,18 @@ getJasmineRequireObj().ReportDispatcher = function(j$) {
7670
8795
  queueRunnerFactory({
7671
8796
  queueableFns: fns,
7672
8797
  onComplete: onComplete,
7673
- 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
+ }
7674
8810
  });
7675
8811
  }
7676
8812
 
@@ -7987,10 +9123,11 @@ getJasmineRequireObj().interface = function(jasmine, env) {
7987
9123
  * @function
7988
9124
  * @global
7989
9125
  * @param {Object} obj - The object upon which to install the {@link Spy}s
9126
+ * @param {boolean} includeNonEnumerable - Whether or not to add spies to non-enumerable properties
7990
9127
  * @returns {Object} the spied object
7991
9128
  */
7992
- spyOnAllFunctions: function(obj) {
7993
- return env.spyOnAllFunctions(obj);
9129
+ spyOnAllFunctions: function(obj, includeNonEnumerable) {
9130
+ return env.spyOnAllFunctions(obj, includeNonEnumerable);
7994
9131
  },
7995
9132
 
7996
9133
  jsApiReporter: new jasmine.JsApiReporter({
@@ -8145,9 +9282,11 @@ getJasmineRequireObj().Spy = function(j$) {
8145
9282
  });
8146
9283
 
8147
9284
  /**
8148
- * _Note:_ Do not construct this directly, use {@link spyOn}, {@link spyOnProperty}, {@link jasmine.createSpy}, or {@link jasmine.createSpyObj}
8149
- * @constructor
8150
- * @name Spy
9285
+ * @classdesc _Note:_ Do not construct this directly. Use {@link spyOn},
9286
+ * {@link spyOnProperty}, {@link jasmine.createSpy}, or
9287
+ * {@link jasmine.createSpyObj} instead.
9288
+ * @class Spy
9289
+ * @hideconstructor
8151
9290
  */
8152
9291
  function Spy(
8153
9292
  name,
@@ -8176,6 +9315,7 @@ getJasmineRequireObj().Spy = function(j$) {
8176
9315
  * @property {object} object - `this` context for the invocation.
8177
9316
  * @property {number} invocationOrder - Order of the invocation.
8178
9317
  * @property {Array} args - The arguments passed for this invocation.
9318
+ * @property returnValue - The value that was returned from this invocation.
8179
9319
  */
8180
9320
  var callData = {
8181
9321
  object: context,
@@ -8296,7 +9436,7 @@ getJasmineRequireObj().Spy = function(j$) {
8296
9436
  "Spy '" +
8297
9437
  strategyArgs.name +
8298
9438
  "' received a call with arguments " +
8299
- j$.pp(Array.prototype.slice.call(args)) +
9439
+ j$.basicPrettyPrinter_(Array.prototype.slice.call(args)) +
8300
9440
  ' but all configured strategies specify other arguments.'
8301
9441
  );
8302
9442
  } else {
@@ -8591,7 +9731,7 @@ getJasmineRequireObj().SpyRegistry = function(j$) {
8591
9731
  return spy;
8592
9732
  };
8593
9733
 
8594
- this.spyOnAllFunctions = function(obj) {
9734
+ this.spyOnAllFunctions = function(obj, includeNonEnumerable) {
8595
9735
  if (j$.util.isUndefined(obj)) {
8596
9736
  throw new Error(
8597
9737
  'spyOnAllFunctions could not find an object to spy upon'
@@ -8599,30 +9739,27 @@ getJasmineRequireObj().SpyRegistry = function(j$) {
8599
9739
  }
8600
9740
 
8601
9741
  var pointer = obj,
8602
- props = [],
8603
- prop,
8604
- descriptor;
9742
+ propsToSpyOn = [],
9743
+ properties,
9744
+ propertiesToSkip = [];
8605
9745
 
8606
- while (pointer) {
8607
- for (prop in pointer) {
8608
- if (
8609
- Object.prototype.hasOwnProperty.call(pointer, prop) &&
8610
- pointer[prop] instanceof Function
8611
- ) {
8612
- descriptor = Object.getOwnPropertyDescriptor(pointer, prop);
8613
- if (
8614
- (descriptor.writable || descriptor.set) &&
8615
- descriptor.configurable
8616
- ) {
8617
- props.push(prop);
8618
- }
8619
- }
8620
- }
9746
+ while (
9747
+ pointer &&
9748
+ (!includeNonEnumerable || pointer !== Object.prototype)
9749
+ ) {
9750
+ properties = getProps(pointer, includeNonEnumerable);
9751
+ properties = properties.filter(function(prop) {
9752
+ return propertiesToSkip.indexOf(prop) === -1;
9753
+ });
9754
+ propertiesToSkip = propertiesToSkip.concat(properties);
9755
+ propsToSpyOn = propsToSpyOn.concat(
9756
+ getSpyableFunctionProps(pointer, properties)
9757
+ );
8621
9758
  pointer = Object.getPrototypeOf(pointer);
8622
9759
  }
8623
9760
 
8624
- for (var i = 0; i < props.length; i++) {
8625
- this.spyOn(obj, props[i]);
9761
+ for (var i = 0; i < propsToSpyOn.length; i++) {
9762
+ this.spyOn(obj, propsToSpyOn[i]);
8626
9763
  }
8627
9764
 
8628
9765
  return obj;
@@ -8637,6 +9774,50 @@ getJasmineRequireObj().SpyRegistry = function(j$) {
8637
9774
  };
8638
9775
  }
8639
9776
 
9777
+ function getProps(obj, includeNonEnumerable) {
9778
+ var enumerableProperties = Object.keys(obj);
9779
+
9780
+ if (!includeNonEnumerable) {
9781
+ return enumerableProperties;
9782
+ }
9783
+
9784
+ return Object.getOwnPropertyNames(obj).filter(function(prop) {
9785
+ return (
9786
+ prop !== 'constructor' ||
9787
+ enumerableProperties.indexOf('constructor') > -1
9788
+ );
9789
+ });
9790
+ }
9791
+
9792
+ function getSpyableFunctionProps(obj, propertiesToCheck) {
9793
+ var props = [],
9794
+ prop;
9795
+ for (var i = 0; i < propertiesToCheck.length; i++) {
9796
+ prop = propertiesToCheck[i];
9797
+ if (
9798
+ Object.prototype.hasOwnProperty.call(obj, prop) &&
9799
+ isSpyableProp(obj, prop)
9800
+ ) {
9801
+ props.push(prop);
9802
+ }
9803
+ }
9804
+ return props;
9805
+ }
9806
+
9807
+ function isSpyableProp(obj, prop) {
9808
+ var value, descriptor;
9809
+ try {
9810
+ value = obj[prop];
9811
+ } catch (e) {
9812
+ return false;
9813
+ }
9814
+ if (value instanceof Function) {
9815
+ descriptor = Object.getOwnPropertyDescriptor(obj, prop);
9816
+ return (descriptor.writable || descriptor.set) && descriptor.configurable;
9817
+ }
9818
+ return false;
9819
+ }
9820
+
8640
9821
  return SpyRegistry;
8641
9822
  };
8642
9823
 
@@ -8969,15 +10150,42 @@ getJasmineRequireObj().StackTrace = function(j$) {
8969
10150
  };
8970
10151
 
8971
10152
  getJasmineRequireObj().Suite = function(j$) {
10153
+ /**
10154
+ * @interface Suite
10155
+ * @see Env#topSuite
10156
+ * @since 2.0.0
10157
+ */
8972
10158
  function Suite(attrs) {
8973
10159
  this.env = attrs.env;
10160
+ /**
10161
+ * The unique ID of this suite.
10162
+ * @name Suite#id
10163
+ * @readonly
10164
+ * @type {string}
10165
+ * @since 2.0.0
10166
+ */
8974
10167
  this.id = attrs.id;
10168
+ /**
10169
+ * The parent of this suite, or null if this is the top suite.
10170
+ * @name Suite#parentSuite
10171
+ * @readonly
10172
+ * @type {Suite}
10173
+ */
8975
10174
  this.parentSuite = attrs.parentSuite;
10175
+ /**
10176
+ * The description passed to the {@link describe} that created this suite.
10177
+ * @name Suite#description
10178
+ * @readonly
10179
+ * @type {string}
10180
+ * @since 2.0.0
10181
+ */
8976
10182
  this.description = attrs.description;
8977
10183
  this.expectationFactory = attrs.expectationFactory;
8978
10184
  this.asyncExpectationFactory = attrs.asyncExpectationFactory;
8979
10185
  this.expectationResultFactory = attrs.expectationResultFactory;
8980
10186
  this.throwOnExpectationFailure = !!attrs.throwOnExpectationFailure;
10187
+ this.autoCleanClosures =
10188
+ attrs.autoCleanClosures === undefined ? true : !!attrs.autoCleanClosures;
8981
10189
 
8982
10190
  this.beforeFns = [];
8983
10191
  this.afterFns = [];
@@ -8986,28 +10194,15 @@ getJasmineRequireObj().Suite = function(j$) {
8986
10194
 
8987
10195
  this.timer = attrs.timer || new j$.Timer();
8988
10196
 
8989
- this.children = [];
8990
-
8991
10197
  /**
8992
- * @typedef SuiteResult
8993
- * @property {Int} id - The unique id of this suite.
8994
- * @property {String} description - The description text passed to the {@link describe} that made this suite.
8995
- * @property {String} fullName - The full description including all ancestors of this suite.
8996
- * @property {Expectation[]} failedExpectations - The list of expectations that failed in an {@link afterAll} for this suite.
8997
- * @property {Expectation[]} deprecationWarnings - The list of deprecation warnings that occurred on this suite.
8998
- * @property {String} status - Once the suite has completed, this string represents the pass/fail status of this suite.
8999
- * @property {number} duration - The time in ms for Suite execution, including any before/afterAll, before/afterEach.
9000
- * @property {Object} properties - User-supplied properties, if any, that were set using {@link Env#setSuiteProperty}
10198
+ * The suite's children.
10199
+ * @name Suite#children
10200
+ * @type {Array.<(Spec|Suite)>}
10201
+ * @since 2.0.0
9001
10202
  */
9002
- this.result = {
9003
- id: this.id,
9004
- description: this.description,
9005
- fullName: this.getFullName(),
9006
- failedExpectations: [],
9007
- deprecationWarnings: [],
9008
- duration: null,
9009
- properties: null
9010
- };
10203
+ this.children = [];
10204
+
10205
+ this.reset();
9011
10206
  }
9012
10207
 
9013
10208
  Suite.prototype.setSuiteProperty = function(key, value) {
@@ -9023,6 +10218,13 @@ getJasmineRequireObj().Suite = function(j$) {
9023
10218
  return this.asyncExpectationFactory(actual, this);
9024
10219
  };
9025
10220
 
10221
+ /**
10222
+ * The full description including all ancestors of this suite.
10223
+ * @name Suite#getFullName
10224
+ * @function
10225
+ * @returns {string}
10226
+ * @since 2.0.0
10227
+ */
9026
10228
  Suite.prototype.getFullName = function() {
9027
10229
  var fullName = [];
9028
10230
  for (
@@ -9037,10 +10239,22 @@ getJasmineRequireObj().Suite = function(j$) {
9037
10239
  return fullName.join(' ');
9038
10240
  };
9039
10241
 
10242
+ /*
10243
+ * Mark the suite with "pending" status
10244
+ */
9040
10245
  Suite.prototype.pend = function() {
9041
10246
  this.markedPending = true;
9042
10247
  };
9043
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
+
9044
10258
  Suite.prototype.beforeEach = function(fn) {
9045
10259
  this.beforeFns.unshift(fn);
9046
10260
  };
@@ -9072,10 +10286,40 @@ getJasmineRequireObj().Suite = function(j$) {
9072
10286
  }
9073
10287
 
9074
10288
  Suite.prototype.cleanupBeforeAfter = function() {
9075
- removeFns(this.beforeAllFns);
9076
- removeFns(this.afterAllFns);
9077
- removeFns(this.beforeFns);
9078
- 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
+ });
9079
10323
  };
9080
10324
 
9081
10325
  Suite.prototype.addChild = function(child) {
@@ -9138,6 +10382,36 @@ getJasmineRequireObj().Suite = function(j$) {
9138
10382
  this.result.failedExpectations.push(failedExpectation);
9139
10383
  };
9140
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
+
9141
10415
  Suite.prototype.addExpectationResult = function() {
9142
10416
  if (isFailure(arguments)) {
9143
10417
  var data = arguments[1];
@@ -9240,7 +10514,10 @@ getJasmineRequireObj().TreeProcessor = function() {
9240
10514
  onException: function() {
9241
10515
  tree.onException.apply(tree, arguments);
9242
10516
  },
9243
- onComplete: done
10517
+ onComplete: done,
10518
+ onMultipleDone: tree.onMultipleDone
10519
+ ? tree.onMultipleDone.bind(tree)
10520
+ : null
9244
10521
  });
9245
10522
  };
9246
10523
 
@@ -9412,7 +10689,10 @@ getJasmineRequireObj().TreeProcessor = function() {
9412
10689
  userContext: node.sharedUserContext(),
9413
10690
  onException: function() {
9414
10691
  node.onException.apply(node, arguments);
9415
- }
10692
+ },
10693
+ onMultipleDone: node.onMultipleDone
10694
+ ? node.onMultipleDone.bind(node)
10695
+ : null
9416
10696
  });
9417
10697
  }
9418
10698
  };
@@ -9469,5 +10749,5 @@ getJasmineRequireObj().UserContext = function(j$) {
9469
10749
  };
9470
10750
 
9471
10751
  getJasmineRequireObj().version = function() {
9472
- return '3.7.1';
10752
+ return '3.99.0';
9473
10753
  };