1103 lines
		
	
	
		
			30 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			1103 lines
		
	
	
		
			30 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| 'use strict';
 | |
| 
 | |
| Object.defineProperty(exports, '__esModule', {
 | |
|   value: true
 | |
| });
 | |
| exports.default = normalize;
 | |
| 
 | |
| function _crypto() {
 | |
|   const data = _interopRequireDefault(require('crypto'));
 | |
| 
 | |
|   _crypto = function _crypto() {
 | |
|     return data;
 | |
|   };
 | |
| 
 | |
|   return data;
 | |
| }
 | |
| 
 | |
| function _path() {
 | |
|   const data = _interopRequireDefault(require('path'));
 | |
| 
 | |
|   _path = function _path() {
 | |
|     return data;
 | |
|   };
 | |
| 
 | |
|   return data;
 | |
| }
 | |
| 
 | |
| function _glob() {
 | |
|   const data = _interopRequireDefault(require('glob'));
 | |
| 
 | |
|   _glob = function _glob() {
 | |
|     return data;
 | |
|   };
 | |
| 
 | |
|   return data;
 | |
| }
 | |
| 
 | |
| function _jestValidate() {
 | |
|   const data = require('jest-validate');
 | |
| 
 | |
|   _jestValidate = function _jestValidate() {
 | |
|     return data;
 | |
|   };
 | |
| 
 | |
|   return data;
 | |
| }
 | |
| 
 | |
| function _jestUtil() {
 | |
|   const data = require('jest-util');
 | |
| 
 | |
|   _jestUtil = function _jestUtil() {
 | |
|     return data;
 | |
|   };
 | |
| 
 | |
|   return data;
 | |
| }
 | |
| 
 | |
| function _chalk() {
 | |
|   const data = _interopRequireDefault(require('chalk'));
 | |
| 
 | |
|   _chalk = function _chalk() {
 | |
|     return data;
 | |
|   };
 | |
| 
 | |
|   return data;
 | |
| }
 | |
| 
 | |
| function _micromatch() {
 | |
|   const data = _interopRequireDefault(require('micromatch'));
 | |
| 
 | |
|   _micromatch = function _micromatch() {
 | |
|     return data;
 | |
|   };
 | |
| 
 | |
|   return data;
 | |
| }
 | |
| 
 | |
| function _realpathNative() {
 | |
|   const data = require('realpath-native');
 | |
| 
 | |
|   _realpathNative = function _realpathNative() {
 | |
|     return data;
 | |
|   };
 | |
| 
 | |
|   return data;
 | |
| }
 | |
| 
 | |
| function _jestResolve() {
 | |
|   const data = _interopRequireDefault(require('jest-resolve'));
 | |
| 
 | |
|   _jestResolve = function _jestResolve() {
 | |
|     return data;
 | |
|   };
 | |
| 
 | |
|   return data;
 | |
| }
 | |
| 
 | |
| function _jestRegexUtil() {
 | |
|   const data = require('jest-regex-util');
 | |
| 
 | |
|   _jestRegexUtil = function _jestRegexUtil() {
 | |
|     return data;
 | |
|   };
 | |
| 
 | |
|   return data;
 | |
| }
 | |
| 
 | |
| function _jestGetType() {
 | |
|   const data = _interopRequireDefault(require('jest-get-type'));
 | |
| 
 | |
|   _jestGetType = function _jestGetType() {
 | |
|     return data;
 | |
|   };
 | |
| 
 | |
|   return data;
 | |
| }
 | |
| 
 | |
| var _validatePattern = _interopRequireDefault(require('./validatePattern'));
 | |
| 
 | |
| var _getMaxWorkers = _interopRequireDefault(require('./getMaxWorkers'));
 | |
| 
 | |
| var _utils = require('./utils');
 | |
| 
 | |
| var _constants = require('./constants');
 | |
| 
 | |
| var _ReporterValidationErrors = require('./ReporterValidationErrors');
 | |
| 
 | |
| var _Defaults = _interopRequireDefault(require('./Defaults'));
 | |
| 
 | |
| var _Deprecated = _interopRequireDefault(require('./Deprecated'));
 | |
| 
 | |
| var _setFromArgv = _interopRequireDefault(require('./setFromArgv'));
 | |
| 
 | |
| var _ValidConfig = _interopRequireDefault(require('./ValidConfig'));
 | |
| 
 | |
| function _interopRequireDefault(obj) {
 | |
|   return obj && obj.__esModule ? obj : {default: obj};
 | |
| }
 | |
| 
 | |
| function _objectSpread(target) {
 | |
|   for (var i = 1; i < arguments.length; i++) {
 | |
|     var source = arguments[i] != null ? arguments[i] : {};
 | |
|     var ownKeys = Object.keys(source);
 | |
|     if (typeof Object.getOwnPropertySymbols === 'function') {
 | |
|       ownKeys = ownKeys.concat(
 | |
|         Object.getOwnPropertySymbols(source).filter(function(sym) {
 | |
|           return Object.getOwnPropertyDescriptor(source, sym).enumerable;
 | |
|         })
 | |
|       );
 | |
|     }
 | |
|     ownKeys.forEach(function(key) {
 | |
|       _defineProperty(target, key, source[key]);
 | |
|     });
 | |
|   }
 | |
|   return target;
 | |
| }
 | |
| 
 | |
| function _defineProperty(obj, key, value) {
 | |
|   if (key in obj) {
 | |
|     Object.defineProperty(obj, key, {
 | |
|       value: value,
 | |
|       enumerable: true,
 | |
|       configurable: true,
 | |
|       writable: true
 | |
|     });
 | |
|   } else {
 | |
|     obj[key] = value;
 | |
|   }
 | |
|   return obj;
 | |
| }
 | |
