From 8d1e059fc856c1d9074644e07e61df3521623887 Mon Sep 17 00:00:00 2001 From: Yen-Chi Chen Date: Wed, 1 Apr 2020 18:02:53 +0200 Subject: [PATCH 01/29] Put full stack trace in console buffer --- packages/jest-console/src/BufferedConsole.ts | 7 +- packages/jest-console/src/formatStackTrace.ts | 274 ++++++++++++++++++ packages/jest-console/src/getConsoleOutput.ts | 32 +- packages/jest-console/tsconfig.json | 1 + packages/jest-message-util/src/index.ts | 8 +- .../jest-reporters/src/default_reporter.ts | 2 +- packages/jest-runner/src/runTest.ts | 2 +- packages/jest-source-map/src/getCallsite.ts | 41 +++ packages/jest-source-map/src/index.ts | 2 +- 9 files changed, 352 insertions(+), 17 deletions(-) create mode 100644 packages/jest-console/src/formatStackTrace.ts diff --git a/packages/jest-console/src/BufferedConsole.ts b/packages/jest-console/src/BufferedConsole.ts index 2ac94ac5c83b..68aa6fc0b98d 100644 --- a/packages/jest-console/src/BufferedConsole.ts +++ b/packages/jest-console/src/BufferedConsole.ts @@ -9,7 +9,8 @@ import assert = require('assert'); import {Console} from 'console'; import {format} from 'util'; import chalk = require('chalk'); -import {SourceMapRegistry, getCallsite} from '@jest/source-map'; +import {SourceMapRegistry, getSourceMappedStack} from '@jest/source-map'; + import type { ConsoleBuffer, LogCounters, @@ -48,8 +49,8 @@ export default class BufferedConsole extends Console { level?: number | null, sourceMaps?: SourceMapRegistry | null, ): ConsoleBuffer { - const callsite = getCallsite(level != null ? level : 2, sourceMaps); - const origin = callsite.getFileName() + ':' + callsite.getLineNumber(); + + const origin = getSourceMappedStack(level != null ? level : 2, sourceMaps); buffer.push({ message, diff --git a/packages/jest-console/src/formatStackTrace.ts b/packages/jest-console/src/formatStackTrace.ts new file mode 100644 index 000000000000..e27be016b9c7 --- /dev/null +++ b/packages/jest-console/src/formatStackTrace.ts @@ -0,0 +1,274 @@ +/** + * 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. + */ + +/** + * This is a temporary file to prevent breaking change + * TODO: + * 1) move formatResultErrors to jest-test-result so that jest-message-util no + * longer depends on jest-test-result + * 2) make jest-console depend on jest-message-util + * 3) remove this file + */ + +import * as fs from 'fs'; +import * as path from 'path'; +import type {Config} from '@jest/types'; +import chalk = require('chalk'); +import micromatch = require('micromatch'); +import slash = require('slash'); +import {codeFrameColumns} from '@babel/code-frame'; +import StackUtils = require('stack-utils'); + + +export interface Frame extends StackUtils.StackData { + file: string; +} + +type Path = Config.Path; + +// stack utils tries to create pretty stack by making paths relative. +const stackUtils = new StackUtils({cwd: 'something which does not exist'}); + +let nodeInternals: Array = []; + +try { + nodeInternals = StackUtils.nodeInternals(); +} catch (e) { + // `StackUtils.nodeInternals()` fails in browsers. We don't need to remove + // node internals in the browser though, so no issue. +} + +export type StackTraceConfig = Pick< + Config.ProjectConfig, + 'rootDir' | 'testMatch' +>; + +export type StackTraceOptions = { + noStackTrace: boolean; +}; + +const PATH_NODE_MODULES = `${path.sep}node_modules${path.sep}`; +const PATH_JEST_PACKAGES = `${path.sep}jest${path.sep}packages${path.sep}`; + +// filter for noisy stack trace lines +const JASMINE_IGNORE = /^\s+at(?:(?:.jasmine\-)|\s+jasmine\.buildExpectationResult)/; +const JEST_INTERNALS_IGNORE = /^\s+at.*?jest(-.*?)?(\/|\\)(build|node_modules|packages)(\/|\\)/; +const ANONYMOUS_FN_IGNORE = /^\s+at .*$/; +const ANONYMOUS_PROMISE_IGNORE = /^\s+at (new )?Promise \(\).*$/; +const ANONYMOUS_GENERATOR_IGNORE = /^\s+at Generator.next \(\).*$/; +const NATIVE_NEXT_IGNORE = /^\s+at next \(native\).*$/; +const MESSAGE_INDENT = ' '; +const STACK_INDENT = ' '; +const STACK_TRACE_COLOR = chalk.dim; +const STACK_PATH_REGEXP = /\s*at.*\(?(\:\d*\:\d*|native)\)?/; +const NOT_EMPTY_LINE_REGEXP = /^(?!$)/gm; + +const indentAllLines = (lines: string, indent: string) => + lines.replace(NOT_EMPTY_LINE_REGEXP, indent); + +const trim = (string: string) => (string || '').trim(); + +// Some errors contain not only line numbers in stack traces +// e.g. SyntaxErrors can contain snippets of code, and we don't +// want to trim those, because they may have pointers to the column/character +// which will get misaligned. +const trimPaths = (string: string) => + string.match(STACK_PATH_REGEXP) ? trim(string) : string; + +const getRenderedCallsite = ( + fileContent: string, + line: number, + column?: number, +) => { + let renderedCallsite = codeFrameColumns( + fileContent, + {start: {column, line}}, + {highlightCode: true}, + ); + + renderedCallsite = indentAllLines(renderedCallsite, MESSAGE_INDENT); + + renderedCallsite = `\n${renderedCallsite}\n`; + return renderedCallsite; +}; + + + +const removeInternalStackEntries = ( + lines: Array, + options: StackTraceOptions, +): Array => { + let pathCounter = 0; + + return lines.filter(line => { + if (ANONYMOUS_FN_IGNORE.test(line)) { + return false; + } + + if (ANONYMOUS_PROMISE_IGNORE.test(line)) { + return false; + } + + if (ANONYMOUS_GENERATOR_IGNORE.test(line)) { + return false; + } + + if (NATIVE_NEXT_IGNORE.test(line)) { + return false; + } + + if (nodeInternals.some(internal => internal.test(line))) { + return false; + } + + if (!STACK_PATH_REGEXP.test(line)) { + return true; + } + + if (JASMINE_IGNORE.test(line)) { + return false; + } + + if (++pathCounter === 1) { + return true; // always keep the first line even if it's from Jest + } + + if (options.noStackTrace) { + return false; + } + + if (JEST_INTERNALS_IGNORE.test(line)) { + return false; + } + + return true; + }); +}; + +const formatPaths = ( + config: StackTraceConfig, + relativeTestPath: Path | null, + line: string, +) => { + // Extract the file path from the trace line. + const match = line.match(/(^\s*at .*?\(?)([^()]+)(:[0-9]+:[0-9]+\)?.*$)/); + if (!match) { + return line; + } + + let filePath = slash(path.relative(config.rootDir, match[2])); + // highlight paths from the current test file + if ( + (config.testMatch && + config.testMatch.length && + micromatch([filePath], config.testMatch).length > 0) || + filePath === relativeTestPath + ) { + filePath = chalk.reset.cyan(filePath); + } + return STACK_TRACE_COLOR(match[1]) + filePath + STACK_TRACE_COLOR(match[3]); +}; + +export const getStackTraceLines = ( + stack: string, + options: StackTraceOptions = {noStackTrace: false}, +): Array => removeInternalStackEntries(stack.split(/\n/), options); + +export const getTopFrame = (lines: Array): Frame | null => { + for (const line of lines) { + if (line.includes(PATH_NODE_MODULES) || line.includes(PATH_JEST_PACKAGES)) { + continue; + } + + const parsedFrame = stackUtils.parseLine(line.trim()); + + if (parsedFrame && parsedFrame.file) { + return parsedFrame as Frame; + } + } + + return null; +}; + +export const formatStackTrace = ( + stack: string, + config: StackTraceConfig, + options: StackTraceOptions, + testPath?: Path, +): string => { + const lines = getStackTraceLines(stack, options); + const topFrame = getTopFrame(lines); + let renderedCallsite = ''; + const relativeTestPath = testPath + ? slash(path.relative(config.rootDir, testPath)) + : null; + + if (topFrame) { + const {column, file: filename, line} = topFrame; + + if (line && filename && path.isAbsolute(filename)) { + let fileContent; + try { + // TODO: check & read HasteFS instead of reading the filesystem: + // see: https://github.com/facebook/jest/pull/5405#discussion_r164281696 + fileContent = fs.readFileSync(filename, 'utf8'); + renderedCallsite = getRenderedCallsite(fileContent, line, column); + } catch (e) { + // the file does not exist or is inaccessible, we ignore + } + } + } + + const stacktrace = lines + .filter(Boolean) + .map( + line => + STACK_INDENT + formatPaths(config, relativeTestPath, trimPaths(line)), + ) + .join('\n'); + + return `${renderedCallsite}\n${stacktrace}`; +}; + + + +const errorRegexp = /^Error:?\s*$/; + +export const removeBlankErrorLine = (str: string) => + str + .split('\n') + // Lines saying just `Error:` are useless + .filter(line => + !errorRegexp.test(line)) + .join('\n') + .trimRight(); + +// jasmine and worker farm sometimes don't give us access to the actual +// Error object, so we have to regexp out the message from the stack string +// to format it. +export const separateMessageFromStack = ( + content: string, +): {message: string; stack: string} => { + if (!content) { + return {message: '', stack: ''}; + } + + // All lines up to what looks like a stack -- or if nothing looks like a stack + // (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]*)$/, + ); + if (!messageMatch) { + // For typescript + throw new Error('If you hit this error, the regex above is buggy.'); + } + const message = removeBlankErrorLine(messageMatch[1]); + const stack = removeBlankErrorLine(messageMatch[2]); + return {message, stack}; +}; diff --git a/packages/jest-console/src/getConsoleOutput.ts b/packages/jest-console/src/getConsoleOutput.ts index 09a3232b557e..bb518cae0ebf 100644 --- a/packages/jest-console/src/getConsoleOutput.ts +++ b/packages/jest-console/src/getConsoleOutput.ts @@ -5,43 +5,59 @@ * LICENSE file in the root directory of this source tree. */ -import * as path from 'path'; import chalk = require('chalk'); -import slash = require('slash'); import type {ConsoleBuffer} from './types'; +import { + formatStackTrace, + StackTraceConfig} from 'jest-message-util'; + export default ( - root: string, verbose: boolean, + stackTraceConfig: StackTraceConfig, buffer: ConsoleBuffer, ): string => { const TITLE_INDENT = verbose ? ' ' : ' '; const CONSOLE_INDENT = TITLE_INDENT + ' '; - return buffer.reduce((output, {type, message, origin}) => { - origin = slash(path.relative(root, origin)); + return buffer.reduce((output, {type, message, origin}) => { message = message .split(/\n/) .map(line => CONSOLE_INDENT + line) .join('\n'); let typeMessage = 'console.' + type; + let noStackTrace = true; + let noCodeFrame = true; + if (type === 'warn') { message = chalk.yellow(message); typeMessage = chalk.yellow(typeMessage); + noStackTrace = false; + noCodeFrame = false; } else if (type === 'error') { message = chalk.red(message); typeMessage = chalk.red(typeMessage); - } + noStackTrace = false; + noCodeFrame = false; + } + + const formattedStackTrace = formatStackTrace( + origin, + stackTraceConfig, + { + noStackTrace: noStackTrace, + noCodeFrame: noCodeFrame + }); return ( output + TITLE_INDENT + chalk.dim(typeMessage) + - ' ' + - chalk.dim(origin) + '\n' + message + + '\n' + + chalk.dim(formattedStackTrace) + '\n' ); }, ''); diff --git a/packages/jest-console/tsconfig.json b/packages/jest-console/tsconfig.json index 719bab0f554b..787fa0ffe52d 100644 --- a/packages/jest-console/tsconfig.json +++ b/packages/jest-console/tsconfig.json @@ -6,6 +6,7 @@ }, "references": [ {"path": "../jest-source-map"}, + {"path": "../jest-message-util"}, {"path": "../jest-util"} ] } diff --git a/packages/jest-message-util/src/index.ts b/packages/jest-message-util/src/index.ts index b82b512690fa..a887191ab719 100644 --- a/packages/jest-message-util/src/index.ts +++ b/packages/jest-message-util/src/index.ts @@ -38,6 +38,7 @@ export type StackTraceConfig = Pick< export type StackTraceOptions = { noStackTrace: boolean; + noCodeFrame?: boolean; }; const PATH_NODE_MODULES = `${path.sep}node_modules${path.sep}`; @@ -251,7 +252,7 @@ const formatPaths = ( export const getStackTraceLines = ( stack: string, - options: StackTraceOptions = {noStackTrace: false}, + options: StackTraceOptions = {noStackTrace: false, noCodeFrame: false}, ): Array => removeInternalStackEntries(stack.split(/\n/), options); export const getTopFrame = (lines: Array): Frame | null => { @@ -283,7 +284,7 @@ export const formatStackTrace = ( ? slash(path.relative(config.rootDir, testPath)) : null; - if (topFrame) { + if (topFrame && !options.noStackTrace) { const {column, file: filename, line} = topFrame; if (line && filename && path.isAbsolute(filename)) { @@ -307,7 +308,8 @@ export const formatStackTrace = ( ) .join('\n'); - return `${renderedCallsite}\n${stacktrace}`; + return (options.noCodeFrame) ? + `${stacktrace}` : `${renderedCallsite}\n${stacktrace}`; }; type FailedResults = Array<{ diff --git a/packages/jest-reporters/src/default_reporter.ts b/packages/jest-reporters/src/default_reporter.ts index ae90384cd2b8..8997791d899a 100644 --- a/packages/jest-reporters/src/default_reporter.ts +++ b/packages/jest-reporters/src/default_reporter.ts @@ -179,8 +179,8 @@ export default class DefaultReporter extends BaseReporter { TITLE_BULLET + 'Console\n\n' + getConsoleOutput( - config.cwd, !!this._globalConfig.verbose, + config, result.console, ), ); diff --git a/packages/jest-runner/src/runTest.ts b/packages/jest-runner/src/runTest.ts index a617bc9d510c..d1679d104d49 100644 --- a/packages/jest-runner/src/runTest.ts +++ b/packages/jest-runner/src/runTest.ts @@ -119,8 +119,8 @@ async function runTestInternal( const consoleOut = globalConfig.useStderr ? process.stderr : process.stdout; const consoleFormatter = (type: LogType, message: LogMessage) => getConsoleOutput( - config.cwd, !!globalConfig.verbose, + config, // 4 = the console call is buried 4 stack frames deep BufferedConsole.write( [], diff --git a/packages/jest-source-map/src/getCallsite.ts b/packages/jest-source-map/src/getCallsite.ts index ecb903d7729e..ffba37e77718 100644 --- a/packages/jest-source-map/src/getCallsite.ts +++ b/packages/jest-source-map/src/getCallsite.ts @@ -9,6 +9,8 @@ import {readFileSync} from 'graceful-fs'; import callsites = require('callsites'); import {SourceMapConsumer} from 'source-map'; import type {SourceMapRegistry} from './types'; +import StackUtils = require('stack-utils'); +import {ErrorWithStack} from 'jest-util'; // Copied from https://github.com/rexxars/sourcemap-decorate-callsites/blob/5b9735a156964973a75dc62fd2c7f0c1975458e8/lib/index.js#L113-L158 const addSourceMapConsumer = ( @@ -66,3 +68,42 @@ export default ( return stack; }; + +export const getSourceMappedStack = ( + level: number, + sourceMaps ?: SourceMapRegistry | null, +): string => { + + const rawStack = new ErrorWithStack( + undefined, + getSourceMappedStack) + .stack || ''; + + const stackUtils = new StackUtils({ + cwd: 'something which does not exist', + wrapCallSite: (callsite: StackUtils.CallSite) => { + const sourceMapFileName = sourceMaps && + sourceMaps[callsite.getFileName() || '']; + + if (sourceMapFileName) { + try { + const sourceMap = readFileSync(sourceMapFileName, 'utf8'); + // @ts-ignore: Not allowed to pass string + addSourceMapConsumer(stack, new SourceMapConsumer(sourceMap)); + } catch (e) { + // ignore + } + } + return callsite; + } + }); + + const sourceMapped = stackUtils.clean(rawStack) + .split('\n') + .slice(level) + .filter(Boolean) + .map(s=>'\tat '+s) + .join('\n'); + + return sourceMapped; +}; \ No newline at end of file diff --git a/packages/jest-source-map/src/index.ts b/packages/jest-source-map/src/index.ts index 37a0bc1d525b..12bd704f1b4c 100644 --- a/packages/jest-source-map/src/index.ts +++ b/packages/jest-source-map/src/index.ts @@ -5,5 +5,5 @@ * LICENSE file in the root directory of this source tree. */ -export {default as getCallsite} from './getCallsite'; +export {default as getCallsite, getSourceMappedStack} from './getCallsite'; export type {SourceMapRegistry} from './types'; From d9390b624943d6a95a65ee0ee81c088877ebb6b7 Mon Sep 17 00:00:00 2001 From: Yen-Chi Chen Date: Sat, 4 Apr 2020 17:40:32 +0200 Subject: [PATCH 02/29] Rely on source-map-support No need to pass SourceMapRegistry --- packages/jest-console/package.json | 3 +- packages/jest-console/src/BufferedConsole.ts | 17 +- packages/jest-console/src/formatStackTrace.ts | 274 ------------------ packages/jest-console/src/getConsoleOutput.ts | 42 ++- packages/jest-message-util/src/index.ts | 9 +- .../jest-reporters/src/default_reporter.ts | 3 +- packages/jest-runner/src/runTest.ts | 3 +- packages/jest-source-map/src/getCallsite.ts | 41 --- packages/jest-source-map/src/index.ts | 2 +- 9 files changed, 53 insertions(+), 341 deletions(-) delete mode 100644 packages/jest-console/src/formatStackTrace.ts diff --git a/packages/jest-console/package.json b/packages/jest-console/package.json index e5501896ebfe..f96cf00c6318 100644 --- a/packages/jest-console/package.json +++ b/packages/jest-console/package.json @@ -19,7 +19,8 @@ "dependencies": { "@jest/source-map": "^25.2.6", "chalk": "^3.0.0", - "jest-util": "^25.3.0", + "jest-message-util": "^25.2.6", + "jest-util": "^25.2.6", "slash": "^3.0.0" }, "devDependencies": { diff --git a/packages/jest-console/src/BufferedConsole.ts b/packages/jest-console/src/BufferedConsole.ts index 68aa6fc0b98d..87d97ece5f59 100644 --- a/packages/jest-console/src/BufferedConsole.ts +++ b/packages/jest-console/src/BufferedConsole.ts @@ -9,7 +9,8 @@ import assert = require('assert'); import {Console} from 'console'; import {format} from 'util'; import chalk = require('chalk'); -import {SourceMapRegistry, getSourceMappedStack} from '@jest/source-map'; +import type {SourceMapRegistry} from '@jest/source-map'; +import {ErrorWithStack} from 'jest-util'; import type { ConsoleBuffer, @@ -47,10 +48,18 @@ export default class BufferedConsole extends Console { type: LogType, message: LogMessage, level?: number | null, - sourceMaps?: SourceMapRegistry | null, + // @ts-ignore: To avoid breaking change. It's actually not used. + _sourceMaps?: SourceMapRegistry | null, ): ConsoleBuffer { - - const origin = getSourceMappedStack(level != null ? level : 2, sourceMaps); + const stackLevel = level != null ? level : 2; + const rawStack = + new ErrorWithStack(undefined, BufferedConsole.write).stack || ''; + + const origin = rawStack + .split('\n') + .slice(stackLevel) + .filter(Boolean) + .join('\n'); buffer.push({ message, diff --git a/packages/jest-console/src/formatStackTrace.ts b/packages/jest-console/src/formatStackTrace.ts deleted file mode 100644 index e27be016b9c7..000000000000 --- a/packages/jest-console/src/formatStackTrace.ts +++ /dev/null @@ -1,274 +0,0 @@ -/** - * 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. - */ - -/** - * This is a temporary file to prevent breaking change - * TODO: - * 1) move formatResultErrors to jest-test-result so that jest-message-util no - * longer depends on jest-test-result - * 2) make jest-console depend on jest-message-util - * 3) remove this file - */ - -import * as fs from 'fs'; -import * as path from 'path'; -import type {Config} from '@jest/types'; -import chalk = require('chalk'); -import micromatch = require('micromatch'); -import slash = require('slash'); -import {codeFrameColumns} from '@babel/code-frame'; -import StackUtils = require('stack-utils'); - - -export interface Frame extends StackUtils.StackData { - file: string; -} - -type Path = Config.Path; - -// stack utils tries to create pretty stack by making paths relative. -const stackUtils = new StackUtils({cwd: 'something which does not exist'}); - -let nodeInternals: Array = []; - -try { - nodeInternals = StackUtils.nodeInternals(); -} catch (e) { - // `StackUtils.nodeInternals()` fails in browsers. We don't need to remove - // node internals in the browser though, so no issue. -} - -export type StackTraceConfig = Pick< - Config.ProjectConfig, - 'rootDir' | 'testMatch' ->; - -export type StackTraceOptions = { - noStackTrace: boolean; -}; - -const PATH_NODE_MODULES = `${path.sep}node_modules${path.sep}`; -const PATH_JEST_PACKAGES = `${path.sep}jest${path.sep}packages${path.sep}`; - -// filter for noisy stack trace lines -const JASMINE_IGNORE = /^\s+at(?:(?:.jasmine\-)|\s+jasmine\.buildExpectationResult)/; -const JEST_INTERNALS_IGNORE = /^\s+at.*?jest(-.*?)?(\/|\\)(build|node_modules|packages)(\/|\\)/; -const ANONYMOUS_FN_IGNORE = /^\s+at .*$/; -const ANONYMOUS_PROMISE_IGNORE = /^\s+at (new )?Promise \(\).*$/; -const ANONYMOUS_GENERATOR_IGNORE = /^\s+at Generator.next \(\).*$/; -const NATIVE_NEXT_IGNORE = /^\s+at next \(native\).*$/; -const MESSAGE_INDENT = ' '; -const STACK_INDENT = ' '; -const STACK_TRACE_COLOR = chalk.dim; -const STACK_PATH_REGEXP = /\s*at.*\(?(\:\d*\:\d*|native)\)?/; -const NOT_EMPTY_LINE_REGEXP = /^(?!$)/gm; - -const indentAllLines = (lines: string, indent: string) => - lines.replace(NOT_EMPTY_LINE_REGEXP, indent); - -const trim = (string: string) => (string || '').trim(); - -// Some errors contain not only line numbers in stack traces -// e.g. SyntaxErrors can contain snippets of code, and we don't -// want to trim those, because they may have pointers to the column/character -// which will get misaligned. -const trimPaths = (string: string) => - string.match(STACK_PATH_REGEXP) ? trim(string) : string; - -const getRenderedCallsite = ( - fileContent: string, - line: number, - column?: number, -) => { - let renderedCallsite = codeFrameColumns( - fileContent, - {start: {column, line}}, - {highlightCode: true}, - ); - - renderedCallsite = indentAllLines(renderedCallsite, MESSAGE_INDENT); - - renderedCallsite = `\n${renderedCallsite}\n`; - return renderedCallsite; -}; - - - -const removeInternalStackEntries = ( - lines: Array, - options: StackTraceOptions, -): Array => { - let pathCounter = 0; - - return lines.filter(line => { - if (ANONYMOUS_FN_IGNORE.test(line)) { - return false; - } - - if (ANONYMOUS_PROMISE_IGNORE.test(line)) { - return false; - } - - if (ANONYMOUS_GENERATOR_IGNORE.test(line)) { - return false; - } - - if (NATIVE_NEXT_IGNORE.test(line)) { - return false; - } - - if (nodeInternals.some(internal => internal.test(line))) { - return false; - } - - if (!STACK_PATH_REGEXP.test(line)) { - return true; - } - - if (JASMINE_IGNORE.test(line)) { - return false; - } - - if (++pathCounter === 1) { - return true; // always keep the first line even if it's from Jest - } - - if (options.noStackTrace) { - return false; - } - - if (JEST_INTERNALS_IGNORE.test(line)) { - return false; - } - - return true; - }); -}; - -const formatPaths = ( - config: StackTraceConfig, - relativeTestPath: Path | null, - line: string, -) => { - // Extract the file path from the trace line. - const match = line.match(/(^\s*at .*?\(?)([^()]+)(:[0-9]+:[0-9]+\)?.*$)/); - if (!match) { - return line; - } - - let filePath = slash(path.relative(config.rootDir, match[2])); - // highlight paths from the current test file - if ( - (config.testMatch && - config.testMatch.length && - micromatch([filePath], config.testMatch).length > 0) || - filePath === relativeTestPath - ) { - filePath = chalk.reset.cyan(filePath); - } - return STACK_TRACE_COLOR(match[1]) + filePath + STACK_TRACE_COLOR(match[3]); -}; - -export const getStackTraceLines = ( - stack: string, - options: StackTraceOptions = {noStackTrace: false}, -): Array => removeInternalStackEntries(stack.split(/\n/), options); - -export const getTopFrame = (lines: Array): Frame | null => { - for (const line of lines) { - if (line.includes(PATH_NODE_MODULES) || line.includes(PATH_JEST_PACKAGES)) { - continue; - } - - const parsedFrame = stackUtils.parseLine(line.trim()); - - if (parsedFrame && parsedFrame.file) { - return parsedFrame as Frame; - } - } - - return null; -}; - -export const formatStackTrace = ( - stack: string, - config: StackTraceConfig, - options: StackTraceOptions, - testPath?: Path, -): string => { - const lines = getStackTraceLines(stack, options); - const topFrame = getTopFrame(lines); - let renderedCallsite = ''; - const relativeTestPath = testPath - ? slash(path.relative(config.rootDir, testPath)) - : null; - - if (topFrame) { - const {column, file: filename, line} = topFrame; - - if (line && filename && path.isAbsolute(filename)) { - let fileContent; - try { - // TODO: check & read HasteFS instead of reading the filesystem: - // see: https://github.com/facebook/jest/pull/5405#discussion_r164281696 - fileContent = fs.readFileSync(filename, 'utf8'); - renderedCallsite = getRenderedCallsite(fileContent, line, column); - } catch (e) { - // the file does not exist or is inaccessible, we ignore - } - } - } - - const stacktrace = lines - .filter(Boolean) - .map( - line => - STACK_INDENT + formatPaths(config, relativeTestPath, trimPaths(line)), - ) - .join('\n'); - - return `${renderedCallsite}\n${stacktrace}`; -}; - - - -const errorRegexp = /^Error:?\s*$/; - -export const removeBlankErrorLine = (str: string) => - str - .split('\n') - // Lines saying just `Error:` are useless - .filter(line => - !errorRegexp.test(line)) - .join('\n') - .trimRight(); - -// jasmine and worker farm sometimes don't give us access to the actual -// Error object, so we have to regexp out the message from the stack string -// to format it. -export const separateMessageFromStack = ( - content: string, -): {message: string; stack: string} => { - if (!content) { - return {message: '', stack: ''}; - } - - // All lines up to what looks like a stack -- or if nothing looks like a stack - // (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]*)$/, - ); - if (!messageMatch) { - // For typescript - throw new Error('If you hit this error, the regex above is buggy.'); - } - const message = removeBlankErrorLine(messageMatch[1]); - const stack = removeBlankErrorLine(messageMatch[2]); - return {message, stack}; -}; diff --git a/packages/jest-console/src/getConsoleOutput.ts b/packages/jest-console/src/getConsoleOutput.ts index bb518cae0ebf..7d9eb64a1d1d 100644 --- a/packages/jest-console/src/getConsoleOutput.ts +++ b/packages/jest-console/src/getConsoleOutput.ts @@ -6,21 +6,32 @@ */ import chalk = require('chalk'); -import type {ConsoleBuffer} from './types'; - import { - formatStackTrace, - StackTraceConfig} from 'jest-message-util'; + StackTraceConfig, + StackTraceOptions, + formatStackTrace, +} from 'jest-message-util'; +import type {ConsoleBuffer} from './types'; export default ( + root: string, verbose: boolean, - stackTraceConfig: StackTraceConfig, buffer: ConsoleBuffer, + optionalStackTraceConfig?: StackTraceConfig, ): string => { const TITLE_INDENT = verbose ? ' ' : ' '; const CONSOLE_INDENT = TITLE_INDENT + ' '; - return buffer.reduce((output, {type, message, origin}) => { + // TODO: make sure all callers pass correct config and remove this + const stackTraceConfig: StackTraceConfig = + optionalStackTraceConfig != null + ? optionalStackTraceConfig + : { + rootDir: root, + testMatch: [], + }; + + return buffer.reduce((output, {type, message, origin}) => { message = message .split(/\n/) .map(line => CONSOLE_INDENT + line) @@ -40,15 +51,18 @@ export default ( typeMessage = chalk.red(typeMessage); noStackTrace = false; noCodeFrame = false; - } - + } + + const options: StackTraceOptions = { + noCodeFrame, + noStackTrace, + }; + const formattedStackTrace = formatStackTrace( - origin, - stackTraceConfig, - { - noStackTrace: noStackTrace, - noCodeFrame: noCodeFrame - }); + origin, + stackTraceConfig, + options, + ); return ( output + diff --git a/packages/jest-message-util/src/index.ts b/packages/jest-message-util/src/index.ts index a887191ab719..765a772a1801 100644 --- a/packages/jest-message-util/src/index.ts +++ b/packages/jest-message-util/src/index.ts @@ -252,7 +252,7 @@ const formatPaths = ( export const getStackTraceLines = ( stack: string, - options: StackTraceOptions = {noStackTrace: false, noCodeFrame: false}, + options: StackTraceOptions = {noCodeFrame: false, noStackTrace: false}, ): Array => removeInternalStackEntries(stack.split(/\n/), options); export const getTopFrame = (lines: Array): Frame | null => { @@ -284,7 +284,7 @@ export const formatStackTrace = ( ? slash(path.relative(config.rootDir, testPath)) : null; - if (topFrame && !options.noStackTrace) { + if (topFrame && !options.noCodeFrame) { const {column, file: filename, line} = topFrame; if (line && filename && path.isAbsolute(filename)) { @@ -308,8 +308,9 @@ export const formatStackTrace = ( ) .join('\n'); - return (options.noCodeFrame) ? - `${stacktrace}` : `${renderedCallsite}\n${stacktrace}`; + return options.noCodeFrame + ? `${stacktrace}` + : `${renderedCallsite}\n${stacktrace}`; }; type FailedResults = Array<{ diff --git a/packages/jest-reporters/src/default_reporter.ts b/packages/jest-reporters/src/default_reporter.ts index 8997791d899a..9053fbf20eac 100644 --- a/packages/jest-reporters/src/default_reporter.ts +++ b/packages/jest-reporters/src/default_reporter.ts @@ -179,9 +179,10 @@ export default class DefaultReporter extends BaseReporter { TITLE_BULLET + 'Console\n\n' + getConsoleOutput( + config.cwd, !!this._globalConfig.verbose, - config, result.console, + config, ), ); } diff --git a/packages/jest-runner/src/runTest.ts b/packages/jest-runner/src/runTest.ts index d1679d104d49..68d5928c4f3a 100644 --- a/packages/jest-runner/src/runTest.ts +++ b/packages/jest-runner/src/runTest.ts @@ -119,8 +119,8 @@ async function runTestInternal( const consoleOut = globalConfig.useStderr ? process.stderr : process.stdout; const consoleFormatter = (type: LogType, message: LogMessage) => getConsoleOutput( + config.cwd, !!globalConfig.verbose, - config, // 4 = the console call is buried 4 stack frames deep BufferedConsole.write( [], @@ -129,6 +129,7 @@ async function runTestInternal( 4, runtime && runtime.getSourceMaps(), ), + config, ); let testConsole; diff --git a/packages/jest-source-map/src/getCallsite.ts b/packages/jest-source-map/src/getCallsite.ts index ffba37e77718..ecb903d7729e 100644 --- a/packages/jest-source-map/src/getCallsite.ts +++ b/packages/jest-source-map/src/getCallsite.ts @@ -9,8 +9,6 @@ import {readFileSync} from 'graceful-fs'; import callsites = require('callsites'); import {SourceMapConsumer} from 'source-map'; import type {SourceMapRegistry} from './types'; -import StackUtils = require('stack-utils'); -import {ErrorWithStack} from 'jest-util'; // Copied from https://github.com/rexxars/sourcemap-decorate-callsites/blob/5b9735a156964973a75dc62fd2c7f0c1975458e8/lib/index.js#L113-L158 const addSourceMapConsumer = ( @@ -68,42 +66,3 @@ export default ( return stack; }; - -export const getSourceMappedStack = ( - level: number, - sourceMaps ?: SourceMapRegistry | null, -): string => { - - const rawStack = new ErrorWithStack( - undefined, - getSourceMappedStack) - .stack || ''; - - const stackUtils = new StackUtils({ - cwd: 'something which does not exist', - wrapCallSite: (callsite: StackUtils.CallSite) => { - const sourceMapFileName = sourceMaps && - sourceMaps[callsite.getFileName() || '']; - - if (sourceMapFileName) { - try { - const sourceMap = readFileSync(sourceMapFileName, 'utf8'); - // @ts-ignore: Not allowed to pass string - addSourceMapConsumer(stack, new SourceMapConsumer(sourceMap)); - } catch (e) { - // ignore - } - } - return callsite; - } - }); - - const sourceMapped = stackUtils.clean(rawStack) - .split('\n') - .slice(level) - .filter(Boolean) - .map(s=>'\tat '+s) - .join('\n'); - - return sourceMapped; -}; \ No newline at end of file diff --git a/packages/jest-source-map/src/index.ts b/packages/jest-source-map/src/index.ts index 12bd704f1b4c..37a0bc1d525b 100644 --- a/packages/jest-source-map/src/index.ts +++ b/packages/jest-source-map/src/index.ts @@ -5,5 +5,5 @@ * LICENSE file in the root directory of this source tree. */ -export {default as getCallsite, getSourceMappedStack} from './getCallsite'; +export {default as getCallsite} from './getCallsite'; export type {SourceMapRegistry} from './types'; From 1ed4e366eb350d37ceddd73f5d93f4744c01ee77 Mon Sep 17 00:00:00 2001 From: Yen-Chi Chen Date: Wed, 8 Apr 2020 19:27:34 +0200 Subject: [PATCH 03/29] Incorporate review feedbacks --- packages/jest-console/package.json | 1 + packages/jest-console/src/BufferedConsole.ts | 13 ++++++++++++- packages/jest-console/src/getConsoleOutput.ts | 15 ++++----------- packages/jest-console/tsconfig.json | 3 ++- 4 files changed, 19 insertions(+), 13 deletions(-) diff --git a/packages/jest-console/package.json b/packages/jest-console/package.json index f96cf00c6318..698f150821b7 100644 --- a/packages/jest-console/package.json +++ b/packages/jest-console/package.json @@ -20,6 +20,7 @@ "@jest/source-map": "^25.2.6", "chalk": "^3.0.0", "jest-message-util": "^25.2.6", + "jest-types": "^25.2.6", "jest-util": "^25.2.6", "slash": "^3.0.0" }, diff --git a/packages/jest-console/src/BufferedConsole.ts b/packages/jest-console/src/BufferedConsole.ts index 87d97ece5f59..6fdcd4e0cd2e 100644 --- a/packages/jest-console/src/BufferedConsole.ts +++ b/packages/jest-console/src/BufferedConsole.ts @@ -53,7 +53,9 @@ export default class BufferedConsole extends Console { ): ConsoleBuffer { const stackLevel = level != null ? level : 2; const rawStack = - new ErrorWithStack(undefined, BufferedConsole.write).stack || ''; + new ErrorWithStack(undefined, BufferedConsole.write).stack; + + invariant(rawStack, 'always have a stack trace'); const origin = rawStack .split('\n') @@ -173,3 +175,12 @@ export default class BufferedConsole extends Console { return this._buffer.length ? this._buffer : undefined; } } + +function invariant( + condition: unknown, + message?: string, +): asserts condition { + if (!condition) { + throw new Error(message); + } +} \ No newline at end of file diff --git a/packages/jest-console/src/getConsoleOutput.ts b/packages/jest-console/src/getConsoleOutput.ts index 7d9eb64a1d1d..8c2f1952d35b 100644 --- a/packages/jest-console/src/getConsoleOutput.ts +++ b/packages/jest-console/src/getConsoleOutput.ts @@ -6,30 +6,23 @@ */ import chalk = require('chalk'); +import type {Config} from '@jest/types'; import { - StackTraceConfig, StackTraceOptions, formatStackTrace, } from 'jest-message-util'; import type {ConsoleBuffer} from './types'; export default ( + // @ts-ignore: cleanup after 26 root: string, verbose: boolean, buffer: ConsoleBuffer, - optionalStackTraceConfig?: StackTraceConfig, + config: Config.ProjectConfig, ): string => { const TITLE_INDENT = verbose ? ' ' : ' '; const CONSOLE_INDENT = TITLE_INDENT + ' '; - // TODO: make sure all callers pass correct config and remove this - const stackTraceConfig: StackTraceConfig = - optionalStackTraceConfig != null - ? optionalStackTraceConfig - : { - rootDir: root, - testMatch: [], - }; return buffer.reduce((output, {type, message, origin}) => { message = message @@ -60,7 +53,7 @@ export default ( const formattedStackTrace = formatStackTrace( origin, - stackTraceConfig, + config, options, ); diff --git a/packages/jest-console/tsconfig.json b/packages/jest-console/tsconfig.json index 787fa0ffe52d..895d3c26862f 100644 --- a/packages/jest-console/tsconfig.json +++ b/packages/jest-console/tsconfig.json @@ -5,8 +5,9 @@ "outDir": "build" }, "references": [ - {"path": "../jest-source-map"}, {"path": "../jest-message-util"}, + {"path": "../jest-source-map"}, + {"path": "../jest-types"}, {"path": "../jest-util"} ] } From 6e153d1a3b3fe6a13f51ae6a4ee3a0f8fb3d0ea3 Mon Sep 17 00:00:00 2001 From: ychi Date: Thu, 9 Apr 2020 17:50:02 +0200 Subject: [PATCH 04/29] Update packages/jest-console/src/getConsoleOutput.ts Co-Authored-By: Simen Bekkhus --- packages/jest-console/src/getConsoleOutput.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/jest-console/src/getConsoleOutput.ts b/packages/jest-console/src/getConsoleOutput.ts index 8c2f1952d35b..fe5f38c97daa 100644 --- a/packages/jest-console/src/getConsoleOutput.ts +++ b/packages/jest-console/src/getConsoleOutput.ts @@ -14,8 +14,8 @@ import { import type {ConsoleBuffer} from './types'; export default ( - // @ts-ignore: cleanup after 26 - root: string, + // TODO: remove in 26 + _root: string, verbose: boolean, buffer: ConsoleBuffer, config: Config.ProjectConfig, From 1b1e7139c39534d25ec448d3a9e7f24a02ce4b02 Mon Sep 17 00:00:00 2001 From: ychi Date: Thu, 9 Apr 2020 17:51:04 +0200 Subject: [PATCH 05/29] Ignore unused parameter (sourceMaps) Co-Authored-By: Simen Bekkhus --- packages/jest-console/src/BufferedConsole.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/packages/jest-console/src/BufferedConsole.ts b/packages/jest-console/src/BufferedConsole.ts index 6fdcd4e0cd2e..125d90da4a33 100644 --- a/packages/jest-console/src/BufferedConsole.ts +++ b/packages/jest-console/src/BufferedConsole.ts @@ -48,8 +48,6 @@ export default class BufferedConsole extends Console { type: LogType, message: LogMessage, level?: number | null, - // @ts-ignore: To avoid breaking change. It's actually not used. - _sourceMaps?: SourceMapRegistry | null, ): ConsoleBuffer { const stackLevel = level != null ? level : 2; const rawStack = @@ -183,4 +181,4 @@ function invariant( if (!condition) { throw new Error(message); } -} \ No newline at end of file +} From 51258fbc63ecef6f34b090d04089938f83eb6a0f Mon Sep 17 00:00:00 2001 From: ychi Date: Thu, 9 Apr 2020 17:52:04 +0200 Subject: [PATCH 06/29] Remove redundant newline Co-Authored-By: Simen Bekkhus --- packages/jest-console/src/getConsoleOutput.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/jest-console/src/getConsoleOutput.ts b/packages/jest-console/src/getConsoleOutput.ts index fe5f38c97daa..67a3e6045f9f 100644 --- a/packages/jest-console/src/getConsoleOutput.ts +++ b/packages/jest-console/src/getConsoleOutput.ts @@ -23,7 +23,6 @@ export default ( const TITLE_INDENT = verbose ? ' ' : ' '; const CONSOLE_INDENT = TITLE_INDENT + ' '; - return buffer.reduce((output, {type, message, origin}) => { message = message .split(/\n/) From d15996cfbaa8a1a168f2d692698f7a4656a5a6a7 Mon Sep 17 00:00:00 2001 From: Yen-Chi Chen Date: Thu, 9 Apr 2020 18:11:37 +0200 Subject: [PATCH 07/29] More review feedbacks --- packages/jest-console/src/BufferedConsole.ts | 2 ++ packages/jest-message-util/src/index.ts | 31 +++++++++++--------- 2 files changed, 19 insertions(+), 14 deletions(-) diff --git a/packages/jest-console/src/BufferedConsole.ts b/packages/jest-console/src/BufferedConsole.ts index 125d90da4a33..019549209fea 100644 --- a/packages/jest-console/src/BufferedConsole.ts +++ b/packages/jest-console/src/BufferedConsole.ts @@ -48,6 +48,8 @@ export default class BufferedConsole extends Console { type: LogType, message: LogMessage, level?: number | null, + // TODO: remove in 26 + _sourceMaps?: SourceMapRegistry | null ): ConsoleBuffer { const stackLevel = level != null ? level : 2; const rawStack = diff --git a/packages/jest-message-util/src/index.ts b/packages/jest-message-util/src/index.ts index 765a772a1801..df23b5c28f3e 100644 --- a/packages/jest-message-util/src/index.ts +++ b/packages/jest-message-util/src/index.ts @@ -278,27 +278,30 @@ export const formatStackTrace = ( testPath?: Path, ): string => { const lines = getStackTraceLines(stack, options); - const topFrame = getTopFrame(lines); let renderedCallsite = ''; const relativeTestPath = testPath ? slash(path.relative(config.rootDir, testPath)) : null; - if (topFrame && !options.noCodeFrame) { - const {column, file: filename, line} = topFrame; - - if (line && filename && path.isAbsolute(filename)) { - let fileContent; - try { - // TODO: check & read HasteFS instead of reading the filesystem: - // see: https://github.com/facebook/jest/pull/5405#discussion_r164281696 - fileContent = fs.readFileSync(filename, 'utf8'); - renderedCallsite = getRenderedCallsite(fileContent, line, column); - } catch (e) { - // the file does not exist or is inaccessible, we ignore + if (!options.noCodeFrame) { + const topFrame = getTopFrame(lines); + + if (topFrame) { + const {column, file: filename, line} = topFrame; + + if (line && filename && path.isAbsolute(filename)) { + let fileContent; + try { + // TODO: check & read HasteFS instead of reading the filesystem: + // see: https://github.com/facebook/jest/pull/5405#discussion_r164281696 + fileContent = fs.readFileSync(filename, 'utf8'); + renderedCallsite = getRenderedCallsite(fileContent, line, column); + } catch (e) { + // the file does not exist or is inaccessible, we ignore + } } } - } + } const stacktrace = lines .filter(Boolean) From 881da4d611c950458af5e9b7c4ef237d2a7dd6f9 Mon Sep 17 00:00:00 2001 From: Yen-Chi Chen Date: Thu, 9 Apr 2020 18:46:43 +0200 Subject: [PATCH 08/29] Remove unused sourcemap --- packages/jest-console/package.json | 1 - packages/jest-console/src/BufferedConsole.ts | 12 +++--------- packages/jest-console/tsconfig.json | 1 - packages/jest-runner/src/runTest.ts | 5 ++--- 4 files changed, 5 insertions(+), 14 deletions(-) diff --git a/packages/jest-console/package.json b/packages/jest-console/package.json index 698f150821b7..7317031d20dd 100644 --- a/packages/jest-console/package.json +++ b/packages/jest-console/package.json @@ -17,7 +17,6 @@ } }, "dependencies": { - "@jest/source-map": "^25.2.6", "chalk": "^3.0.0", "jest-message-util": "^25.2.6", "jest-types": "^25.2.6", diff --git a/packages/jest-console/src/BufferedConsole.ts b/packages/jest-console/src/BufferedConsole.ts index 019549209fea..3dbca63cedfa 100644 --- a/packages/jest-console/src/BufferedConsole.ts +++ b/packages/jest-console/src/BufferedConsole.ts @@ -9,7 +9,6 @@ import assert = require('assert'); import {Console} from 'console'; import {format} from 'util'; import chalk = require('chalk'); -import type {SourceMapRegistry} from '@jest/source-map'; import {ErrorWithStack} from 'jest-util'; import type { @@ -25,18 +24,16 @@ export default class BufferedConsole extends Console { private _counters: LogCounters; private _timers: LogTimers; private _groupDepth: number; - private _getSourceMaps: () => SourceMapRegistry | null | undefined; - constructor(getSourceMaps: () => SourceMapRegistry | null | undefined) { + constructor() { const buffer: ConsoleBuffer = []; super({ write: (message: string) => { - BufferedConsole.write(buffer, 'log', message, null, getSourceMaps()); + BufferedConsole.write(buffer, 'log', message, null); return true; }, } as NodeJS.WritableStream); - this._getSourceMaps = getSourceMaps; this._buffer = buffer; this._counters = {}; this._timers = {}; @@ -48,8 +45,6 @@ export default class BufferedConsole extends Console { type: LogType, message: LogMessage, level?: number | null, - // TODO: remove in 26 - _sourceMaps?: SourceMapRegistry | null ): ConsoleBuffer { const stackLevel = level != null ? level : 2; const rawStack = @@ -77,8 +72,7 @@ export default class BufferedConsole extends Console { this._buffer, type, ' '.repeat(this._groupDepth) + message, - 3, - this._getSourceMaps(), + 3 ); } diff --git a/packages/jest-console/tsconfig.json b/packages/jest-console/tsconfig.json index 895d3c26862f..a436b61458e6 100644 --- a/packages/jest-console/tsconfig.json +++ b/packages/jest-console/tsconfig.json @@ -6,7 +6,6 @@ }, "references": [ {"path": "../jest-message-util"}, - {"path": "../jest-source-map"}, {"path": "../jest-types"}, {"path": "../jest-util"} ] diff --git a/packages/jest-runner/src/runTest.ts b/packages/jest-runner/src/runTest.ts index 68d5928c4f3a..03e0a96fb67c 100644 --- a/packages/jest-runner/src/runTest.ts +++ b/packages/jest-runner/src/runTest.ts @@ -126,8 +126,7 @@ async function runTestInternal( [], type, message, - 4, - runtime && runtime.getSourceMaps(), + 4 ), config, ); @@ -139,7 +138,7 @@ async function runTestInternal( } else if (globalConfig.verbose) { testConsole = new CustomConsole(consoleOut, consoleOut, consoleFormatter); } else { - testConsole = new BufferedConsole(() => runtime && runtime.getSourceMaps()); + testConsole = new BufferedConsole(); } const environment = new TestEnvironment(config, { From d33b5c3b6e3680ee323789d3bb29c94bb6688cdb Mon Sep 17 00:00:00 2001 From: Yen-Chi Chen Date: Thu, 9 Apr 2020 22:39:37 +0200 Subject: [PATCH 09/29] lint --- packages/jest-console/src/BufferedConsole.ts | 12 ++++-------- packages/jest-console/src/getConsoleOutput.ts | 11 ++--------- packages/jest-message-util/src/index.ts | 4 ++-- packages/jest-runner/src/runTest.ts | 7 +------ 4 files changed, 9 insertions(+), 25 deletions(-) diff --git a/packages/jest-console/src/BufferedConsole.ts b/packages/jest-console/src/BufferedConsole.ts index 3dbca63cedfa..e4247934f126 100644 --- a/packages/jest-console/src/BufferedConsole.ts +++ b/packages/jest-console/src/BufferedConsole.ts @@ -29,7 +29,7 @@ export default class BufferedConsole extends Console { const buffer: ConsoleBuffer = []; super({ write: (message: string) => { - BufferedConsole.write(buffer, 'log', message, null); + BufferedConsole.write(buffer, 'log', message, null); return true; }, @@ -47,8 +47,7 @@ export default class BufferedConsole extends Console { level?: number | null, ): ConsoleBuffer { const stackLevel = level != null ? level : 2; - const rawStack = - new ErrorWithStack(undefined, BufferedConsole.write).stack; + const rawStack = new ErrorWithStack(undefined, BufferedConsole.write).stack; invariant(rawStack, 'always have a stack trace'); @@ -72,7 +71,7 @@ export default class BufferedConsole extends Console { this._buffer, type, ' '.repeat(this._groupDepth) + message, - 3 + 3, ); } @@ -170,10 +169,7 @@ export default class BufferedConsole extends Console { } } -function invariant( - condition: unknown, - message?: string, -): asserts condition { +function invariant(condition: unknown, message?: string): asserts condition { if (!condition) { throw new Error(message); } diff --git a/packages/jest-console/src/getConsoleOutput.ts b/packages/jest-console/src/getConsoleOutput.ts index 67a3e6045f9f..df5bbe0c4c4a 100644 --- a/packages/jest-console/src/getConsoleOutput.ts +++ b/packages/jest-console/src/getConsoleOutput.ts @@ -7,10 +7,7 @@ import chalk = require('chalk'); import type {Config} from '@jest/types'; -import { - StackTraceOptions, - formatStackTrace, -} from 'jest-message-util'; +import {StackTraceOptions, formatStackTrace} from 'jest-message-util'; import type {ConsoleBuffer} from './types'; export default ( @@ -50,11 +47,7 @@ export default ( noStackTrace, }; - const formattedStackTrace = formatStackTrace( - origin, - config, - options, - ); + const formattedStackTrace = formatStackTrace(origin, config, options); return ( output + diff --git a/packages/jest-message-util/src/index.ts b/packages/jest-message-util/src/index.ts index df23b5c28f3e..12b8df24c48e 100644 --- a/packages/jest-message-util/src/index.ts +++ b/packages/jest-message-util/src/index.ts @@ -288,7 +288,7 @@ export const formatStackTrace = ( if (topFrame) { const {column, file: filename, line} = topFrame; - + if (line && filename && path.isAbsolute(filename)) { let fileContent; try { @@ -301,7 +301,7 @@ export const formatStackTrace = ( } } } - } + } const stacktrace = lines .filter(Boolean) diff --git a/packages/jest-runner/src/runTest.ts b/packages/jest-runner/src/runTest.ts index 03e0a96fb67c..f2f9ad507c8e 100644 --- a/packages/jest-runner/src/runTest.ts +++ b/packages/jest-runner/src/runTest.ts @@ -122,12 +122,7 @@ async function runTestInternal( config.cwd, !!globalConfig.verbose, // 4 = the console call is buried 4 stack frames deep - BufferedConsole.write( - [], - type, - message, - 4 - ), + BufferedConsole.write([], type, message, 4), config, ); From 23b34cfd523ac5022db5744411c9425d04c32f79 Mon Sep 17 00:00:00 2001 From: Yen-Chi Chen Date: Thu, 9 Apr 2020 23:07:55 +0200 Subject: [PATCH 10/29] update snapshots --- .../__snapshots__/beforeAllFiltered.ts.snap | 15 ++-- .../__snapshots__/beforeEachQueue.ts.snap | 15 ++-- .../__snapshots__/console.test.ts.snap | 71 +++++++++++++++---- .../consoleAfterTeardown.test.ts.snap | 2 +- ...consoleLogOutputWhenRunInBand.test.ts.snap | 3 +- .../declarationErrors.test.ts.snap | 2 + .../__snapshots__/jest.config.js.test.ts.snap | 3 +- e2e/__tests__/resolveBrowserField.test.ts | 3 +- 8 files changed, 88 insertions(+), 26 deletions(-) diff --git a/e2e/__tests__/__snapshots__/beforeAllFiltered.ts.snap b/e2e/__tests__/__snapshots__/beforeAllFiltered.ts.snap index 247de33015d5..192772e065ce 100644 --- a/e2e/__tests__/__snapshots__/beforeAllFiltered.ts.snap +++ b/e2e/__tests__/__snapshots__/beforeAllFiltered.ts.snap @@ -1,19 +1,24 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`Correct BeforeAll run ensures the BeforeAll of ignored suite is not run 1`] = ` - console.log __tests__/beforeAllFiltered.test.js:10 + console.log beforeAll 1 + at Object.log (__tests__/beforeAllFiltered.test.js:10:13) - console.log __tests__/beforeAllFiltered.test.js:13 + console.log beforeEach 1 + at Object.log (__tests__/beforeAllFiltered.test.js:13:13) - console.log __tests__/beforeAllFiltered.test.js:22 + console.log It Foo + at Object.log (__tests__/beforeAllFiltered.test.js:22:13) - console.log __tests__/beforeAllFiltered.test.js:16 + console.log afterEach 1 + at Object.log (__tests__/beforeAllFiltered.test.js:16:13) - console.log __tests__/beforeAllFiltered.test.js:19 + console.log afterAll 1 + at Object.log (__tests__/beforeAllFiltered.test.js:19:13) `; diff --git a/e2e/__tests__/__snapshots__/beforeEachQueue.ts.snap b/e2e/__tests__/__snapshots__/beforeEachQueue.ts.snap index a665905a9f06..05aa1771efc0 100644 --- a/e2e/__tests__/__snapshots__/beforeEachQueue.ts.snap +++ b/e2e/__tests__/__snapshots__/beforeEachQueue.ts.snap @@ -1,19 +1,24 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`Correct beforeEach order ensures the correct order for beforeEach 1`] = ` - console.log __tests__/beforeEachQueue.test.js:10 + console.log BeforeEach + at Object.log (__tests__/beforeEachQueue.test.js:10:13) - console.log __tests__/beforeEachQueue.test.js:14 + console.log It Foo + at Object.log (__tests__/beforeEachQueue.test.js:14:13) - console.log __tests__/beforeEachQueue.test.js:17 + console.log BeforeEach Inline Foo + at Object.log (__tests__/beforeEachQueue.test.js:17:15) - console.log __tests__/beforeEachQueue.test.js:10 + console.log BeforeEach + at Object.log (__tests__/beforeEachQueue.test.js:10:13) - console.log __tests__/beforeEachQueue.test.js:22 + console.log It Bar + at Object.log (__tests__/beforeEachQueue.test.js:22:13) `; diff --git a/e2e/__tests__/__snapshots__/console.test.ts.snap b/e2e/__tests__/__snapshots__/console.test.ts.snap index 8077db761de9..9fb32fa24ff3 100644 --- a/e2e/__tests__/__snapshots__/console.test.ts.snap +++ b/e2e/__tests__/__snapshots__/console.test.ts.snap @@ -4,14 +4,35 @@ exports[`console printing 1`] = ` PASS __tests__/console.test.js ● Console - console.log __tests__/console.test.js:10 + console.log This is a log message. - console.info __tests__/console.test.js:12 + at Object.log (__tests__/console.test.js:10:11) + console.info This is an info message. - console.warn __tests__/console.test.js:14 + at Object.info (__tests__/console.test.js:12:11) + console.warn This is a warning message. - console.error __tests__/console.test.js:16 + + 12 | console.info('This is an info message.'); + 13 | + > 14 | console.warn('This is a warning message.'); + | ^ + 15 | + 16 | console.error('This is an error message.'); + 17 | }); + + at Object.warn (__tests__/console.test.js:14:11) + console.error This is an error message. + + 14 | console.warn('This is a warning message.'); + 15 | + > 16 | console.error('This is an error message.'); + | ^ + 17 | }); + 18 | + + at Object.error (__tests__/console.test.js:16:11) `; exports[`console printing 2`] = ` @@ -23,18 +44,39 @@ Ran all test suites. `; exports[`console printing with --verbose 1`] = ` - console.log __tests__/console.test.js:10 + console.log This is a log message. + at Object.log (__tests__/console.test.js:10:11) - console.info __tests__/console.test.js:12 + console.info This is an info message. + at Object.info (__tests__/console.test.js:12:11) - console.warn __tests__/console.test.js:14 + console.warn This is a warning message. - console.error __tests__/console.test.js:16 + 12 | console.info('This is an info message.'); + 13 | + > 14 | console.warn('This is a warning message.'); + | ^ + 15 | + 16 | console.error('This is an error message.'); + 17 | }); + + at Object.warn (__tests__/console.test.js:14:11) + + console.error This is an error message. + 14 | console.warn('This is a warning message.'); + 15 | + > 16 | console.error('This is an error message.'); + | ^ + 17 | }); + 18 | + + at Object.error (__tests__/console.test.js:16:11) + `; exports[`console printing with --verbose 2`] = ` @@ -56,17 +98,22 @@ exports[`does not error out when using winston 2`] = ` PASS __tests__/console.test.js ● Console - console.log node_modules/winston/lib/winston/transports/console.js:79 + console.log {"level":"info","message":"Log message from winston"} - console.log node_modules/winston/lib/winston/transports/console.js:79 + at Console.log (node_modules/winston/lib/winston/transports/console.js:79:23) + console.log {"message":"Info message from winston","level":"info"} - console.log node_modules/winston/lib/winston/transports/console.js:79 + at Console.log (node_modules/winston/lib/winston/transports/console.js:79:23) + console.log {"message":"Warn message from winston","level":"warn"} - console.log node_modules/winston/lib/winston/transports/console.js:79 + at Console.log (node_modules/winston/lib/winston/transports/console.js:79:23) + console.log {"message":"Error message from winston","level":"error"} + + at Console.log (node_modules/winston/lib/winston/transports/console.js:79:23) `; exports[`does not error out when using winston 3`] = ` diff --git a/e2e/__tests__/__snapshots__/consoleAfterTeardown.test.ts.snap b/e2e/__tests__/__snapshots__/consoleAfterTeardown.test.ts.snap index 80308c7d489c..c75128492c2e 100644 --- a/e2e/__tests__/__snapshots__/consoleAfterTeardown.test.ts.snap +++ b/e2e/__tests__/__snapshots__/consoleAfterTeardown.test.ts.snap @@ -15,6 +15,6 @@ PASS __tests__/console.test.js 14 | }); 15 | - at BufferedConsole.log (../../packages/jest-console/build/BufferedConsole.js:199:10) + at BufferedConsole.log (../../packages/jest-console/build/BufferedConsole.js:201:10) at log (__tests__/console.test.js:12:13) `; diff --git a/e2e/__tests__/__snapshots__/consoleLogOutputWhenRunInBand.test.ts.snap b/e2e/__tests__/__snapshots__/consoleLogOutputWhenRunInBand.test.ts.snap index fb009e134aed..c10c464477cf 100644 --- a/e2e/__tests__/__snapshots__/consoleLogOutputWhenRunInBand.test.ts.snap +++ b/e2e/__tests__/__snapshots__/consoleLogOutputWhenRunInBand.test.ts.snap @@ -17,7 +17,8 @@ Ran all test suites. `; exports[`prints console.logs when run with forceExit 3`] = ` - console.log __tests__/a-banana.js:1 + console.log Hey + at Object. (__tests__/a-banana.js:1:1) `; diff --git a/e2e/__tests__/__snapshots__/declarationErrors.test.ts.snap b/e2e/__tests__/__snapshots__/declarationErrors.test.ts.snap index ae697a3dfe6c..ba8fbe981588 100644 --- a/e2e/__tests__/__snapshots__/declarationErrors.test.ts.snap +++ b/e2e/__tests__/__snapshots__/declarationErrors.test.ts.snap @@ -17,6 +17,7 @@ exports[`warns if describe returns a Promise 1`] = ` at Object.describe (__tests__/describeReturnPromise.test.js:11:1) + at addSpecsToSuite (../../packages/jest-jasmine2/build/jasmine/Env.js:450:21) " `; @@ -37,5 +38,6 @@ exports[`warns if describe returns something 1`] = ` at Object.describe (__tests__/describeReturnSomething.test.js:11:1) + at addSpecsToSuite (../../packages/jest-jasmine2/build/jasmine/Env.js:468:21) " `; diff --git a/e2e/__tests__/__snapshots__/jest.config.js.test.ts.snap b/e2e/__tests__/__snapshots__/jest.config.js.test.ts.snap index 498c5c97bfd8..e6574598170d 100644 --- a/e2e/__tests__/__snapshots__/jest.config.js.test.ts.snap +++ b/e2e/__tests__/__snapshots__/jest.config.js.test.ts.snap @@ -1,8 +1,9 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`traverses directory tree up until it finds jest.config 1`] = ` - console.log ../../../__tests__/a-banana.js:3 + console.log <>/jest.config.js/some/nested/directory + at Object.log (__tests__/a-banana.js:3:27) `; diff --git a/e2e/__tests__/resolveBrowserField.test.ts b/e2e/__tests__/resolveBrowserField.test.ts index f2e9383ed22c..2d7ffbf34b93 100644 --- a/e2e/__tests__/resolveBrowserField.test.ts +++ b/e2e/__tests__/resolveBrowserField.test.ts @@ -63,8 +63,9 @@ test('preserves module identity for symlinks when using browser field resolution const {stdout, stderr, exitCode} = runJest(DIR, ['--no-watchman']); expect(stderr).toContain('Test Suites: 1 passed, 1 total'); expect(wrap(stdout.trim())).toMatchInlineSnapshot(` - console.log packages/needs-preserved-id/index.js:1 + console.log needs-preserved-id executed + at Object. (packages/needs-preserved-id/index.js:1:13) `); expect(exitCode).toEqual(0); }); From 0fbf49b8b0857b4477049ba430687ca49d339240 Mon Sep 17 00:00:00 2001 From: Yen-Chi Chen Date: Fri, 10 Apr 2020 21:38:06 +0200 Subject: [PATCH 11/29] correct package name & bump dep version --- packages/jest-console/package.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/jest-console/package.json b/packages/jest-console/package.json index 7317031d20dd..3b7e6f1ce578 100644 --- a/packages/jest-console/package.json +++ b/packages/jest-console/package.json @@ -17,10 +17,10 @@ } }, "dependencies": { + "@jest/types": "^25.3.0", "chalk": "^3.0.0", - "jest-message-util": "^25.2.6", - "jest-types": "^25.2.6", - "jest-util": "^25.2.6", + "jest-message-util": "^25.3.0", + "jest-util": "^25.3.0", "slash": "^3.0.0" }, "devDependencies": { From fd6a4f1bd5e6b764046fb08eb556fb76d80d1126 Mon Sep 17 00:00:00 2001 From: Yen-Chi Chen Date: Fri, 10 Apr 2020 21:38:22 +0200 Subject: [PATCH 12/29] Review feedbacks --- packages/jest-console/src/BufferedConsole.ts | 1 - packages/jest-console/src/getConsoleOutput.ts | 25 ++++++++++++++++--- 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/packages/jest-console/src/BufferedConsole.ts b/packages/jest-console/src/BufferedConsole.ts index e4247934f126..2bf53f350f72 100644 --- a/packages/jest-console/src/BufferedConsole.ts +++ b/packages/jest-console/src/BufferedConsole.ts @@ -10,7 +10,6 @@ import {Console} from 'console'; import {format} from 'util'; import chalk = require('chalk'); import {ErrorWithStack} from 'jest-util'; - import type { ConsoleBuffer, LogCounters, diff --git a/packages/jest-console/src/getConsoleOutput.ts b/packages/jest-console/src/getConsoleOutput.ts index df5bbe0c4c4a..97daf286df8a 100644 --- a/packages/jest-console/src/getConsoleOutput.ts +++ b/packages/jest-console/src/getConsoleOutput.ts @@ -6,8 +6,11 @@ */ import chalk = require('chalk'); -import type {Config} from '@jest/types'; -import {StackTraceOptions, formatStackTrace} from 'jest-message-util'; +import { + StackTraceConfig, + StackTraceOptions, + formatStackTrace, +} from 'jest-message-util'; import type {ConsoleBuffer} from './types'; export default ( @@ -15,11 +18,21 @@ export default ( _root: string, verbose: boolean, buffer: ConsoleBuffer, - config: Config.ProjectConfig, + // TODO: make mandatory and take Config.ProjectConfig in 26 + config?: StackTraceConfig, ): string => { const TITLE_INDENT = verbose ? ' ' : ' '; const CONSOLE_INDENT = TITLE_INDENT + ' '; + //TODO: remove in 26 + const stackTraceConfig: StackTraceConfig = + config != null + ? config + : { + rootDir: _root, + testMatch: [], + }; + return buffer.reduce((output, {type, message, origin}) => { message = message .split(/\n/) @@ -47,7 +60,11 @@ export default ( noStackTrace, }; - const formattedStackTrace = formatStackTrace(origin, config, options); + const formattedStackTrace = formatStackTrace( + origin, + stackTraceConfig, + options, + ); return ( output + From 211bd7caff673bb8b9641fd55cb31722ec1ad08a Mon Sep 17 00:00:00 2001 From: Yen-Chi Chen Date: Fri, 10 Apr 2020 22:21:29 +0200 Subject: [PATCH 13/29] fix declarationErrors normalisation --- e2e/__tests__/__snapshots__/declarationErrors.test.ts.snap | 2 -- e2e/__tests__/declarationErrors.test.ts | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/e2e/__tests__/__snapshots__/declarationErrors.test.ts.snap b/e2e/__tests__/__snapshots__/declarationErrors.test.ts.snap index ba8fbe981588..ae697a3dfe6c 100644 --- a/e2e/__tests__/__snapshots__/declarationErrors.test.ts.snap +++ b/e2e/__tests__/__snapshots__/declarationErrors.test.ts.snap @@ -17,7 +17,6 @@ exports[`warns if describe returns a Promise 1`] = ` at Object.describe (__tests__/describeReturnPromise.test.js:11:1) - at addSpecsToSuite (../../packages/jest-jasmine2/build/jasmine/Env.js:450:21) " `; @@ -38,6 +37,5 @@ exports[`warns if describe returns something 1`] = ` at Object.describe (__tests__/describeReturnSomething.test.js:11:1) - at addSpecsToSuite (../../packages/jest-jasmine2/build/jasmine/Env.js:468:21) " `; diff --git a/e2e/__tests__/declarationErrors.test.ts b/e2e/__tests__/declarationErrors.test.ts index 2c5058f0e164..1efa840d47ed 100644 --- a/e2e/__tests__/declarationErrors.test.ts +++ b/e2e/__tests__/declarationErrors.test.ts @@ -10,7 +10,7 @@ import runJest from '../runJest'; const normalizeCircusJasmine = (str: string) => str .replace(/console\.log .+:\d+/, 'console.log') - .replace(/.+addSpecsToSuite (.+:\d+:\d+).+\n/, ''); + .replace(/.+addSpecsToSuite (.+:\d+:\d+).+\n/g, ''); it('warns if describe returns a Promise', () => { const result = runJest('declaration-errors', [ From a9d18b57c2d413d06b4a089ee5f511c2b412cc25 Mon Sep 17 00:00:00 2001 From: Yen-Chi Chen Date: Fri, 10 Apr 2020 22:42:31 +0200 Subject: [PATCH 14/29] fix v8 coverage test --- e2e/__tests__/v8Coverage.test.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/e2e/__tests__/v8Coverage.test.ts b/e2e/__tests__/v8Coverage.test.ts index 97dfea44252f..8cbd868025cf 100644 --- a/e2e/__tests__/v8Coverage.test.ts +++ b/e2e/__tests__/v8Coverage.test.ts @@ -14,6 +14,7 @@ const DIR = path.resolve(__dirname, '../v8-coverage'); onNodeVersions('>=10', () => { test('prints coverage', () => { const sourcemapDir = path.join(DIR, 'no-sourcemap'); + const {stdout, exitCode} = runJest( sourcemapDir, ['--coverage', '--coverage-provider', 'v8'], @@ -31,8 +32,9 @@ onNodeVersions('>=10', () => { .join('\n') + '\n', ).toEqual(` - console.log __tests__/Thing.test.js:10 + console.log 42 + at Object.log (__tests__/Thing.test.js:10:9) ----------|---------|----------|---------|---------|------------------- File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s From 16efc8a9cd71594bf3b26676fa571de73dea951a Mon Sep 17 00:00:00 2001 From: Yen-Chi Chen Date: Sat, 11 Apr 2020 22:18:59 +0200 Subject: [PATCH 15/29] Review feedbacks --- packages/jest-console/src/getConsoleOutput.ts | 4 ++-- packages/jest-message-util/src/index.ts | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/jest-console/src/getConsoleOutput.ts b/packages/jest-console/src/getConsoleOutput.ts index 97daf286df8a..49014efd1fd3 100644 --- a/packages/jest-console/src/getConsoleOutput.ts +++ b/packages/jest-console/src/getConsoleOutput.ts @@ -15,7 +15,7 @@ import type {ConsoleBuffer} from './types'; export default ( // TODO: remove in 26 - _root: string, + root: string, verbose: boolean, buffer: ConsoleBuffer, // TODO: make mandatory and take Config.ProjectConfig in 26 @@ -29,7 +29,7 @@ export default ( config != null ? config : { - rootDir: _root, + rootDir: root, testMatch: [], }; diff --git a/packages/jest-message-util/src/index.ts b/packages/jest-message-util/src/index.ts index 12b8df24c48e..20b284b2535a 100644 --- a/packages/jest-message-util/src/index.ts +++ b/packages/jest-message-util/src/index.ts @@ -311,9 +311,9 @@ export const formatStackTrace = ( ) .join('\n'); - return options.noCodeFrame - ? `${stacktrace}` - : `${renderedCallsite}\n${stacktrace}`; + return renderedCallsite + ? `${renderedCallsite}\n${stacktrace}` + : `${stacktrace}`; }; type FailedResults = Array<{ From 3fbcd890962941ef24492cad09428fee62ca148f Mon Sep 17 00:00:00 2001 From: Simen Bekkhus Date: Sat, 11 Apr 2020 22:42:03 +0200 Subject: [PATCH 16/29] chore: consisten newlines --- packages/jest-message-util/src/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/jest-message-util/src/index.ts b/packages/jest-message-util/src/index.ts index 20b284b2535a..b3c1fbb5967b 100644 --- a/packages/jest-message-util/src/index.ts +++ b/packages/jest-message-util/src/index.ts @@ -313,7 +313,7 @@ export const formatStackTrace = ( return renderedCallsite ? `${renderedCallsite}\n${stacktrace}` - : `${stacktrace}`; + : `\n${stacktrace}`; }; type FailedResults = Array<{ From afd68b64c563d0216d5f4b09b0d10b53ca713e06 Mon Sep 17 00:00:00 2001 From: Simen Bekkhus Date: Sat, 11 Apr 2020 23:24:35 +0200 Subject: [PATCH 17/29] update snaps --- e2e/__tests__/__snapshots__/beforeAllFiltered.ts.snap | 5 +++++ e2e/__tests__/__snapshots__/beforeEachQueue.ts.snap | 5 +++++ e2e/__tests__/__snapshots__/console.test.ts.snap | 8 ++++++++ .../consoleLogOutputWhenRunInBand.test.ts.snap | 1 + e2e/__tests__/__snapshots__/jest.config.js.test.ts.snap | 1 + e2e/__tests__/resolveBrowserField.test.ts | 1 + e2e/__tests__/v8Coverage.test.ts | 1 + 7 files changed, 22 insertions(+) diff --git a/e2e/__tests__/__snapshots__/beforeAllFiltered.ts.snap b/e2e/__tests__/__snapshots__/beforeAllFiltered.ts.snap index 192772e065ce..dad381246358 100644 --- a/e2e/__tests__/__snapshots__/beforeAllFiltered.ts.snap +++ b/e2e/__tests__/__snapshots__/beforeAllFiltered.ts.snap @@ -3,22 +3,27 @@ exports[`Correct BeforeAll run ensures the BeforeAll of ignored suite is not run 1`] = ` console.log beforeAll 1 + at Object.log (__tests__/beforeAllFiltered.test.js:10:13) console.log beforeEach 1 + at Object.log (__tests__/beforeAllFiltered.test.js:13:13) console.log It Foo + at Object.log (__tests__/beforeAllFiltered.test.js:22:13) console.log afterEach 1 + at Object.log (__tests__/beforeAllFiltered.test.js:16:13) console.log afterAll 1 + at Object.log (__tests__/beforeAllFiltered.test.js:19:13) `; diff --git a/e2e/__tests__/__snapshots__/beforeEachQueue.ts.snap b/e2e/__tests__/__snapshots__/beforeEachQueue.ts.snap index 05aa1771efc0..4acca9e4a59d 100644 --- a/e2e/__tests__/__snapshots__/beforeEachQueue.ts.snap +++ b/e2e/__tests__/__snapshots__/beforeEachQueue.ts.snap @@ -3,22 +3,27 @@ exports[`Correct beforeEach order ensures the correct order for beforeEach 1`] = ` console.log BeforeEach + at Object.log (__tests__/beforeEachQueue.test.js:10:13) console.log It Foo + at Object.log (__tests__/beforeEachQueue.test.js:14:13) console.log BeforeEach Inline Foo + at Object.log (__tests__/beforeEachQueue.test.js:17:15) console.log BeforeEach + at Object.log (__tests__/beforeEachQueue.test.js:10:13) console.log It Bar + at Object.log (__tests__/beforeEachQueue.test.js:22:13) `; diff --git a/e2e/__tests__/__snapshots__/console.test.ts.snap b/e2e/__tests__/__snapshots__/console.test.ts.snap index 9fb32fa24ff3..8a7e4b401534 100644 --- a/e2e/__tests__/__snapshots__/console.test.ts.snap +++ b/e2e/__tests__/__snapshots__/console.test.ts.snap @@ -6,9 +6,11 @@ PASS __tests__/console.test.js console.log This is a log message. + at Object.log (__tests__/console.test.js:10:11) console.info This is an info message. + at Object.info (__tests__/console.test.js:12:11) console.warn This is a warning message. @@ -46,10 +48,12 @@ Ran all test suites. exports[`console printing with --verbose 1`] = ` console.log This is a log message. + at Object.log (__tests__/console.test.js:10:11) console.info This is an info message. + at Object.info (__tests__/console.test.js:12:11) console.warn @@ -101,18 +105,22 @@ PASS __tests__/console.test.js console.log {"level":"info","message":"Log message from winston"} + at Console.log (node_modules/winston/lib/winston/transports/console.js:79:23) console.log {"message":"Info message from winston","level":"info"} + at Console.log (node_modules/winston/lib/winston/transports/console.js:79:23) console.log {"message":"Warn message from winston","level":"warn"} + at Console.log (node_modules/winston/lib/winston/transports/console.js:79:23) console.log {"message":"Error message from winston","level":"error"} + at Console.log (node_modules/winston/lib/winston/transports/console.js:79:23) `; diff --git a/e2e/__tests__/__snapshots__/consoleLogOutputWhenRunInBand.test.ts.snap b/e2e/__tests__/__snapshots__/consoleLogOutputWhenRunInBand.test.ts.snap index c10c464477cf..571dd419e639 100644 --- a/e2e/__tests__/__snapshots__/consoleLogOutputWhenRunInBand.test.ts.snap +++ b/e2e/__tests__/__snapshots__/consoleLogOutputWhenRunInBand.test.ts.snap @@ -19,6 +19,7 @@ Ran all test suites. exports[`prints console.logs when run with forceExit 3`] = ` console.log Hey + at Object. (__tests__/a-banana.js:1:1) `; diff --git a/e2e/__tests__/__snapshots__/jest.config.js.test.ts.snap b/e2e/__tests__/__snapshots__/jest.config.js.test.ts.snap index e6574598170d..db94a91b08e4 100644 --- a/e2e/__tests__/__snapshots__/jest.config.js.test.ts.snap +++ b/e2e/__tests__/__snapshots__/jest.config.js.test.ts.snap @@ -3,6 +3,7 @@ exports[`traverses directory tree up until it finds jest.config 1`] = ` console.log <>/jest.config.js/some/nested/directory + at Object.log (__tests__/a-banana.js:3:27) `; diff --git a/e2e/__tests__/resolveBrowserField.test.ts b/e2e/__tests__/resolveBrowserField.test.ts index 2d7ffbf34b93..2c37924e2bc5 100644 --- a/e2e/__tests__/resolveBrowserField.test.ts +++ b/e2e/__tests__/resolveBrowserField.test.ts @@ -65,6 +65,7 @@ test('preserves module identity for symlinks when using browser field resolution expect(wrap(stdout.trim())).toMatchInlineSnapshot(` console.log needs-preserved-id executed + at Object. (packages/needs-preserved-id/index.js:1:13) `); expect(exitCode).toEqual(0); diff --git a/e2e/__tests__/v8Coverage.test.ts b/e2e/__tests__/v8Coverage.test.ts index 8cbd868025cf..767c56da8a8f 100644 --- a/e2e/__tests__/v8Coverage.test.ts +++ b/e2e/__tests__/v8Coverage.test.ts @@ -34,6 +34,7 @@ onNodeVersions('>=10', () => { ).toEqual(` console.log 42 + at Object.log (__tests__/Thing.test.js:10:9) ----------|---------|----------|---------|---------|------------------- From fb0854ea3c0bac919ed2654207a6547c9836d21c Mon Sep 17 00:00:00 2001 From: Simen Bekkhus Date: Sat, 11 Apr 2020 23:40:14 +0200 Subject: [PATCH 18/29] tweak newlines in between messages --- e2e/__tests__/__snapshots__/console.test.ts.snap | 10 ++++++---- .../__snapshots__/declarationErrors.test.ts.snap | 2 -- packages/jest-console/src/getConsoleOutput.ts | 10 ++++++---- 3 files changed, 12 insertions(+), 10 deletions(-) diff --git a/e2e/__tests__/__snapshots__/console.test.ts.snap b/e2e/__tests__/__snapshots__/console.test.ts.snap index 8a7e4b401534..161e2e9e4c21 100644 --- a/e2e/__tests__/__snapshots__/console.test.ts.snap +++ b/e2e/__tests__/__snapshots__/console.test.ts.snap @@ -8,10 +8,12 @@ PASS __tests__/console.test.js This is a log message. at Object.log (__tests__/console.test.js:10:11) + console.info This is an info message. at Object.info (__tests__/console.test.js:12:11) + console.warn This is a warning message. @@ -24,6 +26,7 @@ PASS __tests__/console.test.js 17 | }); at Object.warn (__tests__/console.test.js:14:11) + console.error This is an error message. @@ -104,22 +107,21 @@ PASS __tests__/console.test.js console.log {"level":"info","message":"Log message from winston"} - at Console.log (node_modules/winston/lib/winston/transports/console.js:79:23) + console.log {"message":"Info message from winston","level":"info"} - at Console.log (node_modules/winston/lib/winston/transports/console.js:79:23) + console.log {"message":"Warn message from winston","level":"warn"} - at Console.log (node_modules/winston/lib/winston/transports/console.js:79:23) + console.log {"message":"Error message from winston","level":"error"} - at Console.log (node_modules/winston/lib/winston/transports/console.js:79:23) `; diff --git a/e2e/__tests__/__snapshots__/declarationErrors.test.ts.snap b/e2e/__tests__/__snapshots__/declarationErrors.test.ts.snap index b8e81719d080..017f5cc6d332 100644 --- a/e2e/__tests__/__snapshots__/declarationErrors.test.ts.snap +++ b/e2e/__tests__/__snapshots__/declarationErrors.test.ts.snap @@ -16,7 +16,6 @@ exports[`warns if describe returns a Promise 1`] = ` 14 | }); at Object.describe (__tests__/describeReturnPromise.test.js:11:1) - `; @@ -37,7 +36,6 @@ exports[`warns if describe returns something 1`] = ` 14 | }); at Object.describe (__tests__/describeReturnSomething.test.js:11:1) - `; diff --git a/packages/jest-console/src/getConsoleOutput.ts b/packages/jest-console/src/getConsoleOutput.ts index 49014efd1fd3..a90670957aca 100644 --- a/packages/jest-console/src/getConsoleOutput.ts +++ b/packages/jest-console/src/getConsoleOutput.ts @@ -33,7 +33,7 @@ export default ( testMatch: [], }; - return buffer.reduce((output, {type, message, origin}) => { + const logEntries = buffer.reduce((output, {type, message, origin}) => { message = message .split(/\n/) .map(line => CONSOLE_INDENT + line) @@ -71,10 +71,12 @@ export default ( TITLE_INDENT + chalk.dim(typeMessage) + '\n' + - message + + message.trimRight() + '\n' + - chalk.dim(formattedStackTrace) + - '\n' + chalk.dim(formattedStackTrace.trimRight()) + + '\n\n' ); }, ''); + + return logEntries.trimRight() + '\n'; }; From 34901a36e9ca8a2fb30b58400cf398527ab8e1d5 Mon Sep 17 00:00:00 2001 From: Simen Bekkhus Date: Sat, 11 Apr 2020 23:49:22 +0200 Subject: [PATCH 19/29] fix circus test --- e2e/__tests__/declarationErrors.test.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/e2e/__tests__/declarationErrors.test.ts b/e2e/__tests__/declarationErrors.test.ts index e0c10bb09a3f..d0d1dda1db16 100644 --- a/e2e/__tests__/declarationErrors.test.ts +++ b/e2e/__tests__/declarationErrors.test.ts @@ -12,7 +12,8 @@ const normalizeCircusJasmine = (str: string) => wrap( str .replace(/console\.log .+:\d+/, 'console.log') - .replace(/.+addSpecsToSuite (.+:\d+:\d+).+\n/g, ''), + .replace(/.+addSpecsToSuite (.+:\d+:\d+).+\n/g, '') + .replace(/.+_dispatchDescribe (.+:\d+:\d+).+\n/g, ''), ); it('warns if describe returns a Promise', () => { From 3a8908d2559a53bb57c0bd03d5d7df59cf45bbf5 Mon Sep 17 00:00:00 2001 From: Simen Bekkhus Date: Sat, 11 Apr 2020 23:55:29 +0200 Subject: [PATCH 20/29] fix test diff between node versions --- .../consoleLogOutputWhenRunInBand.test.ts | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/e2e/__tests__/consoleLogOutputWhenRunInBand.test.ts b/e2e/__tests__/consoleLogOutputWhenRunInBand.test.ts index e49a61328672..3e505c906365 100644 --- a/e2e/__tests__/consoleLogOutputWhenRunInBand.test.ts +++ b/e2e/__tests__/consoleLogOutputWhenRunInBand.test.ts @@ -15,6 +15,8 @@ const DIR = path.resolve(__dirname, '../console-log-output-when-run-in-band'); beforeEach(() => cleanup(DIR)); afterAll(() => cleanup(DIR)); +const nodeMajorVersion = Number(process.versions.node.split('.')[0]); + test('prints console.logs when run with forceExit', () => { writeFiles(DIR, { '__tests__/a-banana.js': ` @@ -23,12 +25,26 @@ test('prints console.logs when run with forceExit', () => { 'package.json': '{}', }); - const {stderr, stdout, exitCode} = runJest(DIR, [ + const {stderr, exitCode, ...res} = runJest(DIR, [ '-i', '--ci=false', '--forceExit', ]); + let {stdout} = res; + const {rest, summary} = extractSummary(stderr); + + if (nodeMajorVersion < 12) { + expect(stdout).toContain( + 'at Object..test (__tests__/a-banana.js:1:1)', + ); + + stdout = stdout.replace( + 'at Object..test (__tests__/a-banana.js:1:1)', + 'at Object. (__tests__/a-banana.js:1:1)', + ); + } + expect(exitCode).toBe(0); expect(wrap(rest)).toMatchSnapshot(); expect(wrap(summary)).toMatchSnapshot(); From 58cd2f6df569e2dc893acab0a2e0545e6c18e756 Mon Sep 17 00:00:00 2001 From: Simen Bekkhus Date: Sun, 12 Apr 2020 00:00:09 +0200 Subject: [PATCH 21/29] another circus fix --- e2e/__tests__/__snapshots__/beforeAllFiltered.ts.snap | 10 +++++----- e2e/__tests__/beforeAllFiltered.ts | 8 ++++++-- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/e2e/__tests__/__snapshots__/beforeAllFiltered.ts.snap b/e2e/__tests__/__snapshots__/beforeAllFiltered.ts.snap index dad381246358..77cb833acb56 100644 --- a/e2e/__tests__/__snapshots__/beforeAllFiltered.ts.snap +++ b/e2e/__tests__/__snapshots__/beforeAllFiltered.ts.snap @@ -4,26 +4,26 @@ exports[`Correct BeforeAll run ensures the BeforeAll of ignored suite is not run console.log beforeAll 1 - at Object.log (__tests__/beforeAllFiltered.test.js:10:13) + at log (__tests__/beforeAllFiltered.test.js:10:13) console.log beforeEach 1 - at Object.log (__tests__/beforeAllFiltered.test.js:13:13) + at log (__tests__/beforeAllFiltered.test.js:13:13) console.log It Foo - at Object.log (__tests__/beforeAllFiltered.test.js:22:13) + at log (__tests__/beforeAllFiltered.test.js:22:13) console.log afterEach 1 - at Object.log (__tests__/beforeAllFiltered.test.js:16:13) + at log (__tests__/beforeAllFiltered.test.js:16:13) console.log afterAll 1 - at Object.log (__tests__/beforeAllFiltered.test.js:19:13) + at log (__tests__/beforeAllFiltered.test.js:19:13) `; diff --git a/e2e/__tests__/beforeAllFiltered.ts b/e2e/__tests__/beforeAllFiltered.ts index fdd03d373486..7d0a5cf4fbc5 100644 --- a/e2e/__tests__/beforeAllFiltered.ts +++ b/e2e/__tests__/beforeAllFiltered.ts @@ -10,7 +10,11 @@ import runJest from '../runJest'; describe('Correct BeforeAll run', () => { it('ensures the BeforeAll of ignored suite is not run', () => { - const result = runJest('before-all-filtered'); - expect(wrap(result.stdout.replace(/\\/g, '/'))).toMatchSnapshot(); + let {stdout} = runJest('before-all-filtered'); + + // for some reason Circus does not have the `Object` part + stdout = stdout.replace(/at Object.log \(/g, 'at log ('); + + expect(wrap(stdout)).toMatchSnapshot(); }); }); From fb47353ca218522d289c807394d1e399cb4344b8 Mon Sep 17 00:00:00 2001 From: Simen Bekkhus Date: Sun, 12 Apr 2020 00:04:05 +0200 Subject: [PATCH 22/29] use snapshot --- .../__snapshots__/v8Coverage.test.ts.snap | 16 ++++++++++++++ e2e/__tests__/v8Coverage.test.ts | 22 +------------------ 2 files changed, 17 insertions(+), 21 deletions(-) create mode 100644 e2e/__tests__/__snapshots__/v8Coverage.test.ts.snap diff --git a/e2e/__tests__/__snapshots__/v8Coverage.test.ts.snap b/e2e/__tests__/__snapshots__/v8Coverage.test.ts.snap new file mode 100644 index 000000000000..a3fabf97c9d7 --- /dev/null +++ b/e2e/__tests__/__snapshots__/v8Coverage.test.ts.snap @@ -0,0 +1,16 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`on node >=10 prints coverage 1`] = ` +" console.log + 42 + + at Object.log (__tests__/Thing.test.js:10:9) + +----------|---------|----------|---------|---------|------------------- +File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s +----------|---------|----------|---------|---------|------------------- +All files | 100 | 100 | 100 | 100 | + Thing.js | 100 | 100 | 100 | 100 | + x.css | 100 | 100 | 100 | 100 | +----------|---------|----------|---------|---------|-------------------" +`; diff --git a/e2e/__tests__/v8Coverage.test.ts b/e2e/__tests__/v8Coverage.test.ts index 767c56da8a8f..902d324aab10 100644 --- a/e2e/__tests__/v8Coverage.test.ts +++ b/e2e/__tests__/v8Coverage.test.ts @@ -24,26 +24,6 @@ onNodeVersions('>=10', () => { ); expect(exitCode).toBe(0); - expect( - '\n' + - stdout - .split('\n') - .map(s => s.trimRight()) - .join('\n') + - '\n', - ).toEqual(` - console.log - 42 - - at Object.log (__tests__/Thing.test.js:10:9) - -----------|---------|----------|---------|---------|------------------- -File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s -----------|---------|----------|---------|---------|------------------- -All files | 100 | 100 | 100 | 100 | - Thing.js | 100 | 100 | 100 | 100 | - x.css | 100 | 100 | 100 | 100 | -----------|---------|----------|---------|---------|------------------- -`); + expect(stdout).toMatchSnapshot(); }); }); From 21ee2535f4cd14c7ac4bc7985369844a30255133 Mon Sep 17 00:00:00 2001 From: Simen Bekkhus Date: Sun, 12 Apr 2020 00:08:14 +0200 Subject: [PATCH 23/29] runtime can be const now --- packages/jest-runner/src/runTest.ts | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/packages/jest-runner/src/runTest.ts b/packages/jest-runner/src/runTest.ts index f2f9ad507c8e..87b9e809720c 100644 --- a/packages/jest-runner/src/runTest.ts +++ b/packages/jest-runner/src/runTest.ts @@ -114,8 +114,6 @@ async function runTestInternal( ? require(config.moduleLoader) : require('jest-runtime'); - let runtime: RuntimeClass | undefined = undefined; - const consoleOut = globalConfig.useStderr ? process.stderr : process.stdout; const consoleFormatter = (type: LogType, message: LogMessage) => getConsoleOutput( @@ -148,7 +146,7 @@ async function runTestInternal( const cacheFS = {[path]: testSource}; setGlobal(environment.global, 'console', testConsole); - runtime = new Runtime(config, environment, resolver, cacheFS, { + const runtime = new Runtime(config, environment, resolver, cacheFS, { changedFiles: context && context.changedFiles, collectCoverage: globalConfig.collectCoverage, collectCoverageFrom: globalConfig.collectCoverageFrom, @@ -158,13 +156,13 @@ async function runTestInternal( const start = Date.now(); - config.setupFiles.forEach(path => runtime!.requireModule(path)); + config.setupFiles.forEach(path => runtime.requireModule(path)); const sourcemapOptions: sourcemapSupport.Options = { environment: 'node', handleUncaughtExceptions: false, retrieveSourceMap: source => { - const sourceMaps = runtime && runtime.getSourceMaps(); + const sourceMaps = runtime.getSourceMaps(); const sourceMapSource = sourceMaps && sourceMaps[source]; if (sourceMapSource) { From 1e99400badc133702131250ae3144d123869c45b Mon Sep 17 00:00:00 2001 From: Simen Bekkhus Date: Sun, 12 Apr 2020 00:12:50 +0200 Subject: [PATCH 24/29] use default param --- packages/jest-console/src/getConsoleOutput.ts | 20 +++++-------------- 1 file changed, 5 insertions(+), 15 deletions(-) diff --git a/packages/jest-console/src/getConsoleOutput.ts b/packages/jest-console/src/getConsoleOutput.ts index a90670957aca..1c3dba19f898 100644 --- a/packages/jest-console/src/getConsoleOutput.ts +++ b/packages/jest-console/src/getConsoleOutput.ts @@ -19,20 +19,14 @@ export default ( verbose: boolean, buffer: ConsoleBuffer, // TODO: make mandatory and take Config.ProjectConfig in 26 - config?: StackTraceConfig, + config: StackTraceConfig = { + rootDir: root, + testMatch: [], + }, ): string => { const TITLE_INDENT = verbose ? ' ' : ' '; const CONSOLE_INDENT = TITLE_INDENT + ' '; - //TODO: remove in 26 - const stackTraceConfig: StackTraceConfig = - config != null - ? config - : { - rootDir: root, - testMatch: [], - }; - const logEntries = buffer.reduce((output, {type, message, origin}) => { message = message .split(/\n/) @@ -60,11 +54,7 @@ export default ( noStackTrace, }; - const formattedStackTrace = formatStackTrace( - origin, - stackTraceConfig, - options, - ); + const formattedStackTrace = formatStackTrace(origin, config, options); return ( output + From 8b6b76daf76c0def290efaf4b6fcfebb705e4181 Mon Sep 17 00:00:00 2001 From: Simen Bekkhus Date: Sun, 12 Apr 2020 00:15:34 +0200 Subject: [PATCH 25/29] changelog --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index fa2445e8f8b4..d364c9f036bc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ ### Features +- `[jest-console]` Add code frame to `console.error` and `console.warn` ([#9741](https://github.com/facebook/jest/pull/9741)) + ### Fixes - `[expect]` Restore support for passing functions to `toHaveLength` matcher ([#9796](https://github.com/facebook/jest/pull/9796)) From 3d9d47d4ba047d2f7634aea84478973f3f72829f Mon Sep 17 00:00:00 2001 From: Simen Bekkhus Date: Sun, 12 Apr 2020 17:58:27 +0200 Subject: [PATCH 26/29] unit tests jest-message-util --- .../__snapshots__/messages.test.ts.snap | 32 +++++- .../src/__tests__/messages.test.ts | 100 +++++++++++++++++- 2 files changed, 130 insertions(+), 2 deletions(-) diff --git a/packages/jest-message-util/src/__tests__/__snapshots__/messages.test.ts.snap b/packages/jest-message-util/src/__tests__/__snapshots__/messages.test.ts.snap index 8fb8249ca9b5..9dd7f87d3829 100644 --- a/packages/jest-message-util/src/__tests__/__snapshots__/messages.test.ts.snap +++ b/packages/jest-message-util/src/__tests__/__snapshots__/messages.test.ts.snap @@ -7,6 +7,19 @@ exports[`.formatExecError() 1`] = ` " `; +exports[`codeframe 1`] = ` +" ● Test suite failed to run + + Whoops! + + > 1 | throw new Error(\\"Whoops!\\"); + | ^ + + at Object. (../../../Jester/jest/file.js:1:7) + at internal/main/run_main_module.js:18:47 +" +`; + exports[`formatStackTrace should strip node internals 1`] = ` " Unix test @@ -23,6 +36,23 @@ exports[`formatStackTrace should strip node internals 1`] = ` " `; +exports[`no codeframe 1`] = ` +" ● Test suite failed to run + + Whoops! + + at Object. (../../../Jester/jest/file.js:1:7) + at internal/main/run_main_module.js:18:47 +" +`; + +exports[`no stack 1`] = ` +" ● Test suite failed to run + + Whoops! +" +`; + exports[`retains message in babel code frame error 1`] = ` " Babel test @@ -30,7 +60,7 @@ exports[`retains message in babel code frame error 1`] = ` packages/react/src/forwardRef.js: Unexpected token, expected , (20:10) 18 | false, - 19 | 'forwardRef requires a render function but received a \`memo\` ' + 19 | 'forwardRef requires a render function but received a \`memo\` ' > 20 | 'component. Instead of forwardRef(memo(...)), use ' + | ^ 21 | 'memo(forwardRef(...)).', diff --git a/packages/jest-message-util/src/__tests__/messages.test.ts b/packages/jest-message-util/src/__tests__/messages.test.ts index 667038690713..6f82f0e2c175 100644 --- a/packages/jest-message-util/src/__tests__/messages.test.ts +++ b/packages/jest-message-util/src/__tests__/messages.test.ts @@ -6,8 +6,11 @@ * */ +import {readFileSync} from 'fs'; import {formatExecError, formatResultsErrors} from '..'; +jest.mock('fs'); + const unixStackTrace = ` ` + `at stack (../jest-jasmine2/build/jasmine-2.4.1.js:1580:17) @@ -61,7 +64,7 @@ const babelStack = ` packages/react/src/forwardRef.js: Unexpected token, expected , (20:10) \u001b[0m \u001b[90m 18 | \u001b[39m \u001b[36mfalse\u001b[39m\u001b[33m,\u001b[39m - \u001b[90m 19 | \u001b[39m \u001b[32m'forwardRef requires a render function but received a \`memo\` '\u001b[39m + \u001b[90m 19 | \u001b[39m \u001b[32m'forwardRef requires a render function but received a \`memo\` '\u001b[39m \u001b[31m\u001b[1m>\u001b[22m\u001b[39m\u001b[90m 20 | \u001b[39m \u001b[32m'component. Instead of forwardRef(memo(...)), use '\u001b[39m \u001b[33m+\u001b[39m \u001b[90m | \u001b[39m \u001b[31m\u001b[1m^\u001b[22m\u001b[39m \u001b[90m 21 | \u001b[39m \u001b[32m'memo(forwardRef(...)).'\u001b[39m\u001b[33m,\u001b[39m @@ -69,6 +72,10 @@ const babelStack = \u001b[90m 23 | \u001b[39m } \u001b[36melse\u001b[39m \u001b[36mif\u001b[39m (\u001b[36mtypeof\u001b[39m render \u001b[33m!==\u001b[39m \u001b[32m'function'\u001b[39m) {\u001b[0m `; +beforeEach(() => { + jest.clearAllMocks(); +}); + it('should exclude jasmine from stack trace for Unix paths.', () => { const messages = formatResultsErrors( [ @@ -187,3 +194,94 @@ it('retains message in babel code frame error', () => { expect(messages).toMatchSnapshot(); }); + +it('codeframe', () => { + readFileSync.mockImplementationOnce(() => 'throw new Error("Whoops!");'); + + const message = formatExecError( + { + message: 'Whoops!', + stack: ` + at Object. (/Users/Jester/jest/file.js:1:7) + at Module._compile (internal/modules/cjs/loader.js:1158:30) + at Object.Module._extensions..js (internal/modules/cjs/loader.js:1178:10) + at Module.load (internal/modules/cjs/loader.js:1002:32) + at Function.Module._load (internal/modules/cjs/loader.js:901:14) + at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:74:12) + at internal/main/run_main_module.js:18:47 +`, + }, + { + rootDir: '', + testMatch: [], + }, + { + noCodeFrame: false, + noStackTrace: false, + }, + 'path_test', + ); + + expect(message).toMatchSnapshot(); +}); + +it('no codeframe', () => { + readFileSync.mockImplementationOnce(() => 'throw new Error("Whoops!");'); + + const message = formatExecError( + { + message: 'Whoops!', + stack: ` + at Object. (/Users/Jester/jest/file.js:1:7) + at Module._compile (internal/modules/cjs/loader.js:1158:30) + at Object.Module._extensions..js (internal/modules/cjs/loader.js:1178:10) + at Module.load (internal/modules/cjs/loader.js:1002:32) + at Function.Module._load (internal/modules/cjs/loader.js:901:14) + at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:74:12) + at internal/main/run_main_module.js:18:47 +`, + }, + { + rootDir: '', + testMatch: [], + }, + { + noCodeFrame: true, + noStackTrace: false, + }, + 'path_test', + ); + + expect(message).toMatchSnapshot(); +}); + +it('no stack', () => { + readFileSync.mockImplementationOnce(() => 'throw new Error("Whoops!");'); + + const message = formatExecError( + { + message: 'Whoops!', + stack: ` + at Object. (/Users/Jester/jest/file.js:1:7) + at Module._compile (internal/modules/cjs/loader.js:1158:30) + at Object.Module._extensions..js (internal/modules/cjs/loader.js:1178:10) + at Module.load (internal/modules/cjs/loader.js:1002:32) + at Function.Module._load (internal/modules/cjs/loader.js:901:14) + at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:74:12) + at internal/main/run_main_module.js:18:47 +`, + }, + { + rootDir: '', + testMatch: [], + }, + { + // if no stack, no codeframe is implied + noCodeFrame: true, + noStackTrace: true, + }, + 'path_test', + ); + + expect(message).toMatchSnapshot(); +}); From fae01332d23117f4e9dfcf5e2b07949166ca6685 Mon Sep 17 00:00:00 2001 From: Simen Bekkhus Date: Sun, 12 Apr 2020 18:19:01 +0200 Subject: [PATCH 27/29] maybe consistent snap? --- .../src/__tests__/__snapshots__/messages.test.ts.snap | 8 ++++---- .../jest-message-util/src/__tests__/messages.test.ts | 9 ++++++--- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/packages/jest-message-util/src/__tests__/__snapshots__/messages.test.ts.snap b/packages/jest-message-util/src/__tests__/__snapshots__/messages.test.ts.snap index 9dd7f87d3829..f446fe5baad7 100644 --- a/packages/jest-message-util/src/__tests__/__snapshots__/messages.test.ts.snap +++ b/packages/jest-message-util/src/__tests__/__snapshots__/messages.test.ts.snap @@ -15,8 +15,8 @@ exports[`codeframe 1`] = ` > 1 | throw new Error(\\"Whoops!\\"); | ^ - at Object. (../../../Jester/jest/file.js:1:7) - at internal/main/run_main_module.js:18:47 + at Object. (../../../../../Jester/jest/file.js:1:7) + at ../../internal/main/run_main_module.js:18:47 " `; @@ -41,8 +41,8 @@ exports[`no codeframe 1`] = ` Whoops! - at Object. (../../../Jester/jest/file.js:1:7) - at internal/main/run_main_module.js:18:47 + at Object. (../../../../../Jester/jest/file.js:1:7) + at ../../internal/main/run_main_module.js:18:47 " `; diff --git a/packages/jest-message-util/src/__tests__/messages.test.ts b/packages/jest-message-util/src/__tests__/messages.test.ts index 6f82f0e2c175..f6264b857b57 100644 --- a/packages/jest-message-util/src/__tests__/messages.test.ts +++ b/packages/jest-message-util/src/__tests__/messages.test.ts @@ -7,8 +7,11 @@ */ import {readFileSync} from 'fs'; +import {resolve} from 'path'; import {formatExecError, formatResultsErrors} from '..'; +const rootDir = resolve(__dirname, '../../') + jest.mock('fs'); const unixStackTrace = @@ -212,7 +215,7 @@ it('codeframe', () => { `, }, { - rootDir: '', + rootDir, testMatch: [], }, { @@ -242,7 +245,7 @@ it('no codeframe', () => { `, }, { - rootDir: '', + rootDir, testMatch: [], }, { @@ -272,7 +275,7 @@ it('no stack', () => { `, }, { - rootDir: '', + rootDir, testMatch: [], }, { From c4386d5bb419788231cc0458e8b7136e3c8d005f Mon Sep 17 00:00:00 2001 From: Simen Bekkhus Date: Sun, 12 Apr 2020 18:30:31 +0200 Subject: [PATCH 28/29] eslint is hard --- packages/jest-message-util/src/__tests__/messages.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/jest-message-util/src/__tests__/messages.test.ts b/packages/jest-message-util/src/__tests__/messages.test.ts index f6264b857b57..d428c9063c09 100644 --- a/packages/jest-message-util/src/__tests__/messages.test.ts +++ b/packages/jest-message-util/src/__tests__/messages.test.ts @@ -10,7 +10,7 @@ import {readFileSync} from 'fs'; import {resolve} from 'path'; import {formatExecError, formatResultsErrors} from '..'; -const rootDir = resolve(__dirname, '../../') +const rootDir = resolve(__dirname, '../../'); jest.mock('fs'); From 5d3a8e97d850e651fd8c6e5e096d9ba398d50206 Mon Sep 17 00:00:00 2001 From: Simen Bekkhus Date: Sun, 12 Apr 2020 18:37:46 +0200 Subject: [PATCH 29/29] is this consistent? --- .../__snapshots__/messages.test.ts.snap | 6 ++---- .../src/__tests__/messages.test.ts | 19 ++++++++++--------- 2 files changed, 12 insertions(+), 13 deletions(-) diff --git a/packages/jest-message-util/src/__tests__/__snapshots__/messages.test.ts.snap b/packages/jest-message-util/src/__tests__/__snapshots__/messages.test.ts.snap index f446fe5baad7..490db062e6fb 100644 --- a/packages/jest-message-util/src/__tests__/__snapshots__/messages.test.ts.snap +++ b/packages/jest-message-util/src/__tests__/__snapshots__/messages.test.ts.snap @@ -15,8 +15,7 @@ exports[`codeframe 1`] = ` > 1 | throw new Error(\\"Whoops!\\"); | ^ - at Object. (../../../../../Jester/jest/file.js:1:7) - at ../../internal/main/run_main_module.js:18:47 + at Object. (file.js:1:7) " `; @@ -41,8 +40,7 @@ exports[`no codeframe 1`] = ` Whoops! - at Object. (../../../../../Jester/jest/file.js:1:7) - at ../../internal/main/run_main_module.js:18:47 + at Object. (file.js:1:7) " `; diff --git a/packages/jest-message-util/src/__tests__/messages.test.ts b/packages/jest-message-util/src/__tests__/messages.test.ts index d428c9063c09..41a14d0100da 100644 --- a/packages/jest-message-util/src/__tests__/messages.test.ts +++ b/packages/jest-message-util/src/__tests__/messages.test.ts @@ -7,12 +7,16 @@ */ import {readFileSync} from 'fs'; -import {resolve} from 'path'; +import slash = require('slash'); +import tempy = require('tempy'); import {formatExecError, formatResultsErrors} from '..'; -const rootDir = resolve(__dirname, '../../'); +const rootDir = tempy.directory(); -jest.mock('fs'); +jest.mock('fs', () => ({ + ...jest.requireActual('fs'), + readFileSync: jest.fn(), +})); const unixStackTrace = ` ` + @@ -205,13 +209,12 @@ it('codeframe', () => { { message: 'Whoops!', stack: ` - at Object. (/Users/Jester/jest/file.js:1:7) + at Object. (${slash(rootDir)}/file.js:1:7) at Module._compile (internal/modules/cjs/loader.js:1158:30) at Object.Module._extensions..js (internal/modules/cjs/loader.js:1178:10) at Module.load (internal/modules/cjs/loader.js:1002:32) at Function.Module._load (internal/modules/cjs/loader.js:901:14) at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:74:12) - at internal/main/run_main_module.js:18:47 `, }, { @@ -235,13 +238,12 @@ it('no codeframe', () => { { message: 'Whoops!', stack: ` - at Object. (/Users/Jester/jest/file.js:1:7) + at Object. (${slash(rootDir)}/file.js:1:7) at Module._compile (internal/modules/cjs/loader.js:1158:30) at Object.Module._extensions..js (internal/modules/cjs/loader.js:1178:10) at Module.load (internal/modules/cjs/loader.js:1002:32) at Function.Module._load (internal/modules/cjs/loader.js:901:14) at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:74:12) - at internal/main/run_main_module.js:18:47 `, }, { @@ -265,13 +267,12 @@ it('no stack', () => { { message: 'Whoops!', stack: ` - at Object. (/Users/Jester/jest/file.js:1:7) + at Object. (${slash(rootDir)}/file.js:1:7) at Module._compile (internal/modules/cjs/loader.js:1158:30) at Object.Module._extensions..js (internal/modules/cjs/loader.js:1178:10) at Module.load (internal/modules/cjs/loader.js:1002:32) at Function.Module._load (internal/modules/cjs/loader.js:901:14) at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:74:12) - at internal/main/run_main_module.js:18:47 `, }, {