From 14272d51201aa99b920a8c4491a96ec8db50f63b Mon Sep 17 00:00:00 2001 From: Nicolas DUBIEN Date: Tue, 28 Feb 2023 15:14:57 +0000 Subject: [PATCH 1/3] feat(jest-inline-message): Support Error.cause with jasmine too --- .../__snapshots__/failures.test.ts.snap | 63 +++++++++---------- e2e/__tests__/failures.test.ts | 26 +++++--- .../jest-jasmine2/src/jasmineAsyncInstall.ts | 14 +++-- packages/jest-message-util/src/index.ts | 30 +++++++-- 4 files changed, 81 insertions(+), 52 deletions(-) diff --git a/e2e/__tests__/__snapshots__/failures.test.ts.snap b/e2e/__tests__/__snapshots__/failures.test.ts.snap index 4a3f562eb25f..14c7531a152b 100644 --- a/e2e/__tests__/__snapshots__/failures.test.ts.snap +++ b/e2e/__tests__/__snapshots__/failures.test.ts.snap @@ -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`] = ` diff --git a/e2e/__tests__/failures.test.ts b/e2e/__tests__/failures.test.ts index 98f72a0257f3..031035e624ca 100644 --- a/e2e/__tests__/failures.test.ts +++ b/e2e/__tests__/failures.test.ts @@ -6,7 +6,6 @@ */ import * as path from 'path'; -import {isJestJasmineRun} from '@jest/test-utils'; import {extractSummary, runYarnInstall} from '../Utils'; import runJest from '../runJest'; @@ -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']); diff --git a/packages/jest-jasmine2/src/jasmineAsyncInstall.ts b/packages/jest-jasmine2/src/jasmineAsyncInstall.ts index 71d7662f28be..08f839402259 100644 --- a/packages/jest-jasmine2/src/jasmineAsyncInstall.ts +++ b/packages/jest-jasmine2/src/jasmineAsyncInstall.ts @@ -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. @@ -85,6 +85,9 @@ function promisifyLifeCycleFunction( if (message) { extraError.message = message; + extraError.stack = + originalExtraErrorStack && + originalExtraErrorStack.replace('Error: ', `Error: ${message}`); } done.fail(checkIsError ? error : extraError); }); @@ -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; @@ -159,6 +162,9 @@ function promisifyIt( if (message) { extraError.message = message; + extraError.stack = + originalExtraErrorStack && + originalExtraErrorStack.replace('Error: ', `Error: ${message}`); } if (jasmine.Spec.isPendingSpecException(error)) { diff --git a/packages/jest-message-util/src/index.ts b/packages/jest-message-util/src/index.ts index de851ea1d05f..37078cbc842b 100644 --- a/packages/jest-message-util/src/index.ts +++ b/packages/jest-message-util/src/index.ts @@ -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, config: StackTraceConfig, @@ -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 + From 7d0d68819db6f98d88e5dc0ee461bde99ca81634 Mon Sep 17 00:00:00 2001 From: Nicolas DUBIEN Date: Tue, 28 Feb 2023 15:16:25 +0000 Subject: [PATCH 2/3] alter changelog --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f4f5bbe26c2b..418e6c3017a0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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 From e1fc7396a7a33db6619f2e627bbfde43b2175299 Mon Sep 17 00:00:00 2001 From: Nicolas DUBIEN Date: Tue, 28 Feb 2023 16:03:41 +0000 Subject: [PATCH 3/3] update snapshots --- e2e/__tests__/__snapshots__/testFailingJasmine.test.ts.snap | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/e2e/__tests__/__snapshots__/testFailingJasmine.test.ts.snap b/e2e/__tests__/__snapshots__/testFailingJasmine.test.ts.snap index a569f91ac1eb..0f925dc80110 100644 --- a/e2e/__tests__/__snapshots__/testFailingJasmine.test.ts.snap +++ b/e2e/__tests__/__snapshots__/testFailingJasmine.test.ts.snap @@ -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) @@ -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)