| 
 | |
| const ERROR = `${_utils.BULLET}Validation Error`;
 | |
| const PRESET_EXTENSIONS = ['.json', '.js'];
 | |
| const PRESET_NAME = 'jest-preset';
 | |
| 
 | |
| const createConfigError = message =>
 | |
|   new (_jestValidate()).ValidationError(
 | |
|     ERROR,
 | |
|     message,
 | |
|     _utils.DOCUMENTATION_NOTE
 | |
|   );
 | |
| 
 | |
| const mergeOptionWithPreset = (options, preset, optionName) => {
 | |
|   if (options[optionName] && preset[optionName]) {
 | |
|     options[optionName] = _objectSpread(
 | |
|       {},
 | |
|       options[optionName],
 | |
|       preset[optionName],
 | |
|       options[optionName]
 | |
|     );
 | |
|   }
 | |
| };
 | |
| 
 | |
| const setupPreset = (options, optionsPreset) => {
 | |
|   let preset;
 | |
|   const presetPath = (0, _utils.replaceRootDirInPath)(
 | |
|     options.rootDir,
 | |
|     optionsPreset
 | |
|   );
 | |
| 
 | |
|   const presetModule = _jestResolve().default.findNodeModule(
 | |
|     presetPath.startsWith('.')
 | |
|       ? presetPath
 | |
|       : _path().default.join(presetPath, PRESET_NAME),
 | |
|     {
 | |
|       basedir: options.rootDir,
 | |
|       extensions: PRESET_EXTENSIONS
 | |
|     }
 | |
|   );
 | |
| 
 | |
|   try {
 | |
|     // Force re-evaluation to support multiple projects
 | |
|     try {
 | |
|       if (presetModule) {
 | |
|         delete require.cache[require.resolve(presetModule)];
 | |
|       }
 | |
|     } catch (e) {} // @ts-ignore: `presetModule` can be null?
 | |
| 
 | |
|     preset = require(presetModule);
 | |
|   } catch (error) {
 | |
|     if (error instanceof SyntaxError || error instanceof TypeError) {
 | |
|       throw createConfigError(
 | |
|         `  Preset ${_chalk().default.bold(presetPath)} is invalid:\n\n  ${
 | |
|           error.message
 | |
|         }\n  ${error.stack}`
 | |
|       );
 | |
|     }
 | |
| 
 | |
|     const preset = _jestResolve().default.findNodeModule(presetPath, {
 | |
|       basedir: options.rootDir
 | |
|     });
 | |
| 
 | |
|     if (preset) {
 | |
|       throw createConfigError(
 | |
|         `  Module ${_chalk().default.bold(
 | |
|           presetPath
 | |
|         )} should have "jest-preset.js" or "jest-preset.json" file at the root.`
 | |
|       );
 | |
|     }
 | |
| 
 | |
|     throw createConfigError(
 | |
|       `  Preset ${_chalk().default.bold(presetPath)} not found.`
 | |
|     );
 | |
|   }
 | |
| 
 | |
|   if (options.setupFiles) {
 | |
|     options.setupFiles = (preset.setupFiles || []).concat(options.setupFiles);
 | |
|   }
 | |
| 
 | |
|   if (options.modulePathIgnorePatterns && preset.modulePathIgnorePatterns) {
 | |
|     options.modulePathIgnorePatterns = preset.modulePathIgnorePatterns.concat(
 | |
|       options.modulePathIgnorePatterns
 | |
|     );
 | |
|   }
 | |
| 
 | |
|   mergeOptionWithPreset(options, preset, 'moduleNameMapper');
 | |
|   mergeOptionWithPreset(options, preset, 'transform');
 | |
|   return _objectSpread({}, preset, options);
 | |
| };
 | |
| 
 | |
