diff options
Diffstat (limited to 'node_modules/jest-message-util/build')
-rw-r--r-- | node_modules/jest-message-util/build/index.d.ts | 23 | ||||
-rw-r--r-- | node_modules/jest-message-util/build/index.js | 501 | ||||
-rw-r--r-- | node_modules/jest-message-util/build/types.d.ts | 10 | ||||
-rw-r--r-- | node_modules/jest-message-util/build/types.js | 1 |
4 files changed, 535 insertions, 0 deletions
diff --git a/node_modules/jest-message-util/build/index.d.ts b/node_modules/jest-message-util/build/index.d.ts new file mode 100644 index 0000000..7be2d84 --- /dev/null +++ b/node_modules/jest-message-util/build/index.d.ts @@ -0,0 +1,23 @@ +/** + * 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. + */ +import type { Config, TestResult } from '@jest/types'; +import type { Frame } from './types'; +export type { Frame } from './types'; +export declare type StackTraceConfig = Pick<Config.ProjectConfig, 'rootDir' | 'testMatch'>; +export declare type StackTraceOptions = { + noStackTrace: boolean; + noCodeFrame?: boolean; +}; +export declare const formatExecError: (error: Error | TestResult.SerializableError | string | undefined, config: StackTraceConfig, options: StackTraceOptions, testPath?: string | undefined, reuseMessage?: boolean | undefined) => string; +export declare const getStackTraceLines: (stack: string, options?: StackTraceOptions) => Array<string>; +export declare const getTopFrame: (lines: Array<string>) => Frame | null; +export declare const formatStackTrace: (stack: string, config: StackTraceConfig, options: StackTraceOptions, testPath?: string | undefined) => string; +export declare const formatResultsErrors: (testResults: Array<TestResult.AssertionResult>, config: StackTraceConfig, options: StackTraceOptions, testPath?: string | undefined) => string | null; +export declare const separateMessageFromStack: (content: string) => { + message: string; + stack: string; +}; diff --git a/node_modules/jest-message-util/build/index.js b/node_modules/jest-message-util/build/index.js new file mode 100644 index 0000000..4326f27 --- /dev/null +++ b/node_modules/jest-message-util/build/index.js @@ -0,0 +1,501 @@ +'use strict'; + +Object.defineProperty(exports, '__esModule', { + value: true +}); +exports.separateMessageFromStack = + exports.getTopFrame = + exports.getStackTraceLines = + exports.formatStackTrace = + exports.formatResultsErrors = + exports.formatExecError = + void 0; + +var path = _interopRequireWildcard(require('path')); + +var _url = require('url'); + +var _codeFrame = require('@babel/code-frame'); + +var _chalk = _interopRequireDefault(require('chalk')); + +var fs = _interopRequireWildcard(require('graceful-fs')); + +var _micromatch = _interopRequireDefault(require('micromatch')); + +var _slash = _interopRequireDefault(require('slash')); + +var _stackUtils = _interopRequireDefault(require('stack-utils')); + +var _prettyFormat = require('pretty-format'); + +function _interopRequireDefault(obj) { + return obj && obj.__esModule ? obj : {default: obj}; +} + +function _getRequireWildcardCache(nodeInterop) { + if (typeof WeakMap !== 'function') return null; + var cacheBabelInterop = new WeakMap(); + var cacheNodeInterop = new WeakMap(); + return (_getRequireWildcardCache = function (nodeInterop) { + return nodeInterop ? cacheNodeInterop : cacheBabelInterop; + })(nodeInterop); +} + +function _interopRequireWildcard(obj, nodeInterop) { + if (!nodeInterop && obj && obj.__esModule) { + return obj; + } + if (obj === null || (typeof obj !== 'object' && typeof obj !== 'function')) { + return {default: obj}; + } + var cache = _getRequireWildcardCache(nodeInterop); + if (cache && cache.has(obj)) { + return cache.get(obj); + } + var newObj = {}; + var hasPropertyDescriptor = + Object.defineProperty && Object.getOwnPropertyDescriptor; + for (var key in obj) { + if (key !== 'default' && Object.prototype.hasOwnProperty.call(obj, key)) { + var desc = hasPropertyDescriptor + ? Object.getOwnPropertyDescriptor(obj, key) + : null; + if (desc && (desc.get || desc.set)) { + Object.defineProperty(newObj, key, desc); + } else { + newObj[key] = obj[key]; + } + } + } + newObj.default = obj; + if (cache) { + cache.set(obj, newObj); + } + return newObj; +} + +var global = (function () { + if (typeof globalThis !== 'undefined') { + return globalThis; + } else if (typeof global !== 'undefined') { + return global; + } else if (typeof self !== 'undefined') { + return self; + } else if (typeof window !== 'undefined') { + return window; + } else { + return Function('return this')(); + } +})(); + +var Symbol = global['jest-symbol-do-not-touch'] || global.Symbol; + +var global = (function () { + if (typeof globalThis !== 'undefined') { + return globalThis; + } else if (typeof global !== 'undefined') { + return global; + } else if (typeof self !== 'undefined') { + return self; + } else if (typeof window !== 'undefined') { + return window; + } else { + return Function('return this')(); + } +})(); + +var Symbol = global['jest-symbol-do-not-touch'] || global.Symbol; + +var global = (function () { + if (typeof globalThis !== 'undefined') { + return globalThis; + } else if (typeof global !== 'undefined') { + return global; + } else if (typeof self !== 'undefined') { + return self; + } else if (typeof window !== 'undefined') { + return window; + } else { + return Function('return this')(); + } +})(); + +var jestReadFile = + global[Symbol.for('jest-native-read-file')] || fs.readFileSync; +// stack utils tries to create pretty stack by making paths relative. +const stackUtils = new _stackUtils.default({ + cwd: 'something which does not exist' +}); +let nodeInternals = []; + +try { + nodeInternals = _stackUtils.default.nodeInternals(); +} catch { + // `StackUtils.nodeInternals()` fails in browsers. We don't need to remove + // node internals in the browser though, so no issue. +} + +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 <anonymous>.*$/; +const ANONYMOUS_PROMISE_IGNORE = /^\s+at (new )?Promise \(<anonymous>\).*$/; +const ANONYMOUS_GENERATOR_IGNORE = /^\s+at Generator.next \(<anonymous>\).*$/; +const NATIVE_NEXT_IGNORE = /^\s+at next \(native\).*$/; +const TITLE_INDENT = ' '; +const MESSAGE_INDENT = ' '; +const STACK_INDENT = ' '; +const ANCESTRY_SEPARATOR = ' \u203A '; + +const TITLE_BULLET = _chalk.default.bold('\u25cf '); + +const STACK_TRACE_COLOR = _chalk.default.dim; +const STACK_PATH_REGEXP = /\s*at.*\(?(\:\d*\:\d*|native)\)?/; +const EXEC_ERROR_MESSAGE = 'Test suite failed to run'; +const NOT_EMPTY_LINE_REGEXP = /^(?!$)/gm; + +const indentAllLines = (lines, indent) => + lines.replace(NOT_EMPTY_LINE_REGEXP, indent); + +const trim = 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.match(STACK_PATH_REGEXP) ? trim(string) : string; + +const getRenderedCallsite = (fileContent, line, column) => { + let renderedCallsite = (0, _codeFrame.codeFrameColumns)( + fileContent, + { + start: { + column, + line + } + }, + { + highlightCode: true + } + ); + renderedCallsite = indentAllLines(renderedCallsite, MESSAGE_INDENT); + renderedCallsite = `\n${renderedCallsite}\n`; + return renderedCallsite; +}; + +const blankStringRegexp = /^\s*$/; + +function checkForCommonEnvironmentErrors(error) { + if ( + error.includes('ReferenceError: document is not defined') || + error.includes('ReferenceError: window is not defined') || + error.includes('ReferenceError: navigator is not defined') + ) { + return warnAboutWrongTestEnvironment(error, 'jsdom'); + } else if (error.includes('.unref is not a function')) { + return warnAboutWrongTestEnvironment(error, 'node'); + } + + return error; +} + +function warnAboutWrongTestEnvironment(error, env) { + return ( + _chalk.default.bold.red( + `The error below may be caused by using the wrong test environment, see ${_chalk.default.dim.underline( + 'https://jestjs.io/docs/configuration#testenvironment-string' + )}.\nConsider using the "${env}" test environment.\n\n` + ) + error + ); +} // ExecError is an error thrown outside of the test suite (not inside an `it` or +// `before/after each` hooks). If it's thrown, none of the tests in the file +// are executed. + +const formatExecError = (error, config, options, testPath, reuseMessage) => { + if (!error || typeof error === 'number') { + error = new Error(`Expected an Error, but "${String(error)}" was thrown`); + error.stack = ''; + } + + let message, stack; + + if (typeof error === 'string' || !error) { + error || (error = 'EMPTY ERROR'); + message = ''; + stack = error; + } else { + message = error.message; + stack = + typeof error.stack === 'string' + ? error.stack + : `thrown: ${(0, _prettyFormat.format)(error, { + maxDepth: 3 + })}`; + } + + const separated = separateMessageFromStack(stack || ''); + stack = separated.stack; + + if (separated.message.includes(trim(message))) { + // Often stack trace already contains the duplicate of the message + message = separated.message; + } + + message = checkForCommonEnvironmentErrors(message); + message = indentAllLines(message, MESSAGE_INDENT); + stack = + stack && !options.noStackTrace + ? '\n' + formatStackTrace(stack, config, options, testPath) + : ''; + + if ( + typeof stack !== 'string' || + (blankStringRegexp.test(message) && blankStringRegexp.test(stack)) + ) { + // this can happen if an empty object is thrown. + message = `thrown: ${(0, _prettyFormat.format)(error, { + maxDepth: 3 + })}`; + } + + let messageToUse; + + if (reuseMessage) { + messageToUse = ` ${message.trim()}`; + } else { + messageToUse = `${EXEC_ERROR_MESSAGE}\n\n${message}`; + } + + return TITLE_INDENT + TITLE_BULLET + messageToUse + stack + '\n'; +}; + +exports.formatExecError = formatExecError; + +const removeInternalStackEntries = (lines, options) => { + 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, relativeTestPath, line) => { + // Extract the file path from the trace line. + const match = line.match(/(^\s*at .*?\(?)([^()]+)(:[0-9]+:[0-9]+\)?.*$)/); + + if (!match) { + return line; + } + + let filePath = (0, _slash.default)(path.relative(config.rootDir, match[2])); // highlight paths from the current test file + + if ( + (config.testMatch && + config.testMatch.length && + (0, _micromatch.default)([filePath], config.testMatch).length > 0) || + filePath === relativeTestPath + ) { + filePath = _chalk.default.reset.cyan(filePath); + } + + return STACK_TRACE_COLOR(match[1]) + filePath + STACK_TRACE_COLOR(match[3]); +}; + +const getStackTraceLines = ( + stack, + options = { + noCodeFrame: false, + noStackTrace: false + } +) => removeInternalStackEntries(stack.split(/\n/), options); + +exports.getStackTraceLines = getStackTraceLines; + +const getTopFrame = lines => { + 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) { + if (parsedFrame.file.startsWith('file://')) { + parsedFrame.file = (0, _slash.default)( + (0, _url.fileURLToPath)(parsedFrame.file) + ); + } + + return parsedFrame; + } + } + + return null; +}; + +exports.getTopFrame = getTopFrame; + +const formatStackTrace = (stack, config, options, testPath) => { + const lines = getStackTraceLines(stack, options); + let renderedCallsite = ''; + const relativeTestPath = testPath + ? (0, _slash.default)(path.relative(config.rootDir, testPath)) + : null; + + if (!options.noStackTrace && !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 = jestReadFile(filename, 'utf8'); + renderedCallsite = getRenderedCallsite(fileContent, line, column); + } catch { + // 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 + ? `${renderedCallsite}\n${stacktrace}` + : `\n${stacktrace}`; +}; + +exports.formatStackTrace = formatStackTrace; + +const formatResultsErrors = (testResults, config, options, testPath) => { + const failedResults = testResults.reduce((errors, result) => { + result.failureMessages.forEach(item => { + errors.push({ + content: checkForCommonEnvironmentErrors(item), + result + }); + }); + return errors; + }, []); + + if (!failedResults.length) { + return null; + } + + return failedResults + .map(({result, content}) => { + let {message, stack} = separateMessageFromStack(content); + stack = options.noStackTrace + ? '' + : STACK_TRACE_COLOR( + formatStackTrace(stack, config, options, testPath) + ) + '\n'; + message = indentAllLines(message, MESSAGE_INDENT); + const title = + _chalk.default.bold.red( + TITLE_INDENT + + TITLE_BULLET + + result.ancestorTitles.join(ANCESTRY_SEPARATOR) + + (result.ancestorTitles.length ? ANCESTRY_SEPARATOR : '') + + result.title + ) + '\n'; + return title + '\n' + message + '\n' + stack; + }) + .join('\n'); +}; + +exports.formatResultsErrors = formatResultsErrors; +const errorRegexp = /^Error:?\s*$/; + +const removeBlankErrorLine = str => + 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. + +const separateMessageFromStack = content => { + 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 + }; +}; + +exports.separateMessageFromStack = separateMessageFromStack; diff --git a/node_modules/jest-message-util/build/types.d.ts b/node_modules/jest-message-util/build/types.d.ts new file mode 100644 index 0000000..9a95b77 --- /dev/null +++ b/node_modules/jest-message-util/build/types.d.ts @@ -0,0 +1,10 @@ +/** + * 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. + */ +import type { StackData } from 'stack-utils'; +export interface Frame extends StackData { + file: string; +} diff --git a/node_modules/jest-message-util/build/types.js b/node_modules/jest-message-util/build/types.js new file mode 100644 index 0000000..ad9a93a --- /dev/null +++ b/node_modules/jest-message-util/build/types.js @@ -0,0 +1 @@ +'use strict'; |