jasmine-core 5.5.0 → 5.6.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.
package/LICENSE CHANGED
@@ -1,5 +1,5 @@
1
1
  Copyright (c) 2008-2019 Pivotal Labs
2
- Copyright (c) 2008-2024 The Jasmine developers
2
+ Copyright (c) 2008-2025 The Jasmine developers
3
3
 
4
4
  Permission is hereby granted, free of charge, to any person obtaining
5
5
  a copy of this software and associated documentation files (the
package/README.md CHANGED
@@ -30,7 +30,7 @@ Microsoft Edge) as well as Node.
30
30
  | Environment | Supported versions |
31
31
  |-------------------|----------------------------|
32
32
  | Node | 18, 20, 22 |
33
- | Safari | 15-17 |
33
+ | Safari | 15*, 16*, 17* |
34
34
  | Chrome | Evergreen |
35
35
  | Firefox | Evergreen, 102*, 115*, 128 |
36
36
  | Edge | Evergreen |
@@ -39,9 +39,9 @@ For evergreen browsers, each version of Jasmine is tested against the version of
39
39
  at the time of release. Other browsers, as well as older & newer versions of some supported browsers, are likely to work.
40
40
  However, Jasmine isn't tested against them and they aren't actively supported.
41
41
 
42
- \* Environments that are past end of life are supported on a best-effort basis.
43
- They may be dropped in a future minor release of Jasmine if continued support
44
- becomes impractical.
42
+ \* Supported on a best-effort basis. Support for these versions may be dropped
43
+ if it becomes impractical, and bugs affecting only these versions may not be
44
+ treated as release blockers.
45
45
 
