From 86ee73c7704309b4b717b906c1c5e494a843b669 Mon Sep 17 00:00:00 2001 From: Nitin Kumar Date: Sun, 25 Oct 2020 11:06:17 +0530 Subject: [PATCH 01/16] fix(jest-jasmine2): don't assume stack to be a string always --- CHANGELOG.md | 1 + .../expectationResultFactory.test.ts.snap | 6 ++++++ .../src/__tests__/expectationResultFactory.test.ts | 12 ++++++++++++ packages/jest-jasmine2/src/reporter.ts | 12 ++++++++---- 4 files changed, 27 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bc4c3c1f8bde..77392ef3338a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ ### Fixes - `[expect]` Stop modifying the sample in `expect.objectContaining()` ([#10711](https://github.com/facebook/jest/pull/10711)) +- `[jest-jasmine2]` fix: don't assume stack to be a string always ([#10697](https://github.com/facebook/jest/pull/10697)) ### Chore & Maintenance diff --git a/packages/jest-jasmine2/src/__tests__/__snapshots__/expectationResultFactory.test.ts.snap b/packages/jest-jasmine2/src/__tests__/__snapshots__/expectationResultFactory.test.ts.snap index 73fd8445e1d2..f094459f5f43 100644 --- a/packages/jest-jasmine2/src/__tests__/__snapshots__/expectationResultFactory.test.ts.snap +++ b/packages/jest-jasmine2/src/__tests__/__snapshots__/expectationResultFactory.test.ts.snap @@ -1,5 +1,11 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP +exports[`expectationResultFactory returns the result if failed (with \`error.stack\` not as a string). 1`] = ` +"thrown: Object { + \\"stack\\": Array [], +}" +`; + exports[`expectationResultFactory returns the result if passed. 1`] = ` Object { "error": undefined, diff --git a/packages/jest-jasmine2/src/__tests__/expectationResultFactory.test.ts b/packages/jest-jasmine2/src/__tests__/expectationResultFactory.test.ts index 59cebccb4cd9..7b00492e5edb 100644 --- a/packages/jest-jasmine2/src/__tests__/expectationResultFactory.test.ts +++ b/packages/jest-jasmine2/src/__tests__/expectationResultFactory.test.ts @@ -78,4 +78,16 @@ describe('expectationResultFactory', () => { const result = expectationResultFactory(options); expect(result.message).toEqual('Expected `Pass`, received `Fail`.'); }); + + it('returns the result if failed (with `error.stack` not as a string).', () => { + const options = { + actual: 'Fail', + error: {stack: []}, + expected: 'Pass', + matcherName: 'testMatcher', + passed: false, + }; + const result = expectationResultFactory(options); + expect(result.message).toMatchSnapshot(); + }); }); diff --git a/packages/jest-jasmine2/src/reporter.ts b/packages/jest-jasmine2/src/reporter.ts index 2bcb0ad79c35..9829f1db7805 100644 --- a/packages/jest-jasmine2/src/reporter.ts +++ b/packages/jest-jasmine2/src/reporter.ts @@ -113,15 +113,19 @@ export default class Jasmine2Reporter implements Reporter { return this._resultsPromise; } - private _addMissingMessageToStack(stack: string, message?: string) { + private _addMissingMessageToStack(stack: unknown, message?: string) { // Some errors (e.g. Angular injection error) don't prepend error.message // to stack, instead the first line of the stack is just plain 'Error' const ERROR_REGEX = /^Error:?\s*\n/; - if (stack && message && !stack.includes(message)) { - return message + stack.replace(ERROR_REGEX, '\n'); + if (typeof stack === 'string') { + if (stack && message && !stack.includes(message)) { + return message + stack.replace(ERROR_REGEX, '\n'); + } + return stack; + } else { + return `${stack}`; } - return stack; } private _extractSpecResults( From e64096360a4804e428a63e9b49624dcc6a02473f Mon Sep 17 00:00:00 2001 From: Nitin Kumar Date: Mon, 26 Oct 2020 10:54:47 +0530 Subject: [PATCH 02/16] add tests --- e2e/__tests__/__snapshots__/failures.test.ts.snap | 7 +++++++ e2e/__tests__/failures.test.ts | 2 ++ .../__tests__/throwObjectWithStackProp.test.js | 11 +++++++++++ .../expectationResultFactory.test.ts.snap | 2 +- .../src/__tests__/expectationResultFactory.test.ts | 2 +- packages/jest-message-util/src/index.ts | 7 +++---- 6 files changed, 25 insertions(+), 6 deletions(-) create mode 100644 e2e/failures/__tests__/throwObjectWithStackProp.test.js diff --git a/e2e/__tests__/__snapshots__/failures.test.ts.snap b/e2e/__tests__/__snapshots__/failures.test.ts.snap index 14e7b06d4827..56a6246cf019 100644 --- a/e2e/__tests__/__snapshots__/failures.test.ts.snap +++ b/e2e/__tests__/__snapshots__/failures.test.ts.snap @@ -254,6 +254,13 @@ FAIL __tests__/duringTests.test.js at Object.test (__tests__/duringTests.test.js:45:1) `; +exports[`not throwing Error objects 6`] = ` +FAIL __tests__/throwObjectWithStackProp.test.js + ● Test suite failed to run + + 42 +`; + exports[`works with assertions in separate files 1`] = ` FAIL __tests__/testMacro.test.js ✕ use some imported macro to make assertion diff --git a/e2e/__tests__/failures.test.ts b/e2e/__tests__/failures.test.ts index 70d05a6a0d62..2302e1b04df1 100644 --- a/e2e/__tests__/failures.test.ts +++ b/e2e/__tests__/failures.test.ts @@ -51,6 +51,8 @@ test('not throwing Error objects', () => { } expect(wrap(cleanStderr(stderr))).toMatchSnapshot(); + stderr = runJest(dir, ['throwObjectWithStackProp.test.js']).stderr; + expect(wrap(cleanStderr(stderr))).toMatchSnapshot(); }); test('works with node assert', () => { diff --git a/e2e/failures/__tests__/throwObjectWithStackProp.test.js b/e2e/failures/__tests__/throwObjectWithStackProp.test.js new file mode 100644 index 000000000000..5d672f0fcea7 --- /dev/null +++ b/e2e/failures/__tests__/throwObjectWithStackProp.test.js @@ -0,0 +1,11 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +'use strict'; + +// eslint-disable-next-line no-throw-literal +throw {stack: 42}; \ No newline at end of file diff --git a/packages/jest-jasmine2/src/__tests__/__snapshots__/expectationResultFactory.test.ts.snap b/packages/jest-jasmine2/src/__tests__/__snapshots__/expectationResultFactory.test.ts.snap index f094459f5f43..dd2fc2c56500 100644 --- a/packages/jest-jasmine2/src/__tests__/__snapshots__/expectationResultFactory.test.ts.snap +++ b/packages/jest-jasmine2/src/__tests__/__snapshots__/expectationResultFactory.test.ts.snap @@ -2,7 +2,7 @@ exports[`expectationResultFactory returns the result if failed (with \`error.stack\` not as a string). 1`] = ` "thrown: Object { - \\"stack\\": Array [], + \\"stack\\": 42, }" `; diff --git a/packages/jest-jasmine2/src/__tests__/expectationResultFactory.test.ts b/packages/jest-jasmine2/src/__tests__/expectationResultFactory.test.ts index 7b00492e5edb..8fb9e28fd1d7 100644 --- a/packages/jest-jasmine2/src/__tests__/expectationResultFactory.test.ts +++ b/packages/jest-jasmine2/src/__tests__/expectationResultFactory.test.ts @@ -82,7 +82,7 @@ describe('expectationResultFactory', () => { it('returns the result if failed (with `error.stack` not as a string).', () => { const options = { actual: 'Fail', - error: {stack: []}, + error: {stack: 42}, expected: 'Pass', matcherName: 'testMatcher', passed: false, diff --git a/packages/jest-message-util/src/index.ts b/packages/jest-message-util/src/index.ts index 417b2904effb..59bdfd1c9b52 100644 --- a/packages/jest-message-util/src/index.ts +++ b/packages/jest-message-util/src/index.ts @@ -380,7 +380,7 @@ const removeBlankErrorLine = (str: string) => // Error object, so we have to regexp out the message from the stack string // to format it. export const separateMessageFromStack = ( - content: string, + content: unknown, ): {message: string; stack: string} => { if (!content) { return {message: '', stack: ''}; @@ -390,9 +390,8 @@ export const separateMessageFromStack = ( // (maybe it's a code frame instead), just the first non-empty line. // If the error is a plain "Error:" instead of a SyntaxError or TypeError we // remove the prefix from the message because it is generally not useful. - const messageMatch = content.match( - /^(?:Error: )?([\s\S]*?(?=\n\s*at\s.*:\d*:\d*)|\s*.*)([\s\S]*)$/, - ); + const ERROR_REGEXP = /^(?:Error: )?([\s\S]*?(?=\n\s*at\s.*:\d*:\d*)|\s*.*)([\s\S]*)$/; + const messageMatch = typeof content !== 'string' ? `${content}`.match(ERROR_REGEXP) : content.match(ERROR_REGEXP); if (!messageMatch) { // For typescript throw new Error('If you hit this error, the regex above is buggy.'); From 1554787feb30e51b1d45d99a68b0dfc56ea44776 Mon Sep 17 00:00:00 2001 From: Nitin Kumar Date: Mon, 26 Oct 2020 10:57:29 +0530 Subject: [PATCH 03/16] fix: lint --- e2e/failures/__tests__/throwObjectWithStackProp.test.js | 2 +- packages/jest-message-util/src/index.ts | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/e2e/failures/__tests__/throwObjectWithStackProp.test.js b/e2e/failures/__tests__/throwObjectWithStackProp.test.js index 5d672f0fcea7..1dfe6d4eb64e 100644 --- a/e2e/failures/__tests__/throwObjectWithStackProp.test.js +++ b/e2e/failures/__tests__/throwObjectWithStackProp.test.js @@ -8,4 +8,4 @@ 'use strict'; // eslint-disable-next-line no-throw-literal -throw {stack: 42}; \ No newline at end of file +throw {stack: 42}; diff --git a/packages/jest-message-util/src/index.ts b/packages/jest-message-util/src/index.ts index 59bdfd1c9b52..b00a981cea7d 100644 --- a/packages/jest-message-util/src/index.ts +++ b/packages/jest-message-util/src/index.ts @@ -391,7 +391,10 @@ export const separateMessageFromStack = ( // If the error is a plain "Error:" instead of a SyntaxError or TypeError we // remove the prefix from the message because it is generally not useful. const ERROR_REGEXP = /^(?:Error: )?([\s\S]*?(?=\n\s*at\s.*:\d*:\d*)|\s*.*)([\s\S]*)$/; - const messageMatch = typeof content !== 'string' ? `${content}`.match(ERROR_REGEXP) : content.match(ERROR_REGEXP); + const messageMatch = + typeof content !== 'string' + ? `${content}`.match(ERROR_REGEXP) + : content.match(ERROR_REGEXP); if (!messageMatch) { // For typescript throw new Error('If you hit this error, the regex above is buggy.'); From a5944878b43b182e7da1be1b7d3c4bbbabdc220b Mon Sep 17 00:00:00 2001 From: Simen Bekkhus Date: Mon, 26 Oct 2020 10:42:17 +0100 Subject: [PATCH 04/16] add one more test --- e2e/failures/__tests__/duringTests.test.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/e2e/failures/__tests__/duringTests.test.js b/e2e/failures/__tests__/duringTests.test.js index 679fefada8d5..47bb1f2092ad 100644 --- a/e2e/failures/__tests__/duringTests.test.js +++ b/e2e/failures/__tests__/duringTests.test.js @@ -29,6 +29,11 @@ test('Object thrown during test', () => { throw deepObject; }); +test('Object with stack prop thrown during test', () => { + // eslint-disable-next-line no-throw-literal + throw {stack: 42}; +}); + test('Error during test', () => { // eslint-disable-next-line no-undef doesNotExist.alsoThisNot; From 714f7ac5a4777f228ce5601846a924ba3fd0142e Mon Sep 17 00:00:00 2001 From: Nitin Kumar Date: Mon, 26 Oct 2020 15:42:16 +0530 Subject: [PATCH 05/16] update failures.test snapshot --- .../__snapshots__/failures.test.ts.snap | 59 +++++++++++-------- 1 file changed, 33 insertions(+), 26 deletions(-) diff --git a/e2e/__tests__/__snapshots__/failures.test.ts.snap b/e2e/__tests__/__snapshots__/failures.test.ts.snap index 56a6246cf019..c085140acfa2 100644 --- a/e2e/__tests__/__snapshots__/failures.test.ts.snap +++ b/e2e/__tests__/__snapshots__/failures.test.ts.snap @@ -117,6 +117,7 @@ FAIL __tests__/duringTests.test.js ✕ Boolean thrown during test ✕ undefined thrown during test ✕ Object thrown during test + ✕ Object with stack prop thrown during test ✕ Error during test ✕ done(Error) ✕ done(non-error) @@ -185,33 +186,39 @@ FAIL __tests__/duringTests.test.js at Object.test (__tests__/duringTests.test.js:28:1) + ● Object with stack prop thrown during test + + 42 + + + ● Error during test ReferenceError: doesNotExist is not defined - 32 | test('Error during test', () => { - 33 | // eslint-disable-next-line no-undef - > 34 | doesNotExist.alsoThisNot; + 37 | test('Error during test', () => { + 38 | // eslint-disable-next-line no-undef + > 39 | doesNotExist.alsoThisNot; | ^ - 35 | }); - 36 | - 37 | test('done(Error)', done => { + 40 | }); + 41 | + 42 | test('done(Error)', done => { - at Object.doesNotExist (__tests__/duringTests.test.js:34:3) + at Object.doesNotExist (__tests__/duringTests.test.js:39:3) ● done(Error) this is an error - 36 | - 37 | test('done(Error)', done => { - > 38 | done(new Error('this is an error')); + 41 | + 42 | test('done(Error)', done => { + > 43 | done(new Error('this is an error')); | ^ - 39 | }); - 40 | - 41 | test('done(non-error)', done => { + 44 | }); + 45 | + 46 | test('done(non-error)', done => { - at Object. (__tests__/duringTests.test.js:38:8) + at Object. (__tests__/duringTests.test.js:43:8) ● done(non-error) @@ -224,15 +231,15 @@ FAIL __tests__/duringTests.test.js ], } - 40 | - 41 | test('done(non-error)', done => { - > 42 | done(deepObject); + 45 | + 46 | test('done(non-error)', done => { + > 47 | done(deepObject); | ^ - 43 | }); - 44 | - 45 | test('returned promise rejection', () => Promise.reject(deepObject)); + 48 | }); + 49 | + 50 | test('returned promise rejection', () => Promise.reject(deepObject)); - at Object.done (__tests__/duringTests.test.js:42:3) + at Object.done (__tests__/duringTests.test.js:47:3) ● returned promise rejection @@ -245,13 +252,13 @@ FAIL __tests__/duringTests.test.js ], } - 43 | }); - 44 | - > 45 | test('returned promise rejection', () => Promise.reject(deepObject)); + 48 | }); + 49 | + > 50 | test('returned promise rejection', () => Promise.reject(deepObject)); | ^ - 46 | + 51 | - at Object.test (__tests__/duringTests.test.js:45:1) + at Object.test (__tests__/duringTests.test.js:50:1) `; exports[`not throwing Error objects 6`] = ` From 6a6e7dffc3b96412f35c60f99a0ff3ef64af43c1 Mon Sep 17 00:00:00 2001 From: Nitin Kumar Date: Mon, 26 Oct 2020 18:21:04 +0530 Subject: [PATCH 06/16] fix: tests --- e2e/__tests__/__snapshots__/failures.test.ts.snap | 12 +++++++++++- .../jest-jasmine2/src/expectationResultFactory.ts | 2 +- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/e2e/__tests__/__snapshots__/failures.test.ts.snap b/e2e/__tests__/__snapshots__/failures.test.ts.snap index c085140acfa2..cd3010dd1840 100644 --- a/e2e/__tests__/__snapshots__/failures.test.ts.snap +++ b/e2e/__tests__/__snapshots__/failures.test.ts.snap @@ -188,9 +188,19 @@ FAIL __tests__/duringTests.test.js ● Object with stack prop thrown during test - 42 + thrown: Object { + "stack": 42, + } + 30 | }); + 31 | + > 32 | test('Object with stack prop thrown during test', () => { + | ^ + 33 | // eslint-disable-next-line no-throw-literal + 34 | throw {stack: 42}; + 35 | }); + at Object.test (__tests__/duringTests.test.js:32:1) ● Error during test diff --git a/packages/jest-jasmine2/src/expectationResultFactory.ts b/packages/jest-jasmine2/src/expectationResultFactory.ts index d4533fdf3dcc..035d9a6a52ed 100644 --- a/packages/jest-jasmine2/src/expectationResultFactory.ts +++ b/packages/jest-jasmine2/src/expectationResultFactory.ts @@ -43,7 +43,7 @@ function stackFormatter( } if (options.error) { - if (options.error.stack) { + if ( typeof options.error.stack === 'string') { return options.error.stack; } From 1c37d9236cc4ae29ddd0534e5325fc8a95d54b2f Mon Sep 17 00:00:00 2001 From: Nitin Kumar Date: Mon, 26 Oct 2020 18:38:44 +0530 Subject: [PATCH 07/16] fix lint --- packages/jest-jasmine2/src/expectationResultFactory.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/jest-jasmine2/src/expectationResultFactory.ts b/packages/jest-jasmine2/src/expectationResultFactory.ts index 035d9a6a52ed..11f903afa5cc 100644 --- a/packages/jest-jasmine2/src/expectationResultFactory.ts +++ b/packages/jest-jasmine2/src/expectationResultFactory.ts @@ -43,7 +43,7 @@ function stackFormatter( } if (options.error) { - if ( typeof options.error.stack === 'string') { + if (typeof options.error.stack === 'string') { return options.error.stack; } From b7e5cfe7f9b5e19f59eec6c5911b4859eb8a0e0f Mon Sep 17 00:00:00 2001 From: Simen Bekkhus Date: Tue, 27 Oct 2020 10:13:28 +0100 Subject: [PATCH 08/16] fix node 10 test --- e2e/__tests__/failures.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/e2e/__tests__/failures.test.ts b/e2e/__tests__/failures.test.ts index 2302e1b04df1..f0e2c906712b 100644 --- a/e2e/__tests__/failures.test.ts +++ b/e2e/__tests__/failures.test.ts @@ -40,7 +40,7 @@ test('not throwing Error objects', () => { stderr = runJest(dir, ['duringTests.test.js']).stderr; if (nodeMajorVersion < 12) { - const lineEntry = '(__tests__/duringTests.test.js:38:8)'; + const lineEntry = '(__tests__/duringTests.test.js:43:8)'; expect(stderr).toContain(`at Object..done ${lineEntry}`); From 5b1a06256d1acd282e18ccf8d4d1b32f5fafd629 Mon Sep 17 00:00:00 2001 From: Nitin Kumar Date: Tue, 27 Oct 2020 15:19:44 +0530 Subject: [PATCH 09/16] fix jest-circus tests --- packages/jest-circus/src/utils.ts | 6 +++--- packages/jest-message-util/src/index.ts | 1 - 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/packages/jest-circus/src/utils.ts b/packages/jest-circus/src/utils.ts index 333faf037691..bc89e49f2843 100644 --- a/packages/jest-circus/src/utils.ts +++ b/packages/jest-circus/src/utils.ts @@ -383,16 +383,16 @@ const _getError = ( asyncError = new Error(); } - if (error && (error.stack || error.message)) { + if (error && (typeof error.stack === 'string' || error.message)) { return error; } asyncError.message = `thrown: ${prettyFormat(error, {maxDepth: 3})}`; - return asyncError; }; -const getErrorStack = (error: Error): string => error.stack || error.message; +const getErrorStack = (error: Error): string => + typeof error.stack === 'string' ? error.stack : error.message; export const addErrorToEachTestUnderDescribe = ( describeBlock: Circus.DescribeBlock, diff --git a/packages/jest-message-util/src/index.ts b/packages/jest-message-util/src/index.ts index b00a981cea7d..4197238bb8d8 100644 --- a/packages/jest-message-util/src/index.ts +++ b/packages/jest-message-util/src/index.ts @@ -103,7 +103,6 @@ function checkForCommonEnvironmentErrors(error: string) { } else if (error.includes('.unref is not a function')) { return warnAboutWrongTestEnvironment(error, 'node'); } - return error; } From 2110030c6e6b18bbc42ed4439f8d9e609844192c Mon Sep 17 00:00:00 2001 From: Simen Bekkhus Date: Tue, 27 Oct 2020 14:19:04 +0100 Subject: [PATCH 10/16] Update CHANGELOG.md --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b3a1c6e6216d..5a0b62f24f55 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,7 +8,7 @@ - `[jest-config]` Fix bug introduced in watch mode by PR[#10678](https://github.com/facebook/jest/pull/10678/files#r511037803) ([#10692](https://github.com/facebook/jest/pull/10692)) - `[expect]` Stop modifying the sample in `expect.objectContaining()` ([#10711](https://github.com/facebook/jest/pull/10711)) -- `[jest-jasmine2]` fix: don't assume stack to be a string always ([#10697](https://github.com/facebook/jest/pull/10697)) +- `[jest-circus, jest-jasmine2]` fix: don't assume `stack` is always a string ([#10697](https://github.com/facebook/jest/pull/10697)) - `[jest-resolve-dependencies]` Resolve mocks as dependencies ([#10713](https://github.com/facebook/jest/pull/10713)) ### Chore & Maintenance From f84fc5ce7b7a026e0853ddfa1e3d5c2aa02abdb7 Mon Sep 17 00:00:00 2001 From: Nitin Kumar Date: Tue, 27 Oct 2020 18:51:36 +0530 Subject: [PATCH 11/16] refactor --- .../__snapshots__/failures.test.ts.snap | 7 +++++-- packages/jest-message-util/src/index.ts | 21 ++++++++++++------- 2 files changed, 18 insertions(+), 10 deletions(-) diff --git a/e2e/__tests__/__snapshots__/failures.test.ts.snap b/e2e/__tests__/__snapshots__/failures.test.ts.snap index cd3010dd1840..14f34bcfdc69 100644 --- a/e2e/__tests__/__snapshots__/failures.test.ts.snap +++ b/e2e/__tests__/__snapshots__/failures.test.ts.snap @@ -18,7 +18,7 @@ exports[`not throwing Error objects 3`] = ` FAIL __tests__/throwObject.test.js ● Test suite failed to run - Error: No message was provided + thrown: Object {} `; exports[`not throwing Error objects 4`] = ` @@ -275,7 +275,10 @@ exports[`not throwing Error objects 6`] = ` FAIL __tests__/throwObjectWithStackProp.test.js ● Test suite failed to run - 42 + thrown: Object { + + "stack": 42, + } `; exports[`works with assertions in separate files 1`] = ` diff --git a/packages/jest-message-util/src/index.ts b/packages/jest-message-util/src/index.ts index 4197238bb8d8..544a96a74145 100644 --- a/packages/jest-message-util/src/index.ts +++ b/packages/jest-message-util/src/index.ts @@ -10,6 +10,7 @@ import * as fs from 'graceful-fs'; import type {Config, TestResult} from '@jest/types'; import chalk = require('chalk'); import micromatch = require('micromatch'); +import prettyFormat = require('pretty-format'); import slash = require('slash'); import {codeFrameColumns} from '@babel/code-frame'; import StackUtils = require('stack-utils'); @@ -103,6 +104,7 @@ function checkForCommonEnvironmentErrors(error: string) { } else if (error.includes('.unref is not a function')) { return warnAboutWrongTestEnvironment(error, 'node'); } + return error; } @@ -139,7 +141,10 @@ export const formatExecError = ( stack = error; } else { message = error.message; - stack = error.stack; + stack = + typeof error.stack === 'string' + ? error.stack + : `thrown: ${prettyFormat(error, {maxDepth: 3})}`; } const separated = separateMessageFromStack(stack || ''); @@ -159,9 +164,12 @@ export const formatExecError = ( ? '\n' + formatStackTrace(stack, config, options, testPath) : ''; - if (blankStringRegexp.test(message) && blankStringRegexp.test(stack)) { + if ( + (blankStringRegexp.test(message) && blankStringRegexp.test(stack)) || + typeof stack !== 'string' + ) { // this can happen if an empty object is thrown. - message = MESSAGE_INDENT + 'Error: No message was provided'; + message = `thrown: ${prettyFormat(error, {maxDepth: 3})}`; } let messageToUse; @@ -379,7 +387,7 @@ const removeBlankErrorLine = (str: string) => // Error object, so we have to regexp out the message from the stack string // to format it. export const separateMessageFromStack = ( - content: unknown, + content: string, ): {message: string; stack: string} => { if (!content) { return {message: '', stack: ''}; @@ -390,10 +398,7 @@ export const separateMessageFromStack = ( // If the error is a plain "Error:" instead of a SyntaxError or TypeError we // remove the prefix from the message because it is generally not useful. const ERROR_REGEXP = /^(?:Error: )?([\s\S]*?(?=\n\s*at\s.*:\d*:\d*)|\s*.*)([\s\S]*)$/; - const messageMatch = - typeof content !== 'string' - ? `${content}`.match(ERROR_REGEXP) - : content.match(ERROR_REGEXP); + const messageMatch = content.match(ERROR_REGEXP); if (!messageMatch) { // For typescript throw new Error('If you hit this error, the regex above is buggy.'); From 59b50575e72c7aea35d749c36c8fba5a193f4825 Mon Sep 17 00:00:00 2001 From: Nitin Kumar Date: Tue, 27 Oct 2020 20:09:18 +0530 Subject: [PATCH 12/16] refactor: suggestions --- packages/jest-message-util/src/index.ts | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/packages/jest-message-util/src/index.ts b/packages/jest-message-util/src/index.ts index 544a96a74145..098e404707be 100644 --- a/packages/jest-message-util/src/index.ts +++ b/packages/jest-message-util/src/index.ts @@ -165,8 +165,8 @@ export const formatExecError = ( : ''; if ( - (blankStringRegexp.test(message) && blankStringRegexp.test(stack)) || - typeof stack !== 'string' + typeof stack !== 'string' || + (blankStringRegexp.test(message) && blankStringRegexp.test(stack)) ) { // this can happen if an empty object is thrown. message = `thrown: ${prettyFormat(error, {maxDepth: 3})}`; @@ -397,8 +397,9 @@ export const separateMessageFromStack = ( // (maybe it's a code frame instead), just the first non-empty line. // If the error is a plain "Error:" instead of a SyntaxError or TypeError we // remove the prefix from the message because it is generally not useful. - const ERROR_REGEXP = /^(?:Error: )?([\s\S]*?(?=\n\s*at\s.*:\d*:\d*)|\s*.*)([\s\S]*)$/; - const messageMatch = content.match(ERROR_REGEXP); + const messageMatch = content.match( + /^(?:Error: )?([\s\S]*?(?=\n\s*at\s.*:\d*:\d*)|\s*.*)([\s\S]*)$/, + ); if (!messageMatch) { // For typescript throw new Error('If you hit this error, the regex above is buggy.'); From 10cc9c0c9b9b2ec51614514d7676c27c5e15cacb Mon Sep 17 00:00:00 2001 From: Nitin Kumar Date: Tue, 27 Oct 2020 20:31:01 +0530 Subject: [PATCH 13/16] add pretty-format to deps --- packages/jest-message-util/package.json | 1 + packages/jest-message-util/tsconfig.json | 5 ++++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/jest-message-util/package.json b/packages/jest-message-util/package.json index 88332a3c00e3..abd23da3177a 100644 --- a/packages/jest-message-util/package.json +++ b/packages/jest-message-util/package.json @@ -19,6 +19,7 @@ "chalk": "^4.0.0", "graceful-fs": "^4.2.4", "micromatch": "^4.0.2", + "pretty-format": "^26.6.1", "slash": "^3.0.0", "stack-utils": "^2.0.2" }, diff --git a/packages/jest-message-util/tsconfig.json b/packages/jest-message-util/tsconfig.json index 3046cb6b9b6a..6c9c16f09f5e 100644 --- a/packages/jest-message-util/tsconfig.json +++ b/packages/jest-message-util/tsconfig.json @@ -4,5 +4,8 @@ "rootDir": "src", "outDir": "build" }, - "references": [{"path": "../jest-types"}] + "references": [ + {"path": "../jest-types"}, + {"path": "../pretty-format"} + ] } From 648c24c6f84a21bb9222485d41d050c52ab6bbe1 Mon Sep 17 00:00:00 2001 From: Nitin Kumar Date: Tue, 27 Oct 2020 20:38:48 +0530 Subject: [PATCH 14/16] update lock file --- yarn.lock | 1 + 1 file changed, 1 insertion(+) diff --git a/yarn.lock b/yarn.lock index 96f92e09ab3b..83f715f706a7 100644 --- a/yarn.lock +++ b/yarn.lock @@ -11728,6 +11728,7 @@ fsevents@^1.2.7: chalk: ^4.0.0 graceful-fs: ^4.2.4 micromatch: ^4.0.2 + pretty-format: ^26.6.1 slash: ^3.0.0 stack-utils: ^2.0.2 languageName: unknown From 80785434c1e9fbb1a50ec3b3e7b0d67a93f32ed4 Mon Sep 17 00:00:00 2001 From: Nitin Kumar Date: Tue, 27 Oct 2020 21:23:10 +0530 Subject: [PATCH 15/16] refactor: suggestion --- packages/jest-jasmine2/src/reporter.ts | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/packages/jest-jasmine2/src/reporter.ts b/packages/jest-jasmine2/src/reporter.ts index 9829f1db7805..14518026ba07 100644 --- a/packages/jest-jasmine2/src/reporter.ts +++ b/packages/jest-jasmine2/src/reporter.ts @@ -113,19 +113,15 @@ export default class Jasmine2Reporter implements Reporter { return this._resultsPromise; } - private _addMissingMessageToStack(stack: unknown, message?: string) { + private _addMissingMessageToStack(stack: string, message?: string) { // Some errors (e.g. Angular injection error) don't prepend error.message // to stack, instead the first line of the stack is just plain 'Error' const ERROR_REGEX = /^Error:?\s*\n/; - if (typeof stack === 'string') { - if (stack && message && !stack.includes(message)) { - return message + stack.replace(ERROR_REGEX, '\n'); - } - return stack; - } else { - return `${stack}`; + if (stack && message && !stack.includes(message)) { + return message + stack.replace(ERROR_REGEX, '\n'); } + return stack; } private _extractSpecResults( @@ -156,7 +152,7 @@ export default class Jasmine2Reporter implements Reporter { specResult.failedExpectations.forEach(failed => { const message = - !failed.matcherName && failed.stack + !failed.matcherName && typeof failed.stack === 'string' ? this._addMissingMessageToStack(failed.stack, failed.message) : failed.message || ''; results.failureMessages.push(message); From d0a2d461228bb33d64c24aad886ffa4b6c12b51d Mon Sep 17 00:00:00 2001 From: Simen Bekkhus Date: Tue, 27 Oct 2020 17:10:42 +0100 Subject: [PATCH 16/16] reduce diff --- packages/jest-circus/src/utils.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/jest-circus/src/utils.ts b/packages/jest-circus/src/utils.ts index bc89e49f2843..03f02e69d173 100644 --- a/packages/jest-circus/src/utils.ts +++ b/packages/jest-circus/src/utils.ts @@ -388,6 +388,7 @@ const _getError = ( } asyncError.message = `thrown: ${prettyFormat(error, {maxDepth: 3})}`; + return asyncError; };