Compare commits

..

16 Commits

Author SHA1 Message Date
Steve Gravrock
3de4512681 Bump version to 6.1.0
Some checks failed
Test in latest available Safari / build (push) Has been cancelled
2026-02-22 10:10:40 -08:00
Steve Gravrock
4bf333ed38 rm unnecessary and deprecated eslint-env comments 2026-02-21 11:15:57 -08:00
Steve Gravrock
4f5ef7c2d7 Drop support for Safari 16 and 17
Safari 16 and 17 runners are no longer reliably available in CI. Saucelabs
still provides them, but session creation failures have been frequent for
weeks now. When this has happened in the past, it's been a prelude to
Saucelabs dropping the affected Safari versions altogether.

We could live with retrying ~30-50% of test runs in the hope that things
might improve, but it's probably better to just rip the band-aid off.
2026-02-21 11:14:32 -08:00
Steve Gravrock
5de03beea1 Fix test failure in Node 20 and 22 parallel tests 2026-02-07 20:03:59 -08:00
Steve Gravrock
42baa422b3 Formatting 2026-02-07 18:36:36 -08:00
Steve Gravrock
6af5d24b3b Improve formatting of AggregateErrors 2026-02-07 18:22:12 -08:00
Steve Gravrock
b88ce2d49f Improve AggregateError specs
* Assert that the right inner stack traces are in the right places
* Drop the integration tests. All of the AggregateError-specific code
  is in ExceptionFormatter, so the integration tests just duplicate
  existing integration tests and the ExceptionFormatter specs.
2026-02-07 17:41:39 -08:00
Steve Gravrock
c216ae1d13 Merge branch 'puglyfe-aggregate-errors'
* Adds support for AggregateError
* Merges #2093 from @puglyfe
* Fixes #2063
2026-02-07 16:01:06 -08:00
Charley
319776d241 Report the constituent errors of an AggregateError
Fixes #2063
2026-02-07 11:16:57 -08:00
Steve Gravrock
1d0718dc2f Fix MAX_PRETTY_PRINT_CHARS default jsdoc in source code too 2026-01-19 14:58:15 -08:00
Steve Gravrock
929694310e Merge branch 'fixDefaultsJsDoc' of github.com:HolgerJeromin/jasmine
* Merges #2091 from @HolgerJeromin
2026-01-19 08:15:42 -08:00
Steve Gravrock
7379a3a11b Bump version to 6.0.1
Some checks failed
Test in latest available Safari / build (push) Has been cancelled
2026-01-19 07:59:36 -08:00
Holger Jeromin
4db18aafce Fix default MAX_PRETTY_PRINT_CHARS in JsDoc 2026-01-19 13:41:08 +01:00
Steve Gravrock
066669cfee Revert "Temporarily (I hope) disable testing against Safari 16 and 17"
This reverts commit 6755b03f12.
2026-01-18 20:51:20 -08:00
Steve Gravrock
87177d9d43 Fix browser ESM deprecation wraning
Previously, the warning was issued if jasmineRequire.core was called from
an ES module rather than being defined in an ES module.
2026-01-17 17:12:32 -08:00
Steve Gravrock
0c75a154a8 Fix typo 2026-01-17 12:00:58 -08:00
13 changed files with 294 additions and 19 deletions

View File

@@ -30,7 +30,7 @@ Microsoft Edge) as well as Node.
| Environment | Supported versions |
|-------------------|----------------------------------|
| Node | 20, 22, 24 |
| Safari | 16*, 17*, 26* |
| Safari | 26* |
| Chrome | Evergreen |
| Firefox | Evergreen, 102*, 115*, 128*, 140 |
| Edge | Evergreen |

View File