46
46
  To find out what environments work with a particular Jasmine release, see the [release notes](https://github.com/jasmine/jasmine/tree/main/release_notes).
47
47
 
@@ -60,5 +60,5 @@ To find out what environments work with a particular Jasmine release, see the [r
60
60
  * Sheel Choksi
61
61
 
62
62
  Copyright (c) 2008-2019 Pivotal Labs<br>
63
- Copyright (c) 2008-2024 The Jasmine developers<br>
63
+ Copyright (c) 2008-2025 The Jasmine developers<br>
64
64
  This software is licensed under the [MIT License](https://github.com/jasmine/jasmine/blob/main/LICENSE).
@@ -1,6 +1,6 @@
1
1
  /*
2
2
  Copyright (c) 2008-2019 Pivotal Labs
3
- Copyright (c) 2008-2024 The Jasmine developers
3
+ Copyright (c) 2008-2025 The Jasmine developers
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining
6
6
  a copy of this software and associated documentation files (the
@@ -1,6 +1,6 @@
1
1
  /*
2
2
  Copyright (c) 2008-2019 Pivotal Labs
3
- Copyright (c) 2008-2024 The Jasmine developers
3
+ Copyright (c) 2008-2025 The Jasmine developers
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining
6
6
  a copy of this software and associated documentation files (the
@@ -1,6 +1,6 @@
1
1
  /*
2
2
  Copyright (c) 2008-2019 Pivotal Labs
3
- Copyright (c) 2008-2024 The Jasmine developers
3
+ Copyright (c) 2008-2025 The Jasmine developers
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining
6
6
  a copy of this software and associated documentation files (the
@@ -1,6 +1,6 @@
1
1
  /*
2
2
  Copyright (c) 2008-2019 Pivotal Labs
3
- Copyright (c) 2008-2024 The Jasmine developers
3
+ Copyright (c) 2008-2025 The Jasmine developers
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining
6
6
  a copy of this software and associated documentation files (the
@@ -150,6 +150,7 @@ getJasmineRequireObj().requireMatchers = function(jRequire, j$) {
150
150
  'toBeTrue',
151
151
  'toBeTruthy',
152
152
  'toBeUndefined',
153
+ 'toBeNullish',
153
154
  'toContain',
154
155
  'toEqual',
155
156
  'toHaveSize',
@@ -159,7 +160,9 @@ getJasmineRequireObj().requireMatchers = function(jRequire, j$) {
159
160
  'toHaveBeenCalledTimes',
160
161
  'toHaveBeenCalledWith',
161
162
  'toHaveClass',
163
+ 'toHaveClasses',
162
164
  'toHaveSpyInteractions',
165
+ 'toHaveNoOtherSpyInteractions',
163
166
  'toMatch',
164
167
  'toThrow',
165
168
  'toThrowError',
@@ -2896,6 +2899,10 @@ getJasmineRequireObj().CallTracker = function(j$) {
2896
2899
  this.saveArgumentsByValue = function() {
2897
2900
  opts.cloneArgs = true;
2898
2901
  };
2902
+
2903
+ this.unverifiedCount = function() {
2904
+ return calls.reduce((count, call) => count + (call.verified ? 0 : 1), 0);
2905
+ };
2899
2906
  }
2900
2907
 
2901
2908
  return CallTracker;
@@ -4332,7 +4339,9 @@ getJasmineRequireObj().toBePending = function(j$) {
4332
4339
  return {
4333
4340
  compare: function(actual) {
4334
4341
  if (!j$.isPromiseLike(actual)) {
4335
- throw new Error('Expected toBePending to be called on a promise.');
4342
+ throw new Error(
4343
+ `Expected toBePending to be called on a promise but was on a ${typeof actual}.`
4344
+ );
4336
4345
  }
4337
4346
  const want = {};
4338
4347
  return Promise.race([actual, Promise.resolve(want)]).then(
@@ -4364,7 +4373,9 @@ getJasmineRequireObj().toBeRejected = function(j$) {
4364
4373
  return {
4365
4374
  compare: function(actual) {
4366
4375
  if (!j$.isPromiseLike(actual)) {
4367
- throw new Error('Expected toBeRejected to be called on a promise.');
4376
+ throw new Error(
4377
+ `Expected toBeRejected to be called on a promise but was on a ${typeof actual}.`
4378
+ );
4368
4379
  }
4369
4380
  return actual.then(
4370
4381
  function() {
@@ -4397,7 +4408,7 @@ getJasmineRequireObj().toBeRejectedWith = function(j$) {
4397
4408
  compare: function(actualPromise, expectedValue) {
4398
4409
  if (!j$.isPromiseLike(actualPromise)) {
4399
4410
  throw new Error(
4400
- 'Expected toBeRejectedWith to be called on a promise.'
4411
+ `Expected toBeRejectedWith to be called on a promise but was on a ${typeof actualPromise}.`
4401
4412
  );
4402
4413
  }
4403
4414
 
@@ -4461,7 +4472,7 @@ getJasmineRequireObj().toBeRejectedWithError = function(j$) {
4461
4472
  compare: function(actualPromise, arg1, arg2) {
4462
4473
  if (!j$.isPromiseLike(actualPromise)) {
4463
4474
  throw new Error(
4464
- 'Expected toBeRejectedWithError to be called on a promise.'
4475
+ `Expected toBeRejectedWithError to be called on a promise but was on a ${typeof actualPromise}.`
4465
4476
  );
4466
4477
  }
4467
4478
 
@@ -4579,7 +4590,9 @@ getJasmineRequireObj().toBeResolved = function(j$) {
4579
4590
  return {
4580
4591
  compare: function(actual) {
4581
4592
  if (!j$.isPromiseLike(actual)) {
4582
- throw new Error('Expected toBeResolved to be called on a promise.');
4593
+ throw new Error(
4594
+ `Expected toBeResolved to be called on a promise but was on a ${typeof actual}.`
4595
+ );
4583
4596
  }
4584
4597
 
4585
4598
  return actual.then(
@@ -4619,7 +4632,9 @@ getJasmineRequireObj().toBeResolvedTo = function(j$) {
4619
4632
  return {
4620
4633
  compare: function(actualPromise, expectedValue) {
4621
4634
  if (!j$.isPromiseLike(actualPromise)) {
4622
- throw new Error('Expected toBeResolvedTo to be called on a promise.');
4635
+ throw new Error(
4636
+ `Expected toBeResolvedTo to be called on a promise but was on a ${typeof actualPromise}.`
4637
+ );
4623
4638
  }
4624
4639
 
4625
4640
  function prefix(passed) {
@@ -6010,6 +6025,28 @@ getJasmineRequireObj().toBeNull = function() {
6010
6025
  return toBeNull;
6011
6026
  };
6012
6027
 
6028
+ getJasmineRequireObj().toBeNullish = function() {
6029
+ /**
6030
+ * {@link expect} the actual value to be `null` or `undefined`.
6031
+ * @function
6032
+ * @name matchers#toBeNullish
6033
+ * @since 5.6.0
6034
+ * @example
6035
+ * expect(result).toBeNullish():
6036
+ */
6037
+ function toBeNullish() {
6038
+ return {
6039
+ compare: function(actual) {
6040
+ return {
6041
+ pass: null === actual || void 0 === actual
6042
+ };
6043
+ }
6044
+ };
6045
+ }
6046
+
6047
+ return toBeNullish;
6048
+ };
6049
+
6013
6050
  getJasmineRequireObj().toBePositiveInfinity = function(j$) {
6014
6051
  /**
6015
6052
  * {@link expect} the actual value to be `Infinity` (infinity).
@@ -6199,6 +6236,8 @@ getJasmineRequireObj().toHaveBeenCalled = function(j$) {
6199
6236
 
6200
6237
  result.pass = actual.calls.any();
6201
6238
 
6239
+ actual.calls.all().forEach(call => (call.verified = true));
6240
+
6202
6241
  result.message = result.pass
6203
6242
  ? 'Expected spy ' + actual.and.identity + ' not to have been called.'
6204
6243
  : 'Expected spy ' + actual.and.identity + ' to have been called.';
@@ -6263,6 +6302,9 @@ getJasmineRequireObj().toHaveBeenCalledBefore = function(j$) {
6263
6302
  result.pass = latest1stSpyCall < first2ndSpyCall;
6264
6303
 
6265
6304
  if (result.pass) {
6305
+ firstSpy.calls.mostRecent().verified = true;
6306
+ latterSpy.calls.first().verified = true;
6307
+
6266
6308
  result.message =
6267
6309
  'Expected spy ' +
6268
6310
  firstSpy.and.identity +
@@ -6319,7 +6361,7 @@ getJasmineRequireObj().toHaveBeenCalledOnceWith = function(j$) {
6319
6361
  * @example
6320
6362
  * expect(mySpy).toHaveBeenCalledOnceWith('foo', 'bar', 2);
6321
6363
  */
6322
- function toHaveBeenCalledOnceWith(util) {
6364
+ function toHaveBeenCalledOnceWith(matchersUtil) {
6323
6365
  return {
6324
6366
  compare: function() {
6325
6367
  const args = Array.prototype.slice.call(arguments, 0),
@@ -6328,20 +6370,29 @@ getJasmineRequireObj().toHaveBeenCalledOnceWith = function(j$) {
6328
6370
 
6329
6371
  if (!j$.isSpy(actual)) {
6330
6372
  throw new Error(
6331
- getErrorMsg('Expected a spy, but got ' + util.pp(actual) + '.')
6373
+ getErrorMsg(
6374
+ 'Expected a spy, but got ' + matchersUtil.pp(actual) + '.'
6375
+ )
6332
6376
  );
6333
6377
  }
6334
6378
 
6335
6379
  const prettyPrintedCalls = actual.calls
6336
6380
  .allArgs()
6337
6381
  .map(function(argsForCall) {
6338
- return ' ' + util.pp(argsForCall);
6382
+ return ' ' + matchersUtil.pp(argsForCall);
6339
6383
  });
6340
6384
 
6341
6385
  if (
6342
6386
  actual.calls.count() === 1 &&
6343
- util.contains(actual.calls.allArgs(), expectedArgs)
6387
+ matchersUtil.contains(actual.calls.allArgs(), expectedArgs)
6344
6388
  ) {
6389
+ const firstIndex = actual.calls
6390
+ .all()
6391
+ .findIndex(call => matchersUtil.equals(call.args, expectedArgs));
6392
+ if (firstIndex > -1) {
6393
+ actual.calls.all()[firstIndex].verified = true;
6394
+ }
6395
+
6345
6396
  return {
6346
6397
  pass: true,
6347
6398
  message:
@@ -6349,7 +6400,7 @@ getJasmineRequireObj().toHaveBeenCalledOnceWith = function(j$) {
6349
6400
  actual.and.identity +
6350
6401
  ' to have been called 0 times, multiple times, or once, but with arguments different from:\n' +
6351
6402
  ' ' +
6352
- util.pp(expectedArgs) +
6403
+ matchersUtil.pp(expectedArgs) +
6353
6404
  '\n' +
6354
6405
  'But the actual call was:\n' +
6355
6406
  prettyPrintedCalls.join(',\n') +
@@ -6360,7 +6411,7 @@ getJasmineRequireObj().toHaveBeenCalledOnceWith = function(j$) {
6360
6411
  function getDiffs() {
6361
6412
  return actual.calls.allArgs().map(function(argsForCall, callIx) {
6362
6413
  const diffBuilder = new j$.DiffBuilder();
6363
- util.equals(argsForCall, expectedArgs, diffBuilder);
6414
+ matchersUtil.equals(argsForCall, expectedArgs, diffBuilder);
6364
6415
  return diffBuilder.getMessage();
6365
6416
  });
6366
6417
  }
@@ -6393,7 +6444,7 @@ getJasmineRequireObj().toHaveBeenCalledOnceWith = function(j$) {
6393
6444
  actual.and.identity +
6394
6445
  ' to have been called only once, and with given args:\n' +
6395
6446
  ' ' +
6396
- util.pp(expectedArgs) +
6447
+ matchersUtil.pp(expectedArgs) +
6397
6448
  '\n' +
6398
6449
  butString()
6399
6450
  };
@@ -6442,23 +6493,35 @@ getJasmineRequireObj().toHaveBeenCalledTimes = function(j$) {
6442
6493
  }
6443
6494
 
6444
6495
  actual = args[0];
6445
- const calls = actual.calls.count();
6496
+
6497
+ const callsCount = actual.calls.count();
6446
6498
  const timesMessage = expected === 1 ? 'once' : expected + ' times';
6447
- result.pass = calls === expected;
6499
+
6500
+ result.pass = callsCount === expected;
6501
+
6502
+ if (result.pass) {
6503
+ const allCalls = actual.calls.all();
6504
+ const max = Math.min(expected, callsCount);
6505
+
6506
+ for (let i = 0; i < max; i++) {
6507
+ allCalls[i].verified = true;
6508
+ }
6509
+ }
6510
+
6448
6511
  result.message = result.pass
6449
6512
  ? 'Expected spy ' +
6450
6513
  actual.and.identity +
6451
6514
  ' not to have been called ' +
6452
6515
  timesMessage +
6453
6516
  '. It was called ' +
6454
- calls +
6517
+ callsCount +
6455
6518
  ' times.'
6456
6519
  : 'Expected spy ' +
6457
6520
  actual.and.identity +
6458
6521
  ' to have been called ' +
6459
6522
  timesMessage +
6460
6523
  '. It was called ' +
6461
- calls +
6524
+ callsCount +
6462
6525
  ' times.';
6463
6526
  return result;
6464
6527
  }
@@ -6514,6 +6577,11 @@ getJasmineRequireObj().toHaveBeenCalledWith = function(j$) {
6514
6577
  }
6515
6578
 
6516
6579
  if (matchersUtil.contains(actual.calls.allArgs(), expectedArgs)) {
6580
+ actual.calls
6581
+ .all()
6582
+ .filter(call => matchersUtil.equals(call.args, expectedArgs))
6583
+ .forEach(call => (call.verified = true));
6584
+
6517
6585
  result.pass = true;
6518
6586
  result.message = function() {
6519
6587
  return (
@@ -6605,6 +6673,127 @@ getJasmineRequireObj().toHaveClass = function(j$) {
6605
6673
  return toHaveClass;
6606
6674
  };
6607
6675
 
6676
+ getJasmineRequireObj().toHaveClasses = function(j$) {
6677
+ /**
6678
+ * {@link expect} the actual value to be a DOM element that has the expected classes
6679
+ * @function
6680
+ * @name matchers#toHaveClasses
6681
+ * @since 5.6.0
6682
+ * @param {Object} expected - The class names to test for
6683
+ * @example
6684
+ * const el = document.createElement('div');
6685
+ * el.className = 'foo bar baz';
6686
+ * expect(el).toHaveClasses(['bar', 'baz']);
6687
+ */
6688
+ function toHaveClasses(matchersUtil) {
6689
+ return {
6690
+ compare: function(actual, expected) {
6691
+ if (!isElement(actual)) {
6692
+ throw new Error(matchersUtil.pp(actual) + ' is not a DOM element');
6693
+ }
6694
+
6695
+ return {
6696
+ pass: expected.every(e => actual.classList.contains(e))
6697
+ };
6698
+ }
6699
+ };
6700
+ }
6701
+
6702
+ function isElement(maybeEl) {
6703
+ return (
6704
+ maybeEl && maybeEl.classList && j$.isFunction_(maybeEl.classList.contains)
6705
+ );
6706
+ }
6707
+
6708
+ return toHaveClasses;
6709
+ };
6710
+
6711
+ getJasmineRequireObj().toHaveNoOtherSpyInteractions = function(j$) {
6712
+ const getErrorMsg = j$.formatErrorMsg(
6713
+ '<toHaveNoOtherSpyInteractions>',
6714
+ 'expect(<spyObj>).toHaveNoOtherSpyInteractions()'
6715
+ );
6716
+
6717
+ /**
6718
+ * {@link expect} the actual (a {@link SpyObj}) spies to have not been called except interactions which was already tracked with `toHaveBeenCalled`.
6719
+ * @function
6720
+ * @name matchers#toHaveNoOtherSpyInteractions
6721
+ * @example
6722
+ * expect(mySpyObj).toHaveNoOtherSpyInteractions();
6723
+ * expect(mySpyObj).not.toHaveNoOtherSpyInteractions();
6724
+ */
6725
+ function toHaveNoOtherSpyInteractions(matchersUtil) {
6726
+ return {
6727
+ compare: function(actual) {
6728
+ const result = {};
6729
+
6730
+ if (!j$.isObject_(actual)) {
6731
+ throw new Error(
6732
+ getErrorMsg('Expected an object, but got ' + typeof actual + '.')
6733
+ );
6734
+ }
6735
+
6736
+ if (arguments.length > 1) {
6737
+ throw new Error(getErrorMsg('Does not take arguments'));
6738
+ }
6739
+
6740
+ result.pass = true;
6741
+ let hasSpy = false;
6742
+ const unexpectedCalls = [];
6743
+
6744
+ for (const spy of Object.values(actual)) {
6745
+ if (!j$.isSpy(spy)) {
6746
+ continue;
6747
+ }
6748
+
6749
+ hasSpy = true;
6750
+
6751
+ const unverifiedCalls = spy.calls
6752
+ .all()
6753
+ .filter(call => !call.verified);
6754
+
6755
+ if (unverifiedCalls.length > 0) {
6756
+ result.pass = false;
6757
+ }
6758
+
6759
+ unverifiedCalls.forEach(unverifiedCall => {
6760
+ unexpectedCalls.push([
6761
+ spy.and.identity,
6762
+ matchersUtil.pp(unverifiedCall.args)
6763
+ ]);
6764
+ });
6765
+ }
6766
+
6767
+ if (!hasSpy) {
6768
+ throw new Error(
6769
+ getErrorMsg(
6770
+ 'Expected an object with spies, but object has no spies.'
6771
+ )
6772
+ );
6773
+ }
6774
+
6775
+ if (result.pass) {
6776
+ result.message =
6777
+ "Expected a spy object to have other spy interactions but it didn't.";
6778
+ } else {
6779
+ const ppUnexpectedCalls = unexpectedCalls
6780
+ .map(([spyName, args]) => ` ${spyName} called with ${args}`)
6781
+ .join(',\n');
6782
+
6783
+ result.message =
6784
+ 'Expected a spy object to have no other spy interactions, but it had the following calls:\n' +
6785
+ ppUnexpectedCalls +
6786
+ '.';
6787
+ }
6788
+
6789
+ return result;
6790
+ }
6791
+ };
6792
+ }
6793
+
6794
+ return toHaveNoOtherSpyInteractions;
6795
+ };
6796
+
6608
6797
  getJasmineRequireObj().toHaveSize = function(j$) {
6609
6798
  /**
6610
6799
  * {@link expect} the actual size to be equal to the expected, using array-like length or object keys size.
@@ -9183,7 +9372,8 @@ getJasmineRequireObj().Spy = function(j$) {
9183
9372
  const callData = {
9184
9373
  object: context,
9185
9374
  invocationOrder: nextOrder(),
9186
- args: Array.prototype.slice.apply(args)
9375
+ args: Array.prototype.slice.apply(args),
9376
+ verified: false
9187
9377
  };
9188
9378
 
9189
9379
  callTracker.track(callData);
@@ -11041,5 +11231,5 @@ getJasmineRequireObj().UserContext = function(j$) {
11041
11231
  };
11042
11232
 
11043
11233
  getJasmineRequireObj().version = function() {
11044
- return '5.5.0';
11234
+ return '5.6.0';
11045
11235
  };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "jasmine-core",
3
3
  "license": "MIT",
4
- "version": "5.5.0",
4
+ "version": "5.6.0",
5
5
  "repository": {
6
6
  "type": "git",
7
7
  "url": "https://github.com/jasmine/jasmine.git"