| const setupBabelJest = options => {
 | |
|   const transform = options.transform;
 | |
|   let babelJest;
 | |
| 
 | |
|   if (transform) {
 | |
|     const customJSPattern = Object.keys(transform).find(pattern => {
 | |
|       const regex = new RegExp(pattern);
 | |
|       return regex.test('a.js') || regex.test('a.jsx');
 | |
|     });
 | |
|     const customTSPattern = Object.keys(transform).find(pattern => {
 | |
|       const regex = new RegExp(pattern);
 | |
|       return regex.test('a.ts') || regex.test('a.tsx');
 | |
|     });
 | |
| 
 | |
|     if (customJSPattern) {
 | |
|       const customJSTransformer = transform[customJSPattern];
 | |
| 
 | |
|       if (customJSTransformer === 'babel-jest') {
 | |
|         babelJest = require.resolve('babel-jest');
 | |
|         transform[customJSPattern] = babelJest;
 | |
|       } else if (customJSTransformer.includes('babel-jest')) {
 | |
|         babelJest = customJSTransformer;
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     if (customTSPattern) {
 | |
|       const customTSTransformer = transform[customTSPattern];
 | |
| 
 | |
|       if (customTSTransformer === 'babel-jest') {
 | |
|         babelJest = require.resolve('babel-jest');
 | |
|         transform[customTSPattern] = babelJest;
 | |
|       } else if (customTSTransformer.includes('babel-jest')) {
 | |
|         babelJest = customTSTransformer;
 | |
|       }
 | |
|     }
 | |
|   } else {
 | |
|     babelJest = require.resolve('babel-jest');
 | |
|     options.transform = {
 | |
|       [_constants.DEFAULT_JS_PATTERN]: babelJest
 | |
|     };
 | |
|   }
 | |
| };
 | |
| 
 | |
| const normalizeCollectCoverageOnlyFrom = (options, key) => {
 | |
|   const initialCollectCoverageFrom = options[key];
 | |
|   const collectCoverageOnlyFrom = Array.isArray(initialCollectCoverageFrom)
 | |
|     ? initialCollectCoverageFrom // passed from argv
 | |
|     : Object.keys(initialCollectCoverageFrom); // passed from options
 | |
| 
 | |
|   return collectCoverageOnlyFrom.reduce((map, filePath) => {
 | |
|     filePath = _path().default.resolve(
 | |
|       options.rootDir,
 | |
|       (0, _utils.replaceRootDirInPath)(options.rootDir, filePath)
 | |
|     );
 | |
|     map[filePath] = true;
 | |
|     return map;
 | |
|   }, Object.create(null));
 | |
| };
 | |
| 
 | |
| const normalizeCollectCoverageFrom = (options, key) => {
 | |
|   const initialCollectCoverageFrom = options[key];
 | |
|   let value;
 | |
| 
 | |
|   if (!initialCollectCoverageFrom) {
 | |
|     value = [];
 | |
|   }
 | |
| 
 | |
|   if (!Array.isArray(initialCollectCoverageFrom)) {
 | |
|     try {
 | |
|       value = JSON.parse(initialCollectCoverageFrom);
 | |
|     } catch (e) {}
 | |
| 
 | |
|     if (options[key] && !Array.isArray(value)) {
 | |
|       value = [initialCollectCoverageFrom];
 | |
|     }
 | |
|   } else {
 | |
|     value = initialCollectCoverageFrom;
 | |
|   }
 | |
| 
 | |
|   if (value) {
 | |
|     value = value.map(filePath =>
 | |
|       filePath.replace(/^(!?)(<rootDir>\/)(.*)/, '$1$3')
 | |
|     );
 | |
|   }
 | |
| 
 | |
|   return value;
 | |
| };
 | |
| 
 | |
| const normalizeUnmockedModulePathPatterns = (
 | |
|   options,
 | |
|   key // _replaceRootDirTags is specifically well-suited for substituting
 | |
|   // <rootDir> in paths (it deals with properly interpreting relative path
 | |
|   // separators, etc).
 | |
|   //
 | |
|   // For patterns, direct global substitution is far more ideal, so we
 | |
|   // special case substitutions for patterns here.
 | |
| ) =>
 | |
|   options[key].map(pattern =>
 | |
|     (0, _jestRegexUtil().replacePathSepForRegex)(
 | |
|       pattern.replace(/<rootDir>/g, options.rootDir)
 | |
|     )
 | |
|   );
 | |
| 
 | |
| const normalizePreprocessor = options => {
 | |
|   if (options.scriptPreprocessor && options.transform) {
 | |
|     throw createConfigError(`  Options: ${_chalk().default.bold(
 | |
|       'scriptPreprocessor'
 | |
|     )} and ${_chalk().default.bold('transform')} cannot be used together.
 | |
|   Please change your configuration to only use ${_chalk().default.bold(
 | |
|     'transform'
 | |
|   )}.`);
 | |
|   }
 | |
| 
 | |
|   if (options.preprocessorIgnorePatterns && options.transformIgnorePatterns) {
 | |
|     throw createConfigError(`  Options ${_chalk().default.bold(
 | |
|       'preprocessorIgnorePatterns'
 | |
|     )} and ${_chalk().default.bold(
 | |
|       'transformIgnorePatterns'
 | |
|     )} cannot be used together.
 | |
|   Please change your configuration to only use ${_chalk().default.bold(
 | |
|     'transformIgnorePatterns'
 | |
|   )}.`);
 | |
|   }
 | |
| 
 | |
|   if (options.scriptPreprocessor) {
 | |
|     options.transform = {
 | |
|       '.*': options.scriptPreprocessor
 | |
|     };
 | |
|   }
 | |
| 
 | |
|   if (options.preprocessorIgnorePatterns) {
 | |
|     options.transformIgnorePatterns = options.preprocessorIgnorePatterns;
 | |
|   }
 | |
| 
 | |
|   delete options.scriptPreprocessor;
 | |
|   delete options.preprocessorIgnorePatterns;
 | |
|   return options;
 | |
| };
 | |
| 
 | |
| const normalizeMissingOptions = (options, configPath, projectIndex) => {
 | |
|   if (!options.name) {
 | |
|     options.name = _crypto()
 | |
|       .default.createHash('md5')
 | |
|       .update(options.rootDir) // In case we load config from some path that has the same root dir
 | |
|       .update(configPath || '')
 | |
|       .update(String(projectIndex))
 | |
|       .digest('hex');
 | |
|   }
 | |
| 
 | |
|   if (!options.setupFiles) {
 | |
|     options.setupFiles = [];
 | |
|   }
 | |
| 
 | |
|   return options;
 | |
| };
 | |
| 
 | |
| const normalizeRootDir = options => {
 | |
|   // Assert that there *is* a rootDir
 | |
|   if (!options.hasOwnProperty('rootDir')) {
 | |
|     throw createConfigError(
 | |
|       `  Configuration option ${_chalk().default.bold(
 | |
|         'rootDir'
 | |
|       )} must be specified.`
 | |
|     );
 | |
|   }
 | |
| 
 | |
|   options.rootDir = _path().default.normalize(options.rootDir);
 | |
| 
 | |
|   try {
 | |
|     // try to resolve windows short paths, ignoring errors (permission errors, mostly)
 | |
|     options.rootDir = (0, _realpathNative().sync)(options.rootDir);
 | |
|   } catch (e) {
 | |
|     // ignored
 | |
|   }
 | |
| 
 | |
|   return options;
 | |
| };
 | |
| 
 | |
| const normalizeReporters = options => {
 | |
|   const reporters = options.reporters;
 | |
| 
 | |
|   if (!reporters || !Array.isArray(reporters)) {
 | |
|     return options;
 | |
|   }
 | |
| 
 | |
|   (0, _ReporterValidationErrors.validateReporters)(reporters);
 | |
|   options.reporters = reporters.map(reporterConfig => {
 | |
|     const normalizedReporterConfig =
 | |
|       typeof reporterConfig === 'string' // if reporter config is a string, we wrap it in an array
 | |
|         ? // and pass an empty object for options argument, to normalize
 | |
|           [reporterConfig, {}]
 | |
|         : reporterConfig;
 | |
|     const reporterPath = (0, _utils.replaceRootDirInPath)(
 | |
|       options.rootDir,
 | |
|       normalizedReporterConfig[0]
 | |
|     );
 | |
| 
 | |
|     if (reporterPath !== _constants.DEFAULT_REPORTER_LABEL) {
 | |
|       const reporter = _jestResolve().default.findNodeModule(reporterPath, {
 | |
|         basedir: options.rootDir
 | |
|       });
 | |
| 
 | |
|       if (!reporter) {
 | |
|         throw new Error(
 | |
|           `Could not resolve a module for a custom reporter.\n` +
 | |
|             `  Module name: ${reporterPath}`
 | |
|         );
 | |
|       }
 | |
| 
 | |
|       normalizedReporterConfig[0] = reporter;
 | |
|     }
 | |
| 
 | |
|     return normalizedReporterConfig;
 | |
|   });
 | |
|   return options;
 | |
| };
 | |
| 
 | |
| const buildTestPathPattern = argv => {
 | |
|   const patterns = [];
 | |
| 
 | |
|   if (argv._) {
 | |
|     patterns.push(...argv._);
 | |
|   }
 | |
| 
 | |
|   if (argv.testPathPattern) {
 | |
|     patterns.push(...argv.testPathPattern);
 | |
|   }
 | |
| 
 | |
|   const replacePosixSep = pattern => {
 | |
|     if (_path().default.sep === '/') {
 | |
|       return pattern;
 | |
|     }
 | |
| 
 | |
|     return pattern.replace(/\//g, '\\\\');
 | |
|   };
 | |
| 
 | |
|   const testPathPattern = patterns.map(replacePosixSep).join('|');
 | |
| 
 | |
|   if ((0, _validatePattern.default)(testPathPattern)) {
 | |
|     return testPathPattern;
 | |
|   } else {
 | |
|     showTestPathPatternError(testPathPattern);
 | |
|     return '';
 | |
|   }
 | |
| };
 | |
| 
 | |
| const showTestPathPatternError = testPathPattern => {
 | |
|   (0, _jestUtil().clearLine)(process.stdout);
 | |
|   console.log(
 | |
|     _chalk().default.red(
 | |
|       `  Invalid testPattern ${testPathPattern} supplied. ` +
 | |
|         `Running all tests instead.`
 | |
|     )
 | |
|   );
 | |
| };
 | |
| 
 | |
| function normalize(options, argv, configPath, projectIndex = Infinity) {
 | |
|   const _validate = (0, _jestValidate().validate)(options, {
 | |
|       comment: _utils.DOCUMENTATION_NOTE,
 | |
|       deprecatedConfig: _Deprecated.default,
 | |
|       exampleConfig: _ValidConfig.default,
 | |
|       recursiveBlacklist: [
 | |
|         'collectCoverageOnlyFrom', // 'coverageThreshold' allows to use 'global' and glob strings on the same
 | |
|         'coverageThreshold',
 | |
|         'globals',
 | |
|         'moduleNameMapper',
 | |
|         'testEnvironmentOptions',
 | |
|         'transform'
 | |
|       ]
 | |
|     }),
 | |
|     hasDeprecationWarnings = _validate.hasDeprecationWarnings;
 | |
| 
 | |
|   options = normalizePreprocessor(
 | |
|     normalizeReporters(
 | |
|       normalizeMissingOptions(
 | |
|         normalizeRootDir((0, _setFromArgv.default)(options, argv)),
 | |
|         configPath,
 | |
|         projectIndex
 | |
|       )
 | |
|     )
 | |
|   );
 | |
| 
 | |
|   if (options.preset) {
 | |
|     options = setupPreset(options, options.preset);
 | |
|   }
 | |
| 
 | |
|   if (!options.setupFilesAfterEnv) {
 | |
|     options.setupFilesAfterEnv = [];
 | |
|   }
 | |
| 
 | |
|   if (
 | |
|     options.setupTestFrameworkScriptFile &&
 | |
|     options.setupFilesAfterEnv.length > 0
 | |
|   ) {
 | |
|     throw createConfigError(`  Options: ${_chalk().default.bold(
 | |
|       'setupTestFrameworkScriptFile'
 | |
|     )} and ${_chalk().default.bold(
 | |
|       'setupFilesAfterEnv'
 | |
|     )} cannot be used together.
 | |
|   Please change your configuration to only use ${_chalk().default.bold(
 | |
|     'setupFilesAfterEnv'
 | |
|   )}.`);
 | |
|   }
 | |
| 
 | |
|   if (options.setupTestFrameworkScriptFile) {
 | |
|     options.setupFilesAfterEnv.push(options.setupTestFrameworkScriptFile);
 | |
|   }
 | |
| 
 | |
|   options.testEnvironment = (0, _utils.getTestEnvironment)({
 | |
|     rootDir: options.rootDir,
 | |
|     testEnvironment:
 | |
|       options.testEnvironment || _Defaults.default.testEnvironment
 | |
|   });
 | |
| 
 | |
|   if (!options.roots && options.testPathDirs) {
 | |
|     options.roots = options.testPathDirs;
 | |
|     delete options.testPathDirs;
 | |
|   }
 | |
| 
 | |
|   if (!options.roots) {
 | |
|     options.roots = [options.rootDir];
 | |
|   }
 | |
| 
 | |
|   if (!options.testRunner || options.testRunner === 'jasmine2') {
 | |
|     options.testRunner = require.resolve('jest-jasmine2');
 | |
|   }
 | |
| 
 | |
|   if (!options.coverageDirectory) {
 | |
|     options.coverageDirectory = _path().default.resolve(
 | |
|       options.rootDir,
 | |
|       'coverage'
 | |
|     );
 | |
|   }
 | |
| 
 | |
|   setupBabelJest(options); // TODO: Type this properly
 | |
| 
 | |
|   const newOptions = _objectSpread({}, _Defaults.default);
 | |
| 
 | |
|   if (options.resolver) {
 | |
|     newOptions.resolver = (0, _utils.resolve)(null, {
 | |
|       filePath: options.resolver,
 | |
|       key: 'resolver',
 | |
|       rootDir: options.rootDir
 | |
|     });
 | |
|   }
 | |
| 
 | |
|   const optionKeys = Object.keys(options);
 | |
|   optionKeys.reduce((newOptions, key) => {
 | |
|     // The resolver has been resolved separately; skip it
 | |
|     if (key === 'resolver') {
 | |
|       return newOptions;
 | |
|     } // This is cheating, because it claims that all keys of InitialOptions are Required.
 | |
|     // We only really know it's Required for oldOptions[key], not for oldOptions.someOtherKey,
 | |
|     // so oldOptions[key] is the only way it should be used.
 | |
| 
 | |
|     const oldOptions = options;
 | |
|     let value;
 | |
| 
 | |
|     switch (key) {
 | |
|       case 'collectCoverageOnlyFrom':
 | |
|         value = normalizeCollectCoverageOnlyFrom(oldOptions, key);
 | |
|         break;
 | |
| 
 | |
|       case 'setupFiles':
 | |
|       case 'setupFilesAfterEnv':
 | |
|       case 'snapshotSerializers':
 | |
|         {
 | |
|           const option = oldOptions[key];
 | |
|           value =
 | |
|             option &&
 | |
|             option.map(filePath =>
 | |
|               (0, _utils.resolve)(newOptions.resolver, {
 | |
|                 filePath,
 | |
|                 key,
 | |
|                 rootDir: options.rootDir
 | |
|               })
 | |
|             );
 | |
|         }
 | |
|         break;
 | |
| 
 | |
|       case 'modulePaths':
 | |
|       case 'roots':
 | |
|         {
 | |
|           const option = oldOptions[key];
 | |
|           value =
 | |
|             option &&
 | |
|             option.map(filePath =>
 | |
|               _path().default.resolve(
 | |
|                 options.rootDir,
 | |
|                 (0, _utils.replaceRootDirInPath)(options.rootDir, filePath)
 | |
|               )
 | |
|             );
 | |
|         }
 | |
|         break;
 | |
| 
 | |
|       case 'collectCoverageFrom':
 | |
|         value = normalizeCollectCoverageFrom(oldOptions, key);
 | |
|         break;
 | |
| 
 | |
|       case 'cacheDirectory':
 | |
|       case 'coverageDirectory':
 | |
|         {
 | |
|           const option = oldOptions[key];
 | |
|           value =
 | |
|             option &&
 | |
|             _path().default.resolve(
 | |
|               options.rootDir,
 | |
|               (0, _utils.replaceRootDirInPath)(options.rootDir, option)
 | |
|             );
 | |
|         }
 | |
|         break;
 | |
| 
 | |
|       case 'dependencyExtractor':
 | |
|       case 'globalSetup':
 | |
|       case 'globalTeardown':
 | |
|       case 'moduleLoader':
 | |
|       case 'snapshotResolver':
 | |
|       case 'testResultsProcessor':
 | |
|       case 'testRunner':
 | |
|       case 'filter':
 | |
|         {
 | |
|           const option = oldOptions[key];
 | |
|           value =
 | |
|             option &&
 | |
|             (0, _utils.resolve)(newOptions.resolver, {
 | |
|               filePath: option,
 | |
|               key,
 | |
|               rootDir: options.rootDir
 | |
|             });
 | |
|         }
 | |
|         break;
 | |
| 
 | |
|       case 'runner':
 | |
|         {
 | |
|           const option = oldOptions[key];
 | |
|           value =
 | |
|             option &&
 | |
|             (0, _utils.getRunner)(newOptions.resolver, {
 | |
|               filePath: option,
 | |
|               rootDir: options.rootDir
 | |
|             });
 | |
|         }
 | |
|         break;
 | |
| 
 | |
|       case 'prettierPath':
 | |
|         {
 | |
|           // We only want this to throw if "prettierPath" is explicitly passed
 | |
|           // from config or CLI, and the requested path isn't found. Otherwise we
 | |
|           // set it to null and throw an error lazily when it is used.
 | |
|           const option = oldOptions[key];
 | |
|           value =
 | |
|             option &&
 | |
|             (0, _utils.resolve)(newOptions.resolver, {
 | |
|               filePath: option,
 | |
|               key,
 | |
|               optional: option === _Defaults.default[key],
 | |
|               rootDir: options.rootDir
 | |
|             });
 | |
|         }
 | |
|         break;
 | |
| 
 | |
|       case 'moduleNameMapper':
 | |
|         const moduleNameMapper = oldOptions[key];
 | |
|         value =
 | |
|           moduleNameMapper &&
 | |
|           Object.keys(moduleNameMapper).map(regex => {
 | |
|             const item = moduleNameMapper && moduleNameMapper[regex];
 | |
|             return (
 | |
|               item && [
 | |
|                 regex,
 | |
|                 (0, _utils._replaceRootDirTags)(options.rootDir, item)
 | |
|               ]
 | |
|             );
 | |
|           });
 | |
|         break;
 | |
| 
 | |
|       case 'transform':
 | |
|         const transform = oldOptions[key];
 | |
|         value =
 | |
|           transform &&
 | |
|           Object.keys(transform).map(regex => [
 | |
|             regex,
 | |
|             (0, _utils.resolve)(newOptions.resolver, {
 | |
|               filePath: transform[regex],
 | |
|               key,
 | |
|               rootDir: options.rootDir
 | |
|             })
 | |
|           ]);
 | |
|         break;
 | |
| 
 | |
|       case 'coveragePathIgnorePatterns':
 | |
|       case 'modulePathIgnorePatterns':
 | |
|       case 'testPathIgnorePatterns':
 | |
|       case 'transformIgnorePatterns':
 | |
|       case 'watchPathIgnorePatterns':
 | |
|       case 'unmockedModulePathPatterns':
 | |
|         value = normalizeUnmockedModulePathPatterns(oldOptions, key);
 | |
|         break;
 | |
| 
 | |
|       case 'haste':
 | |
|         value = _objectSpread({}, oldOptions[key]);
 | |
| 
 | |
|         if (value.hasteImplModulePath != null) {
 | |
|           const resolvedHasteImpl = (0, _utils.resolve)(newOptions.resolver, {
 | |
|             filePath: (0, _utils.replaceRootDirInPath)(
 | |
|               options.rootDir,
 | |
|               value.hasteImplModulePath
 | |
|             ),
 | |
|             key: 'haste.hasteImplModulePath',
 | |
|             rootDir: options.rootDir
 | |
|           });
 | |
|           value.hasteImplModulePath = resolvedHasteImpl || undefined;
 | |
|         }
 | |
| 
 | |
|         break;
 | |
| 
 | |
|       case 'projects':
 | |
|         value = (oldOptions[key] || [])
 | |
|           .map(project =>
 | |
|             typeof project === 'string'
 | |
|               ? (0, _utils._replaceRootDirTags)(options.rootDir, project)
 | |
|               : project
 | |
|           )
 | |
|           .reduce((projects, project) => {
 | |
|             // Project can be specified as globs. If a glob matches any files,
 | |
|             // We expand it to these paths. If not, we keep the original path
 | |
|             // for the future resolution.
 | |
|             const globMatches =
 | |
|               typeof project === 'string' ? _glob().default.sync(project) : [];
 | |
|             return projects.concat(globMatches.length ? globMatches : project);
 | |
|           }, []);
 | |
|         break;
 | |
| 
 | |
|       case 'moduleDirectories':
 | |
|       case 'testMatch':
 | |
|         {
 | |
|           const replacedRootDirTags = (0, _utils._replaceRootDirTags)(
 | |
|             (0, _utils.escapeGlobCharacters)(options.rootDir),
 | |
|             oldOptions[key]
 | |
|           );
 | |
| 
 | |
|           if (replacedRootDirTags) {
 | |
|             value = Array.isArray(replacedRootDirTags)
 | |
|               ? replacedRootDirTags.map(_jestUtil().replacePathSepForGlob)
 | |
|               : (0, _jestUtil().replacePathSepForGlob)(replacedRootDirTags);
 | |
|           } else {
 | |
|             value = replacedRootDirTags;
 | |
|           }
 | |
|         }
 | |
|         break;
 | |
| 
 | |
|       case 'testRegex':
 | |
|         {
 | |
|           const option = oldOptions[key];
 | |
|           value = option
 | |
|             ? (Array.isArray(option) ? option : [option]).map(
 | |
|                 _jestRegexUtil().replacePathSepForRegex
 | |
|               )
 | |
|             : [];
 | |
|         }
 | |
|         break;
 | |
| 
 | |
|       case 'moduleFileExtensions': {
 | |
|         value = oldOptions[key];
 | |
| 
 | |
|         if (
 | |
|           Array.isArray(value) && // If it's the wrong type, it can throw at a later time
 | |
|           (options.runner === undefined ||
 | |
|             options.runner === _Defaults.default.runner) && // Only require 'js' for the default jest-runner
 | |
|           !value.includes('js')
 | |
|         ) {
 | |
|           const errorMessage =
 | |
|             `  moduleFileExtensions must include 'js':\n` +
 | |
|             `  but instead received:\n` +
 | |
|             `    ${_chalk().default.bold.red(JSON.stringify(value))}`; // If `js` is not included, any dependency Jest itself injects into
 | |
|           // the environment, like jasmine or sourcemap-support, will need to
 | |
|           // `require` its modules with a file extension. This is not plausible
 | |
|           // in the long run, so it's way easier to just fail hard early.
 | |
|           // We might consider throwing if `json` is missing as well, as it's a
 | |
|           // fair assumption from modules that they can do
 | |
|           // `require('some-package/package') without the trailing `.json` as it
 | |
|           // works in Node normally.
 | |
| 
 | |
|           throw createConfigError(
 | |
|             errorMessage +
 | |
|               "\n  Please change your configuration to include 'js'."
 | |
|           );
 | |
|         }
 | |
| 
 | |
|         break;
 | |
|       }
 | |
| 
 | |
|       case 'bail': {
 | |
|         const bail = oldOptions[key];
 | |
| 
 | |
|         if (typeof bail === 'boolean') {
 | |
|           value = bail ? 1 : 0;
 | |
|         } else if (typeof bail === 'string') {
 | |
|           value = 1; // If Jest is invoked as `jest --bail someTestPattern` then need to
 | |
|           // move the pattern from the `bail` configuration and into `argv._`
 | |
|           // to be processed as an extra parameter
 | |
| 
 | |
|           argv._.push(bail);
 | |
|         } else {
 | |
|           value = oldOptions[key];
 | |
|         }
 | |
| 
 | |
|         break;
 | |
|       }
 | |
| 
 | |
|       case 'displayName': {
 | |
|         const displayName = oldOptions[key];
 | |
| 
 | |
|         if (typeof displayName === 'string') {
 | |
|           value = displayName;
 | |
|           break;
 | |
|         }
 | |
|         /**
 | |
|          * Ensuring that displayName shape is correct here so that the
 | |
|          * reporters can trust the shape of the data
 | |
|          * TODO: Normalize "displayName" such that given a config option
 | |
|          * {
 | |
|          *  "displayName": "Test"
 | |
|          * }
 | |
|          * becomes
 | |
|          * {
 | |
|          *   displayName: {
 | |
|          *     name: "Test",
 | |
|          *     color: "white"
 | |
|          *   }
 | |
|          * }
 | |
|          *
 | |
|          * This can't be done now since this will be a breaking change
 | |
|          * for custom reporters
 | |
|          */
 | |
| 
 | |
|         if ((0, _jestGetType().default)(displayName) === 'object') {
 | |
|           const errorMessage =
 | |
|             `  Option "${_chalk().default.bold(
 | |
|               'displayName'
 | |
|             )}" must be of type:\n\n` +
 | |
|             '  {\n' +
 | |
|             '    name: string;\n' +
 | |
|             '    color: string;\n' +
 | |
|             '  }\n';
 | |
|           const name = displayName.name,
 | |
|             color = displayName.color;
 | |
| 
 | |
|           if (
 | |
|             !name ||
 | |
|             !color ||
 | |
|             typeof name !== 'string' ||
 | |
|             typeof color !== 'string'
 | |
|           ) {
 | |
|             throw createConfigError(errorMessage);
 | |
|           }
 | |
|         }
 | |
| 
 | |
|         value = oldOptions[key];
 | |
|         break;
 | |
|       }
 | |
| 
 | |
|       case 'automock':
 | |
|       case 'browser':
 | |
|       case 'cache':
 | |
|       case 'changedSince':
 | |
|       case 'changedFilesWithAncestor':
 | |
|       case 'clearMocks':
 | |
|       case 'collectCoverage':
 | |
|       case 'coverageReporters':
 | |
|       case 'coverageThreshold':
 | |
|       case 'detectLeaks':
 | |
|       case 'detectOpenHandles':
 | |
|       case 'errorOnDeprecated':
 | |
|       case 'expand':
 | |
|       case 'extraGlobals':
 | |
|       case 'globals':
 | |
|       case 'findRelatedTests':
 | |
|       case 'forceCoverageMatch':
 | |
|       case 'forceExit':
 | |
|       case 'lastCommit':
 | |
|       case 'listTests':
 | |
|       case 'logHeapUsage':
 | |
|       case 'maxConcurrency':
 | |
|       case 'mapCoverage':
 | |
|       case 'name':
 | |
|       case 'noStackTrace':
 | |
|       case 'notify':
 | |
|       case 'notifyMode':
 | |
|       case 'onlyChanged':
 | |
|       case 'outputFile':
 | |
|       case 'passWithNoTests':
 | |
|       case 'replname':
 | |
|       case 'reporters':
 | |
|       case 'resetMocks':
 | |
|       case 'resetModules':
 | |
|       case 'restoreMocks':
 | |
|       case 'rootDir':
 | |
|       case 'runTestsByPath':
 | |
|       case 'silent':
 | |
|       case 'skipFilter':
 | |
|       case 'skipNodeResolution':
 | |
|       case 'testEnvironment':
 | |
|       case 'testEnvironmentOptions':
 | |
|       case 'testFailureExitCode':
 | |
|       case 'testLocationInResults':
 | |
|       case 'testNamePattern':
 | |
|       case 'testURL':
 | |
|       case 'timers':
 | |
|       case 'useStderr':
 | |
|       case 'verbose':
 | |
|       case 'watch':
 | |
|       case 'watchAll':
 | |
|       case 'watchman':
 | |
|         value = oldOptions[key];
 | |
|         break;
 | |
| 
 | |
|       case 'watchPlugins':
 | |
|         value = (oldOptions[key] || []).map(watchPlugin => {
 | |
|           if (typeof watchPlugin === 'string') {
 | |
|             return {
 | |
|               config: {},
 | |
|               path: (0, _utils.getWatchPlugin)(newOptions.resolver, {
 | |
|                 filePath: watchPlugin,
 | |
|                 rootDir: options.rootDir
 | |
|               })
 | |
|             };
 | |
|           } else {
 | |
|             return {
 | |
|               config: watchPlugin[1] || {},
 | |
|               path: (0, _utils.getWatchPlugin)(newOptions.resolver, {
 | |
|                 filePath: watchPlugin[0],
 | |
|                 rootDir: options.rootDir
 | |
|               })
 | |
|             };
 | |
|           }
 | |
|         });
 | |
|         break;
 | |
|     } // @ts-ignore: automock is missing in GlobalConfig, so what
 | |
| 
 | |
|     newOptions[key] = value;
 | |
|     return newOptions;
 | |
|   }, newOptions);
 | |
| 
 | |
|   try {
 | |
|     // try to resolve windows short paths, ignoring errors (permission errors, mostly)
 | |
|     newOptions.cwd = (0, _realpathNative().sync)(process.cwd());
 | |
|   } catch (e) {
 | |
|     // ignored
 | |
|   }
 | |
| 
 | |
|   newOptions.testSequencer = (0, _utils.getSequencer)(newOptions.resolver, {
 | |
|     filePath: options.testSequencer || _Defaults.default.testSequencer,
 | |
|     rootDir: options.rootDir
 | |
|   });
 | |
|   newOptions.nonFlagArgs = argv._;
 | |
|   newOptions.testPathPattern = buildTestPathPattern(argv);
 | |
|   newOptions.json = !!argv.json;
 | |
|   newOptions.testFailureExitCode = parseInt(newOptions.testFailureExitCode, 10);
 | |
| 
 | |
|   if (
 | |
|     newOptions.lastCommit ||
 | |
|     newOptions.changedFilesWithAncestor ||
 | |
|     newOptions.changedSince
 | |
|   ) {
 | |
|     newOptions.onlyChanged = true;
 | |
|   }
 | |
| 
 | |
|   if (argv.all) {
 | |
|     newOptions.onlyChanged = false;
 | |
|   } else if (newOptions.testPathPattern) {
 | |
|     // When passing a test path pattern we don't want to only monitor changed
 | |
|     // files unless `--watch` is also passed.
 | |
|     newOptions.onlyChanged = newOptions.watch;
 | |
|   }
 | |
| 
 | |
|   newOptions.updateSnapshot =
 | |
|     argv.ci && !argv.updateSnapshot
 | |
|       ? 'none'
 | |
|       : argv.updateSnapshot
 | |
|       ? 'all'
 | |
|       : 'new';
 | |
|   newOptions.maxConcurrency = parseInt(newOptions.maxConcurrency, 10);
 | |
|   newOptions.maxWorkers = (0, _getMaxWorkers.default)(argv);
 | |
| 
 | |
|   if (newOptions.testRegex.length && options.testMatch) {
 | |
|     throw createConfigError(
 | |
|       `  Configuration options ${_chalk().default.bold('testMatch')} and` +
 | |
|         ` ${_chalk().default.bold('testRegex')} cannot be used together.`
 | |
|     );
 | |
|   }
 | |
| 
 | |
|   if (newOptions.testRegex.length && !options.testMatch) {
 | |
|     // Prevent the default testMatch conflicting with any explicitly
 | |
|     // configured `testRegex` value
 | |
|     newOptions.testMatch = [];
 | |
|   } // If argv.json is set, coverageReporters shouldn't print a text report.
 | |
| 
 | |
|   if (argv.json) {
 | |
|     newOptions.coverageReporters = (newOptions.coverageReporters || []).filter(
 | |
|       reporter => reporter !== 'text'
 | |
|     );
 | |
|   } // If collectCoverage is enabled while using --findRelatedTests we need to
 | |
|   // avoid having false negatives in the generated coverage report.
 | |
|   // The following: `--findRelatedTests '/rootDir/file1.js' --coverage`
 | |
|   // Is transformed to: `--findRelatedTests '/rootDir/file1.js' --coverage --collectCoverageFrom 'file1.js'`
 | |
|   // where arguments to `--collectCoverageFrom` should be globs (or relative
 | |
|   // paths to the rootDir)
 | |
| 
 | |
|   if (newOptions.collectCoverage && argv.findRelatedTests) {
 | |
|     let collectCoverageFrom = argv._.map(filename => {
 | |
|       filename = (0, _utils.replaceRootDirInPath)(options.rootDir, filename);
 | |
|       return _path().default.isAbsolute(filename)
 | |
|         ? _path().default.relative(options.rootDir, filename)
 | |
|         : filename;
 | |
|     }); // Don't override existing collectCoverageFrom options
 | |
| 
 | |
|     if (newOptions.collectCoverageFrom) {
 | |
|       collectCoverageFrom = collectCoverageFrom.reduce((patterns, filename) => {
 | |
|         if (
 | |
|           !_micromatch().default.some(
 | |
|             (0, _jestUtil().replacePathSepForGlob)(
 | |
|               _path().default.relative(options.rootDir, filename)
 | |
|             ),
 | |
|             newOptions.collectCoverageFrom
 | |
|           )
 | |
|         ) {
 | |
|           return patterns;
 | |
|         }
 | |
| 
 | |
|         return [...patterns, filename];
 | |
|       }, newOptions.collectCoverageFrom);
 | |
|     }
 | |
| 
 | |
|     newOptions.collectCoverageFrom = collectCoverageFrom;
 | |
|   }
 | |
| 
 | |
|   return {
 | |
|     hasDeprecationWarnings,
 | |
|     options: newOptions
 | |
|   };
 | |
| }
 |