@@ -43,6 +43,9 @@ var getJasmineRequireObj = (function() {
return jasmineRequire;
}
const loadedAsBrowserEsm =
globalThis.document && !globalThis.document.currentScript;
getJasmineRequire().core = function(jRequire) {
const j$ = {};
Object.defineProperty(j$, 'private', {
@@ -124,8 +127,7 @@ var getJasmineRequireObj = (function() {
j$.private.matchers = jRequire.requireMatchers(jRequire, j$);
j$.private.asyncMatchers = jRequire.requireAsyncMatchers(jRequire, j$);
j$.private.loadedAsBrowserEsm =
globalThis.document && !globalThis.document.currentScript;
j$.private.loadedAsBrowserEsm = loadedAsBrowserEsm;
j$.private.deprecateMonkeyPatching(j$, [
// These are meant to be set by users.
@@ -220,7 +222,7 @@ getJasmineRequireObj().base = function(j$, jasmineGlobal) {
* Maximum number of characters to display when pretty printing objects.
* Characters past this number will be ellipised.
* @name jasmine.MAX_PRETTY_PRINT_CHARS
* @default 100
* @default 1000
* @since 2.9.0
*/
j$.MAX_PRETTY_PRINT_CHARS = 1000;
@@ -4001,7 +4003,8 @@ getJasmineRequireObj().ExceptionFormatter = function(j$) {
'lineNumber',
'column',
'description',
'jasmineMessage'
'jasmineMessage',
'errors'
];
function ExceptionFormatter(options) {
@@ -4067,6 +4070,19 @@ getJasmineRequireObj().ExceptionFormatter = function(j$) {
lines = lines.concat(substack);
}
if (Array.isArray(error.errors)) {
for (let i = 0; i < error.errors.length; i++) {
if (error.errors[i] instanceof Error) {
lines.push('');
const substack = this.stack_(error.errors[i], {
messageHandling: 'require'
});
substack[0] = 'Error ' + (i + 1) + ': ' + substack[0];
lines = lines.concat(substack.map(x => ' ' + x));
}
}
}
return lines;
};
@@ -12406,5 +12422,5 @@ getJasmineRequireObj().UserContext = function(j$) {
};
getJasmineRequireObj().version = function() {
return '6.0.0';
return '6.1.0';
};

View File

@@ -1,7 +1,7 @@
{
"name": "jasmine-core",
"license": "MIT",
"version": "6.0.0",
"version": "6.1.0",
"repository": {
"type": "git",
"url": "https://github.com/jasmine/jasmine.git"

View File

@@ -10,7 +10,7 @@ jasmine-core's internal state, removing ambiguities from the reporter API, and
warning about monkey patching.
6.x is intended to ba a relatively short-lived, transitional series. It is
compatible with the current versions of karam-jasmine and other legacy Angular
compatible with the current versions of karma-jasmine and other legacy Angular
tools but emits deprecation warnings when used with them. 7.0 will drop
compatibility with those tools. If you use Karma in a non-Angular context,
consider migrating to a maintained alternative such as jasmine-browser-runner or

29
release_notes/6.0.1.md Normal file
View File

@@ -0,0 +1,29 @@
# Jasmine Core 6.0.1 Release Notes
## Bug fixes
* Don't emit a deprecation warning when `jasmineRequire.core` is called from an
ES module
## Supported environments
This version has been tested in the following environments.
| Environment | Supported versions |
|-------------------|--------------------------------|
| Node | 20, 22, 24 |
| Safari** | 16, 17, 26.2 |
| Chrome | 143* |
| Firefox | 102**, 115**, 128**, 140, 147* |
| Edge | 143* |
\* Evergreen browser. Each version of Jasmine is tested against the latest
version available at release time.<br>
\** Supported on a best-effort basis. Support for these versions may be dropped
if it becomes impractical, and bugs affecting only these versions may not be
treated as release blockers.
------
_Release Notes generated with _[Anchorman](http://github.com/infews/anchorman)_

40
release_notes/6.1.0.md Normal file
View File

@@ -0,0 +1,40 @@
# Jasmine Core 6.1.0 Release Notes
## Changes to supported environments
* Safari 16 and 17 are no longer supported. Although jasmine-core may still work
in those versions, we no longer have a reliable way to test them and won't try
to maintain compatibility with them in future releases.
## New features
* Report the underlying errors that make up an `AggregateError`.
* Merges [#2093](https://github.com/jasmine/jasmine/pull/2093) from @puglyfe
* Fixes [#2063](https://github.com/jasmine/jasmine/issues/2063)
## Documentation improvements
* Fix default MAX_PRETTY_PRINT_CHARS in JsDoc.
* Merges [#2091](https://github.com/jasmine/jasmine/pull/2091) from @HolgerJeromin
## Supported environments
This version has been tested in the following environments.
| Environment | Supported versions |
|-------------------|--------------------------------|
| Node | 20, 22, 24 |
| Safari | 26.3** |
| Chrome | 144* |
| Firefox | 102**, 115**, 128**, 140, 147* |
| Edge | 144* |
\* Evergreen browser. Each version of Jasmine is tested against the latest
version available at release time.<br>
\** Supported on a best-effort basis. Support for these versions may be dropped
if it becomes impractical, and bugs affecting only these versions may not be
treated as release blockers.
------
_Release Notes generated with _[Anchorman](http://github.com/infews/anchorman)_

View File

@@ -1,8 +1,8 @@
#!/bin/sh
# Run tests in supported browsers that are available on Saucelabs.
# Note: The latest Safari version is tested via GitHub Actions because Saucelabs
# only makes it available to paid enterprise accounts. See
# Note: Safari is tested via GitHub Actions because Saucelabs only makes Safari
# 18 and later available to paid enterprise accounts. See
# .github/workflows/safari.yml.
run_browser() {
@@ -44,9 +44,6 @@ else
fi
run_browser firefox 102
# run_browser safari 17
# run_browser safari 16
run_browser MicrosoftEdge latest
echo

View File

@@ -346,5 +346,184 @@ describe('ExceptionFormatter', function() {
}).not.toThrowError();
});
});
describe('when the error has an errors array (AggregateError)', function() {
it('includes all aggregated errors in the stack trace', function() {
const subject = new privateUnderTest.ExceptionFormatter();
const error1 = (function fn1() {
return new Error('first error');
})();
const error2 = (function fn2() {
return new Error('second error');
})();
const aggregateError = (function fn3() {
return new Error('Multiple errors occurred');
})();
aggregateError.errors = [error1, error2];
const lines = subject.stack(aggregateError).split('\n');
// TODO: be consistent across environments about whether the message is
// included in the stack trace
if (lines[0] === 'Error: Multiple errors occurred') {
lines.shift();
}
// Exclude lines that vary from environment to environment
const filteredLines = lines.filter(
x =>
!x.includes('/jasmine.js:') &&
// Some Node 20 and 22 minors when running in parallel
!x.includes('process.processTicksAndRejections')
);
for (let i = 0; i < filteredLines.length; i++) {
jasmine.debugLog(`Line ${i} after filtering: ${filteredLines[i]}`);
}
// Inexact matching because stack frame formatting varies from runtime
// to runtime
const expectedPatterns = [
// Overall error
/fn3.*ExceptionFormatterSpec\.js/,
/ExceptionFormatterSpec\.js/,
/^$/,
// First nested error
/^ Error 1: Error: first error$/,
/^ .*fn1.*ExceptionFormatterSpec\.js/,
/^ .*ExceptionFormatterSpec\.js/,
/^$/,
// Second nested error
/^ .*Error 2: Error: second error$/,
/^ .*fn2.*ExceptionFormatterSpec\.js/,
/^ .*ExceptionFormatterSpec\.js/
];
expect(filteredLines).toEqual(
expectedPatterns.map(p => jasmine.stringMatching(p))
);
});
it('handles empty errors array', function() {
const subject = new privateUnderTest.ExceptionFormatter();
const aggregateError = new Error('No errors');
aggregateError.errors = [];
expect(function() {
subject.stack(aggregateError);
}).not.toThrowError();
});
it('handles nested AggregateError', function() {
const subject = new privateUnderTest.ExceptionFormatter();
const innerError1 = new Error('inner error 1');
const innerError2 = new Error('inner error 2');
const innerAggregate = new Error('Inner aggregate');
innerAggregate.errors = [innerError1, innerError2];
const outerError = new Error('outer error');
const outerAggregate = new Error('Outer aggregate');
outerAggregate.errors = [innerAggregate, outerError];
const lines = subject.stack(outerAggregate).split('\n');
const innerAggMsgIx = lines.findIndex(line =>
line.includes('Error 1: Error: Inner aggregate')
);
expect(innerAggMsgIx).toBeGreaterThan(-1);
const innerError1MsgIx = lines.findIndex(line =>
line.includes('Error 1: Error: inner error 1')
);
expect(innerError1MsgIx).toBeGreaterThan(innerAggMsgIx);
const innerError2MsgIx = lines.findIndex(line =>
line.includes('Error 2: Error: inner error 2')
);
expect(innerError2MsgIx).toBeGreaterThan(innerError1MsgIx);
const outerErrorMsgIx = lines.findIndex(line =>
line.includes('Error 2: Error: outer error')
);
expect(outerErrorMsgIx).toBeGreaterThan(innerError2MsgIx);
});
it('handles AggregateError containing error with cause', function() {
const subject = new privateUnderTest.ExceptionFormatter();
const rootCause = new Error('root cause');
const errorWithCause = new Error('error with cause', {
cause: rootCause
});
const aggregateError = new Error('Aggregate with cause chain');
aggregateError.errors = [errorWithCause];
const lines = subject.stack(aggregateError).split('\n');
const error1MsgIx = lines.findIndex(line =>
line.includes('Error 1: Error: error with cause')
);
expect(error1MsgIx).toBeGreaterThan(-1);
const causeMsgIx = lines.findIndex(line =>
line.includes('Caused by: Error: root cause')
);
expect(causeMsgIx).toBeGreaterThan(error1MsgIx);
});
it('skips non-Error items in errors array', function() {
const subject = new privateUnderTest.ExceptionFormatter();
const error1 = new Error('real error');
const aggregateError = new Error('Mixed array');
aggregateError.errors = [
error1,
'string error',
{ message: 'object error' },
null,
undefined,
42
];
const lines = subject.stack(aggregateError).split('\n');
const error1MsgIx = lines.findIndex(line =>
line.includes('Error 1: Error: real error')
);
expect(error1MsgIx).toBeGreaterThan(-1);
const hasStringError = lines.some(line =>
line.includes('string error')
);
expect(hasStringError).toBe(false);
const hasObjectError = lines.some(line =>
line.includes('object error')
);
expect(hasObjectError).toBe(false);
});
it('works with native AggregateError constructor', function() {
const subject = new privateUnderTest.ExceptionFormatter();
const error1 = new Error('first error');
const error2 = new Error('second error');
const aggregateError = new AggregateError(
[error1, error2],
'Multiple errors'
);
const lines = subject.stack(aggregateError).split('\n');
const error1MsgIx = lines.findIndex(line =>
line.includes('Error 1: Error: first error')
);
expect(error1MsgIx).toBeGreaterThan(-1);
const error2MsgIx = lines.findIndex(line =>
line.includes('Error 2: Error: second error')
);
expect(error2MsgIx).toBeGreaterThan(error1MsgIx);
});
});
});
});

View File

@@ -1,4 +1,3 @@
/* eslint-env node, es6 */
const path = require('path'),
jasmineBrowser = require('jasmine-browser-runner'),
jasmineCore = require('../../lib/jasmine-core');

View File

@@ -1,4 +1,3 @@
/* eslint-env node, es6 */
module.exports = {
srcDir: 'src',
srcFiles: [

View File

@@ -11,7 +11,8 @@ getJasmineRequireObj().ExceptionFormatter = function(j$) {
'lineNumber',
'column',
'description',
'jasmineMessage'
'jasmineMessage',
'errors'
];
function ExceptionFormatter(options) {
@@ -77,6 +78,19 @@ getJasmineRequireObj().ExceptionFormatter = function(j$) {
lines = lines.concat(substack);
}
if (Array.isArray(error.errors)) {
for (let i = 0; i < error.errors.length; i++) {
if (error.errors[i] instanceof Error) {
lines.push('');
const substack = this.stack_(error.errors[i], {
messageHandling: 'require'
});
substack[0] = 'Error ' + (i + 1) + ': ' + substack[0];
lines = lines.concat(substack.map(x => ' ' + x));
}
}
}
return lines;
};

View File

@@ -22,7 +22,7 @@ getJasmineRequireObj().base = function(j$, jasmineGlobal) {
* Maximum number of characters to display when pretty printing objects.
* Characters past this number will be ellipised.
* @name jasmine.MAX_PRETTY_PRINT_CHARS
* @default 100
* @default 1000
* @since 2.9.0
*/
j$.MAX_PRETTY_PRINT_CHARS = 1000;

View File

@@ -19,6 +19,9 @@ var getJasmineRequireObj = (function() {
return jasmineRequire;
}
const loadedAsBrowserEsm =
globalThis.document && !globalThis.document.currentScript;
getJasmineRequire().core = function(jRequire) {
const j$ = {};
Object.defineProperty(j$, 'private', {
@@ -100,8 +103,7 @@ var getJasmineRequireObj = (function() {
j$.private.matchers = jRequire.requireMatchers(jRequire, j$);
j$.private.asyncMatchers = jRequire.requireAsyncMatchers(jRequire, j$);
j$.private.loadedAsBrowserEsm =
globalThis.document && !globalThis.document.currentScript;
j$.private.loadedAsBrowserEsm = loadedAsBrowserEsm;
j$.private.deprecateMonkeyPatching(j$, [
// These are meant to be set by users.