Skip to content

Commit

Permalink
feat(jest-inline-message): Support Error.cause with jasmine too (#13966)
Browse files Browse the repository at this point in the history
  • Loading branch information
dubzzz committed Mar 1, 2023
1 parent d6d4575 commit 06f9fa1
Show file tree
Hide file tree
Showing 6 changed files with 84 additions and 55 deletions.
2 changes: 1 addition & 1 deletion CHANGELOG.md
Expand Up @@ -8,7 +8,7 @@
- `[jest-config]` Add `openHandlesTimeout` option to configure possible open handles warning. ([#13875](https://github.com/facebook/jest/pull/13875))
- `[@jest/create-cache-key-function]` Allow passing `length` argument to `createCacheKey()` function and set its default value to `16` on Windows ([#13827](https://github.com/facebook/jest/pull/13827))
- `[jest-message-util]` Add support for [AggregateError](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/AggregateError) ([#13946](https://github.com/facebook/jest/pull/13946) & [#13947](https://github.com/facebook/jest/pull/13947))
- `[jest-message-util]` Add support for [Error causes](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error/cause) in `test` and `it` ([#13935](https://github.com/facebook/jest/pull/13935))
- `[jest-message-util]` Add support for [Error causes](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error/cause) in `test` and `it` ([#13935](https://github.com/facebook/jest/pull/13935) & [#13966](https://github.com/facebook/jest/pull/13966))
- `[jest-worker]` Add `start` method to worker farms ([#13937](https://github.com/facebook/jest/pull/13937))

### Fixes
Expand Down
63 changes: 30 additions & 33 deletions e2e/__tests__/__snapshots__/failures.test.ts.snap
Expand Up @@ -493,39 +493,36 @@ exports[`works with error with cause 1`] = `
`;
exports[`works with error with cause thrown outside tests 1`] = `
"FAIL __tests__/errorWithCauseInDescribe.test.js
● Test suite failed to run
error during f
10 |
11 | function buildErrorWithCause(message: string, opts: {cause: unknown}): Error {
> 12 | const error = new Error(message, opts);
| ^
13 | if (opts.cause !== error.cause) {
14 | // Error with cause not supported in legacy versions of node, we just polyfill it
15 | Object.assign(error, opts);
at buildErrorWithCause (__tests__/errorWithCauseInDescribe.test.js:12:17)
at buildErrorWithCause (__tests__/errorWithCauseInDescribe.test.js:27:11)
at f (__tests__/errorWithCauseInDescribe.test.js:32:3)
at Object.describe (__tests__/errorWithCauseInDescribe.test.js:31:1)
Cause:
error during g
19 |
20 | function g() {
> 21 | throw new Error('error during g');
| ^
22 | }
23 | function f() {
24 | try {
at g (__tests__/errorWithCauseInDescribe.test.js:21:9)
at g (__tests__/errorWithCauseInDescribe.test.js:25:5)
at f (__tests__/errorWithCauseInDescribe.test.js:32:3)
at Object.describe (__tests__/errorWithCauseInDescribe.test.js:31:1)"
"error during f
10 |
11 | function buildErrorWithCause(message: string, opts: {cause: unknown}): Error {
> 12 | const error = new Error(message, opts);
| ^
13 | if (opts.cause !== error.cause) {
14 | // Error with cause not supported in legacy versions of node, we just polyfill it
15 | Object.assign(error, opts);
at buildErrorWithCause (__tests__/errorWithCauseInDescribe.test.js:12:17)
at buildErrorWithCause (__tests__/errorWithCauseInDescribe.test.js:27:11)
at f (__tests__/errorWithCauseInDescribe.test.js:32:3)
at Object.describe (__tests__/errorWithCauseInDescribe.test.js:31:1)
Cause:
error during g
19 |
20 | function g() {
> 21 | throw new Error('error during g');
| ^
22 | }
23 | function f() {
24 | try {
at g (__tests__/errorWithCauseInDescribe.test.js:21:9)
at g (__tests__/errorWithCauseInDescribe.test.js:25:5)
at f (__tests__/errorWithCauseInDescribe.test.js:32:3)
at Object.describe (__tests__/errorWithCauseInDescribe.test.js:31:1)"
`;
exports[`works with node assert 1`] = `
Expand Down
4 changes: 2 additions & 2 deletions e2e/__tests__/__snapshots__/testFailingJasmine.test.ts.snap
Expand Up @@ -46,7 +46,7 @@ FAIL __tests__/worksWithConcurrentMode.test.js
15 | });
16 |
at Function.failing (../../packages/jest-jasmine2/build/jasmineAsyncInstall.js:164:11)
at Function.failing (../../packages/jest-jasmine2/build/jasmineAsyncInstall.js:166:11)
at Suite.failing (__tests__/worksWithConcurrentMode.test.js:13:17)
at Object.describe (__tests__/worksWithConcurrentMode.test.js:8:1)
Expand Down Expand Up @@ -80,7 +80,7 @@ FAIL __tests__/worksWithConcurrentOnlyMode.test.js
15 | });
16 |
at Function.failing (../../packages/jest-jasmine2/build/jasmineAsyncInstall.js:164:11)
at Function.failing (../../packages/jest-jasmine2/build/jasmineAsyncInstall.js:166:11)
at Suite.failing (__tests__/worksWithConcurrentOnlyMode.test.js:13:22)
at Object.describe (__tests__/worksWithConcurrentOnlyMode.test.js:8:1)
Expand Down
26 changes: 16 additions & 10 deletions e2e/__tests__/failures.test.ts
Expand Up @@ -6,7 +6,6 @@
*/

import * as path from 'path';
import {isJestJasmineRun} from '@jest/test-utils';
import {extractSummary, runYarnInstall} from '../Utils';
import runJest from '../runJest';

Expand Down Expand Up @@ -94,22 +93,29 @@ test('works with snapshot failures with hint', () => {
).toMatchSnapshot();
});

(isJestJasmineRun() ? test.skip : test)('works with error with cause', () => {
test('works with error with cause', () => {
const {stderr} = runJest(dir, ['errorWithCause.test.js']);
const summary = normalizeDots(cleanStderr(stderr));

expect(summary).toMatchSnapshot();
});

(isJestJasmineRun() ? test.skip : test)(
'works with error with cause thrown outside tests',
() => {
const {stderr} = runJest(dir, ['errorWithCauseInDescribe.test.js']);
const summary = normalizeDots(cleanStderr(stderr));
test('works with error with cause thrown outside tests', () => {
const {stderr} = runJest(dir, ['errorWithCauseInDescribe.test.js']);
const summary = normalizeDots(cleanStderr(stderr));

const sanitizedSummary = summary
.replace(/ Suite\.f /g, ' f ') // added by jasmine runner
.split('\n')
.map(line => line.trim()) // jasmine runner does not come with the same indentation
.join('\n');

expect(summary).toMatchSnapshot();
},
);
expect(
// jasmine runner differ from circus one in this case, we just start
// the comparison when the stack starts to be reported
sanitizedSummary.substring(sanitizedSummary.indexOf('error during f')),
).toMatchSnapshot();
});

test('errors after test has completed', () => {
const {stderr} = runJest(dir, ['errorAfterTestComplete.test.js']);
Expand Down
14 changes: 10 additions & 4 deletions packages/jest-jasmine2/src/jasmineAsyncInstall.ts
Expand Up @@ -69,8 +69,8 @@ function promisifyLifeCycleFunction(
// in the stack in the Error object. This line stringifies the stack
// property to allow garbage-collecting objects on the stack
// https://crbug.com/v8/7142
// eslint-disable-next-line no-self-assign
extraError.stack = extraError.stack;
const originalExtraErrorStack = extraError.stack;
extraError.stack = originalExtraErrorStack;

// We make *all* functions async and run `done` right away if they
// didn't return a promise.
Expand All @@ -85,6 +85,9 @@ function promisifyLifeCycleFunction(

if (message) {
extraError.message = message;
extraError.stack =
originalExtraErrorStack &&
originalExtraErrorStack.replace('Error: ', `Error: ${message}`);
}
done.fail(checkIsError ? error : extraError);
});
Expand Down Expand Up @@ -146,8 +149,8 @@ function promisifyIt(
// in the stack in the Error object. This line stringifies the stack
// property to allow garbage-collecting objects on the stack
// https://crbug.com/v8/7142
// eslint-disable-next-line no-self-assign
extraError.stack = extraError.stack;
const originalExtraErrorStack = extraError.stack;
extraError.stack = originalExtraErrorStack;

const asyncJestTest = function (done: DoneFn) {
const wrappedFn = isGeneratorFn(fn) ? co.wrap(fn) : fn;
Expand All @@ -159,6 +162,9 @@ function promisifyIt(

if (message) {
extraError.message = message;
extraError.stack =
originalExtraErrorStack &&
originalExtraErrorStack.replace('Error: ', `Error: ${message}`);
}

if (jasmine.Spec.isPendingSpecException(error)) {
Expand Down
30 changes: 25 additions & 5 deletions packages/jest-message-util/src/index.ts
Expand Up @@ -433,6 +433,27 @@ function formatErrorStack(
return `${message}\n${stack}${cause}`;
}

function failureDetailsToErrorOrStack(
failureDetails: unknown,
content: string,
): Error | string {
if (!failureDetails) {
return content;
}
if (types.isNativeError(failureDetails) || failureDetails instanceof Error) {
return failureDetails; // receiving raw errors for jest-circus
}
if (
typeof failureDetails === 'object' &&
'error' in failureDetails &&
(types.isNativeError(failureDetails.error) ||
failureDetails.error instanceof Error)
) {
return failureDetails.error; // receiving instances of FailedAssertion for jest-jasmine
}
return content;
}

export const formatResultsErrors = (
testResults: Array<TestResult.AssertionResult>,
config: StackTraceConfig,
Expand All @@ -459,11 +480,10 @@ export const formatResultsErrors = (

return failedResults
.map(({result, content, failureDetails}) => {
const rootErrorOrStack: Error | string =
failureDetails &&
(types.isNativeError(failureDetails) || failureDetails instanceof Error)
? failureDetails
: content;
const rootErrorOrStack = failureDetailsToErrorOrStack(
failureDetails,
content,
);

const title = `${chalk.bold.red(
TITLE_INDENT +
Expand Down

0 comments on commit 06f9fa1

Please sign in to comment.