normalize.js 37 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372
  1. 'use strict';
  2. Object.defineProperty(exports, '__esModule', {
  3. value: true
  4. });
  5. exports.default = normalize;
  6. function _crypto() {
  7. const data = require('crypto');
  8. _crypto = function () {
  9. return data;
  10. };
  11. return data;
  12. }
  13. function path() {
  14. const data = _interopRequireWildcard(require('path'));
  15. path = function () {
  16. return data;
  17. };
  18. return data;
  19. }
  20. function _chalk() {
  21. const data = _interopRequireDefault(require('chalk'));
  22. _chalk = function () {
  23. return data;
  24. };
  25. return data;
  26. }
  27. function _deepmerge() {
  28. const data = _interopRequireDefault(require('deepmerge'));
  29. _deepmerge = function () {
  30. return data;
  31. };
  32. return data;
  33. }
  34. function _glob() {
  35. const data = require('glob');
  36. _glob = function () {
  37. return data;
  38. };
  39. return data;
  40. }
  41. function _gracefulFs() {
  42. const data = require('graceful-fs');
  43. _gracefulFs = function () {
  44. return data;
  45. };
  46. return data;
  47. }
  48. function _micromatch() {
  49. const data = _interopRequireDefault(require('micromatch'));
  50. _micromatch = function () {
  51. return data;
  52. };
  53. return data;
  54. }
  55. function _jestRegexUtil() {
  56. const data = require('jest-regex-util');
  57. _jestRegexUtil = function () {
  58. return data;
  59. };
  60. return data;
  61. }
  62. function _jestResolve() {
  63. const data = _interopRequireWildcard(require('jest-resolve'));
  64. _jestResolve = function () {
  65. return data;
  66. };
  67. return data;
  68. }
  69. function _jestUtil() {
  70. const data = require('jest-util');
  71. _jestUtil = function () {
  72. return data;
  73. };
  74. return data;
  75. }
  76. function _jestValidate() {
  77. const data = require('jest-validate');
  78. _jestValidate = function () {
  79. return data;
  80. };
  81. return data;
  82. }
  83. var _Defaults = _interopRequireDefault(require('./Defaults'));
  84. var _Deprecated = _interopRequireDefault(require('./Deprecated'));
  85. var _ReporterValidationErrors = require('./ReporterValidationErrors');
  86. var _ValidConfig = _interopRequireDefault(require('./ValidConfig'));
  87. var _color = require('./color');
  88. var _constants = require('./constants');
  89. var _getMaxWorkers = _interopRequireDefault(require('./getMaxWorkers'));
  90. var _setFromArgv = _interopRequireDefault(require('./setFromArgv'));
  91. var _utils = require('./utils');
  92. var _validatePattern = _interopRequireDefault(require('./validatePattern'));
  93. function _interopRequireDefault(obj) {
  94. return obj && obj.__esModule ? obj : {default: obj};
  95. }
  96. function _getRequireWildcardCache(nodeInterop) {
  97. if (typeof WeakMap !== 'function') return null;
  98. var cacheBabelInterop = new WeakMap();
  99. var cacheNodeInterop = new WeakMap();
  100. return (_getRequireWildcardCache = function (nodeInterop) {
  101. return nodeInterop ? cacheNodeInterop : cacheBabelInterop;
  102. })(nodeInterop);
  103. }
  104. function _interopRequireWildcard(obj, nodeInterop) {
  105. if (!nodeInterop && obj && obj.__esModule) {
  106. return obj;
  107. }
  108. if (obj === null || (typeof obj !== 'object' && typeof obj !== 'function')) {
  109. return {default: obj};
  110. }
  111. var cache = _getRequireWildcardCache(nodeInterop);
  112. if (cache && cache.has(obj)) {
  113. return cache.get(obj);
  114. }
  115. var newObj = {};
  116. var hasPropertyDescriptor =
  117. Object.defineProperty && Object.getOwnPropertyDescriptor;
  118. for (var key in obj) {
  119. if (key !== 'default' && Object.prototype.hasOwnProperty.call(obj, key)) {
  120. var desc = hasPropertyDescriptor
  121. ? Object.getOwnPropertyDescriptor(obj, key)
  122. : null;
  123. if (desc && (desc.get || desc.set)) {
  124. Object.defineProperty(newObj, key, desc);
  125. } else {
  126. newObj[key] = obj[key];
  127. }
  128. }
  129. }
  130. newObj.default = obj;
  131. if (cache) {
  132. cache.set(obj, newObj);
  133. }
  134. return newObj;
  135. }
  136. /**
  137. * Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
  138. *
  139. * This source code is licensed under the MIT license found in the
  140. * LICENSE file in the root directory of this source tree.
  141. */
  142. const ERROR = `${_utils.BULLET}Validation Error`;
  143. const PRESET_EXTENSIONS = ['.json', '.js', '.cjs', '.mjs'];
  144. const PRESET_NAME = 'jest-preset';
  145. const createConfigError = message =>
  146. new (_jestValidate().ValidationError)(
  147. ERROR,
  148. message,
  149. _utils.DOCUMENTATION_NOTE
  150. );
  151. function verifyDirectoryExists(path, key) {
  152. try {
  153. const rootStat = (0, _gracefulFs().statSync)(path);
  154. if (!rootStat.isDirectory()) {
  155. throw createConfigError(
  156. ` ${_chalk().default.bold(path)} in the ${_chalk().default.bold(
  157. key
  158. )} option is not a directory.`
  159. );
  160. }
  161. } catch (err) {
  162. if (err instanceof _jestValidate().ValidationError) {
  163. throw err;
  164. }
  165. if (err.code === 'ENOENT') {
  166. throw createConfigError(
  167. ` Directory ${_chalk().default.bold(
  168. path
  169. )} in the ${_chalk().default.bold(key)} option was not found.`
  170. );
  171. } // Not sure in which cases `statSync` can throw, so let's just show the underlying error to the user
  172. throw createConfigError(
  173. ` Got an error trying to find ${_chalk().default.bold(
  174. path
  175. )} in the ${_chalk().default.bold(key)} option.\n\n Error was: ${
  176. err.message
  177. }`
  178. );
  179. }
  180. } // TS 3.5 forces us to split these into 2
  181. const mergeModuleNameMapperWithPreset = (options, preset) => {
  182. if (options['moduleNameMapper'] && preset['moduleNameMapper']) {
  183. options['moduleNameMapper'] = {
  184. ...options['moduleNameMapper'],
  185. ...preset['moduleNameMapper'],
  186. ...options['moduleNameMapper']
  187. };
  188. }
  189. };
  190. const mergeTransformWithPreset = (options, preset) => {
  191. if (options['transform'] && preset['transform']) {
  192. options['transform'] = {
  193. ...options['transform'],
  194. ...preset['transform'],
  195. ...options['transform']
  196. };
  197. }
  198. };
  199. const mergeGlobalsWithPreset = (options, preset) => {
  200. if (options['globals'] && preset['globals']) {
  201. options['globals'] = (0, _deepmerge().default)(
  202. preset['globals'],
  203. options['globals']
  204. );
  205. }
  206. };
  207. const setupPreset = async (options, optionsPreset) => {
  208. let preset;
  209. const presetPath = (0, _utils.replaceRootDirInPath)(
  210. options.rootDir,
  211. optionsPreset
  212. );
  213. const presetModule = _jestResolve().default.findNodeModule(
  214. presetPath.startsWith('.')
  215. ? presetPath
  216. : path().join(presetPath, PRESET_NAME),
  217. {
  218. basedir: options.rootDir,
  219. extensions: PRESET_EXTENSIONS
  220. }
  221. );
  222. try {
  223. if (!presetModule) {
  224. throw new Error(`Cannot find module '${presetPath}'`);
  225. } // Force re-evaluation to support multiple projects
  226. try {
  227. delete require.cache[require.resolve(presetModule)];
  228. } catch {}
  229. preset = await (0, _jestUtil().requireOrImportModule)(presetModule);
  230. } catch (error) {
  231. if (error instanceof SyntaxError || error instanceof TypeError) {
  232. throw createConfigError(
  233. ` Preset ${_chalk().default.bold(presetPath)} is invalid:\n\n ${
  234. error.message
  235. }\n ${error.stack}`
  236. );
  237. }
  238. if (error.message.includes('Cannot find module')) {
  239. if (error.message.includes(presetPath)) {
  240. const preset = _jestResolve().default.findNodeModule(presetPath, {
  241. basedir: options.rootDir
  242. });
  243. if (preset) {
  244. throw createConfigError(
  245. ` Module ${_chalk().default.bold(
  246. presetPath
  247. )} should have "jest-preset.js" or "jest-preset.json" file at the root.`
  248. );
  249. }
  250. throw createConfigError(
  251. ` Preset ${_chalk().default.bold(presetPath)} not found.`
  252. );
  253. }
  254. throw createConfigError(
  255. ` Missing dependency in ${_chalk().default.bold(presetPath)}:\n\n ${
  256. error.message
  257. }\n ${error.stack}`
  258. );
  259. }
  260. throw createConfigError(
  261. ` An unknown error occurred in ${_chalk().default.bold(
  262. presetPath
  263. )}:\n\n ${error.message}\n ${error.stack}`
  264. );
  265. }
  266. if (options.setupFiles) {
  267. options.setupFiles = (preset.setupFiles || []).concat(options.setupFiles);
  268. }
  269. if (options.setupFilesAfterEnv) {
  270. options.setupFilesAfterEnv = (preset.setupFilesAfterEnv || []).concat(
  271. options.setupFilesAfterEnv
  272. );
  273. }
  274. if (options.modulePathIgnorePatterns && preset.modulePathIgnorePatterns) {
  275. options.modulePathIgnorePatterns = preset.modulePathIgnorePatterns.concat(
  276. options.modulePathIgnorePatterns
  277. );
  278. }
  279. mergeModuleNameMapperWithPreset(options, preset);
  280. mergeTransformWithPreset(options, preset);
  281. mergeGlobalsWithPreset(options, preset);
  282. return {...preset, ...options};
  283. };
  284. const setupBabelJest = options => {
  285. const transform = options.transform;
  286. let babelJest;
  287. if (transform) {
  288. const customJSPattern = Object.keys(transform).find(pattern => {
  289. const regex = new RegExp(pattern);
  290. return regex.test('a.js') || regex.test('a.jsx');
  291. });
  292. const customTSPattern = Object.keys(transform).find(pattern => {
  293. const regex = new RegExp(pattern);
  294. return regex.test('a.ts') || regex.test('a.tsx');
  295. });
  296. [customJSPattern, customTSPattern].forEach(pattern => {
  297. if (pattern) {
  298. const customTransformer = transform[pattern];
  299. if (Array.isArray(customTransformer)) {
  300. if (customTransformer[0] === 'babel-jest') {
  301. babelJest = require.resolve('babel-jest');
  302. customTransformer[0] = babelJest;
  303. } else if (customTransformer[0].includes('babel-jest')) {
  304. babelJest = customTransformer[0];
  305. }
  306. } else {
  307. if (customTransformer === 'babel-jest') {
  308. babelJest = require.resolve('babel-jest');
  309. transform[pattern] = babelJest;
  310. } else if (customTransformer.includes('babel-jest')) {
  311. babelJest = customTransformer;
  312. }
  313. }
  314. }
  315. });
  316. } else {
  317. babelJest = require.resolve('babel-jest');
  318. options.transform = {
  319. [_constants.DEFAULT_JS_PATTERN]: babelJest
  320. };
  321. }
  322. };
  323. const normalizeCollectCoverageOnlyFrom = (options, key) => {
  324. const initialCollectCoverageFrom = options[key];
  325. const collectCoverageOnlyFrom = Array.isArray(initialCollectCoverageFrom)
  326. ? initialCollectCoverageFrom // passed from argv
  327. : Object.keys(initialCollectCoverageFrom); // passed from options
  328. return collectCoverageOnlyFrom.reduce((map, filePath) => {
  329. filePath = path().resolve(
  330. options.rootDir,
  331. (0, _utils.replaceRootDirInPath)(options.rootDir, filePath)
  332. );
  333. map[filePath] = true;
  334. return map;
  335. }, Object.create(null));
  336. };
  337. const normalizeCollectCoverageFrom = (options, key) => {
  338. const initialCollectCoverageFrom = options[key];
  339. let value;
  340. if (!initialCollectCoverageFrom) {
  341. value = [];
  342. }
  343. if (!Array.isArray(initialCollectCoverageFrom)) {
  344. try {
  345. value = JSON.parse(initialCollectCoverageFrom);
  346. } catch {}
  347. if (options[key] && !Array.isArray(value)) {
  348. value = [initialCollectCoverageFrom];
  349. }
  350. } else {
  351. value = initialCollectCoverageFrom;
  352. }
  353. if (value) {
  354. value = value.map(filePath =>
  355. filePath.replace(/^(!?)(<rootDir>\/)(.*)/, '$1$3')
  356. );
  357. }
  358. return value;
  359. };
  360. const normalizeUnmockedModulePathPatterns = (
  361. options,
  362. key // _replaceRootDirTags is specifically well-suited for substituting
  363. ) =>
  364. // <rootDir> in paths (it deals with properly interpreting relative path
  365. // separators, etc).
  366. //
  367. // For patterns, direct global substitution is far more ideal, so we
  368. // special case substitutions for patterns here.
  369. options[key].map(pattern =>
  370. (0, _jestRegexUtil().replacePathSepForRegex)(
  371. pattern.replace(/<rootDir>/g, options.rootDir)
  372. )
  373. );
  374. const normalizePreprocessor = options => {
  375. if (options.scriptPreprocessor && options.transform) {
  376. throw createConfigError(` Options: ${_chalk().default.bold(
  377. 'scriptPreprocessor'
  378. )} and ${_chalk().default.bold('transform')} cannot be used together.
  379. Please change your configuration to only use ${_chalk().default.bold(
  380. 'transform'
  381. )}.`);
  382. }
  383. if (options.preprocessorIgnorePatterns && options.transformIgnorePatterns) {
  384. throw createConfigError(` Options ${_chalk().default.bold(
  385. 'preprocessorIgnorePatterns'
  386. )} and ${_chalk().default.bold(
  387. 'transformIgnorePatterns'
  388. )} cannot be used together.
  389. Please change your configuration to only use ${_chalk().default.bold(
  390. 'transformIgnorePatterns'
  391. )}.`);
  392. }
  393. if (options.scriptPreprocessor) {
  394. options.transform = {
  395. '.*': options.scriptPreprocessor
  396. };
  397. }
  398. if (options.preprocessorIgnorePatterns) {
  399. options.transformIgnorePatterns = options.preprocessorIgnorePatterns;
  400. }
  401. delete options.scriptPreprocessor;
  402. delete options.preprocessorIgnorePatterns;
  403. return options;
  404. };
  405. const normalizeMissingOptions = (options, configPath, projectIndex) => {
  406. if (!options.name) {
  407. options.name = (0, _crypto().createHash)('md5')
  408. .update(options.rootDir) // In case we load config from some path that has the same root dir
  409. .update(configPath || '')
  410. .update(String(projectIndex))
  411. .digest('hex');
  412. }
  413. if (!options.setupFiles) {
  414. options.setupFiles = [];
  415. }
  416. return options;
  417. };
  418. const normalizeRootDir = options => {
  419. // Assert that there *is* a rootDir
  420. if (!options.rootDir) {
  421. throw createConfigError(
  422. ` Configuration option ${_chalk().default.bold(
  423. 'rootDir'
  424. )} must be specified.`
  425. );
  426. }
  427. options.rootDir = path().normalize(options.rootDir);
  428. try {
  429. // try to resolve windows short paths, ignoring errors (permission errors, mostly)
  430. options.rootDir = (0, _jestUtil().tryRealpath)(options.rootDir);
  431. } catch {
  432. // ignored
  433. }
  434. verifyDirectoryExists(options.rootDir, 'rootDir');
  435. return {...options, rootDir: options.rootDir};
  436. };
  437. const normalizeReporters = options => {
  438. const reporters = options.reporters;
  439. if (!reporters || !Array.isArray(reporters)) {
  440. return options;
  441. }
  442. (0, _ReporterValidationErrors.validateReporters)(reporters);
  443. options.reporters = reporters.map(reporterConfig => {
  444. const normalizedReporterConfig =
  445. typeof reporterConfig === 'string' // if reporter config is a string, we wrap it in an array
  446. ? // and pass an empty object for options argument, to normalize
  447. // the shape.
  448. [reporterConfig, {}]
  449. : reporterConfig;
  450. const reporterPath = (0, _utils.replaceRootDirInPath)(
  451. options.rootDir,
  452. normalizedReporterConfig[0]
  453. );
  454. if (reporterPath !== _constants.DEFAULT_REPORTER_LABEL) {
  455. const reporter = _jestResolve().default.findNodeModule(reporterPath, {
  456. basedir: options.rootDir
  457. });
  458. if (!reporter) {
  459. throw new (_jestResolve().default.ModuleNotFoundError)(
  460. 'Could not resolve a module for a custom reporter.\n' +
  461. ` Module name: ${reporterPath}`
  462. );
  463. }
  464. normalizedReporterConfig[0] = reporter;
  465. }
  466. return normalizedReporterConfig;
  467. });
  468. return options;
  469. };
  470. const buildTestPathPattern = argv => {
  471. const patterns = [];
  472. if (argv._) {
  473. patterns.push(...argv._);
  474. }
  475. if (argv.testPathPattern) {
  476. patterns.push(...argv.testPathPattern);
  477. }
  478. const replacePosixSep = pattern => {
  479. // yargs coerces positional args into numbers
  480. const patternAsString = pattern.toString();
  481. if (path().sep === '/') {
  482. return patternAsString;
  483. }
  484. return patternAsString.replace(/\//g, '\\\\');
  485. };
  486. const testPathPattern = patterns.map(replacePosixSep).join('|');
  487. if ((0, _validatePattern.default)(testPathPattern)) {
  488. return testPathPattern;
  489. } else {
  490. showTestPathPatternError(testPathPattern);
  491. return '';
  492. }
  493. };
  494. const showTestPathPatternError = testPathPattern => {
  495. (0, _jestUtil().clearLine)(process.stdout); // eslint-disable-next-line no-console
  496. console.log(
  497. _chalk().default.red(
  498. ` Invalid testPattern ${testPathPattern} supplied. ` +
  499. 'Running all tests instead.'
  500. )
  501. );
  502. };
  503. function validateExtensionsToTreatAsEsm(extensionsToTreatAsEsm) {
  504. if (!extensionsToTreatAsEsm || extensionsToTreatAsEsm.length === 0) {
  505. return;
  506. }
  507. function printConfig(opts) {
  508. const string = opts.map(ext => `'${ext}'`).join(', ');
  509. return _chalk().default.bold(`extensionsToTreatAsEsm: [${string}]`);
  510. }
  511. const extensionWithoutDot = extensionsToTreatAsEsm.some(
  512. ext => !ext.startsWith('.')
  513. );
  514. if (extensionWithoutDot) {
  515. throw createConfigError(` Option: ${printConfig(
  516. extensionsToTreatAsEsm
  517. )} includes a string that does not start with a period (${_chalk().default.bold(
  518. '.'
  519. )}).
  520. Please change your configuration to ${printConfig(
  521. extensionsToTreatAsEsm.map(ext => (ext.startsWith('.') ? ext : `.${ext}`))
  522. )}.`);
  523. }
  524. if (extensionsToTreatAsEsm.includes('.js')) {
  525. throw createConfigError(
  526. ` Option: ${printConfig(
  527. extensionsToTreatAsEsm
  528. )} includes ${_chalk().default.bold(
  529. "'.js'"
  530. )} which is always inferred based on ${_chalk().default.bold(
  531. 'type'
  532. )} in its nearest ${_chalk().default.bold('package.json')}.`
  533. );
  534. }
  535. if (extensionsToTreatAsEsm.includes('.cjs')) {
  536. throw createConfigError(
  537. ` Option: ${printConfig(
  538. extensionsToTreatAsEsm
  539. )} includes ${_chalk().default.bold(
  540. "'.cjs'"
  541. )} which is always treated as CommonJS.`
  542. );
  543. }
  544. if (extensionsToTreatAsEsm.includes('.mjs')) {
  545. throw createConfigError(
  546. ` Option: ${printConfig(
  547. extensionsToTreatAsEsm
  548. )} includes ${_chalk().default.bold(
  549. "'.mjs'"
  550. )} which is always treated as an ECMAScript Module.`
  551. );
  552. }
  553. }
  554. async function normalize(
  555. initialOptions,
  556. argv,
  557. configPath,
  558. projectIndex = Infinity
  559. ) {
  560. var _options$haste, _argv$_;
  561. const {hasDeprecationWarnings} = (0, _jestValidate().validate)(
  562. initialOptions,
  563. {
  564. comment: _utils.DOCUMENTATION_NOTE,
  565. deprecatedConfig: _Deprecated.default,
  566. exampleConfig: _ValidConfig.default,
  567. recursiveDenylist: [
  568. 'collectCoverageOnlyFrom', // 'coverageThreshold' allows to use 'global' and glob strings on the same
  569. // level, there's currently no way we can deal with such config
  570. 'coverageThreshold',
  571. 'globals',
  572. 'moduleNameMapper',
  573. 'testEnvironmentOptions',
  574. 'transform'
  575. ]
  576. }
  577. );
  578. let options = normalizePreprocessor(
  579. normalizeReporters(
  580. normalizeMissingOptions(
  581. normalizeRootDir((0, _setFromArgv.default)(initialOptions, argv)),
  582. configPath,
  583. projectIndex
  584. )
  585. )
  586. );
  587. if (options.preset) {
  588. options = await setupPreset(options, options.preset);
  589. }
  590. if (!options.setupFilesAfterEnv) {
  591. options.setupFilesAfterEnv = [];
  592. }
  593. if (
  594. options.setupTestFrameworkScriptFile &&
  595. options.setupFilesAfterEnv.length > 0
  596. ) {
  597. throw createConfigError(` Options: ${_chalk().default.bold(
  598. 'setupTestFrameworkScriptFile'
  599. )} and ${_chalk().default.bold(
  600. 'setupFilesAfterEnv'
  601. )} cannot be used together.
  602. Please change your configuration to only use ${_chalk().default.bold(
  603. 'setupFilesAfterEnv'
  604. )}.`);
  605. }
  606. if (options.setupTestFrameworkScriptFile) {
  607. options.setupFilesAfterEnv.push(options.setupTestFrameworkScriptFile);
  608. }
  609. options.testEnvironment = (0, _jestResolve().resolveTestEnvironment)({
  610. requireResolveFunction: require.resolve,
  611. rootDir: options.rootDir,
  612. testEnvironment:
  613. options.testEnvironment ||
  614. require.resolve(_Defaults.default.testEnvironment)
  615. });
  616. if (!options.roots && options.testPathDirs) {
  617. options.roots = options.testPathDirs;
  618. delete options.testPathDirs;
  619. }
  620. if (!options.roots) {
  621. options.roots = [options.rootDir];
  622. }
  623. if (
  624. !options.testRunner ||
  625. options.testRunner === 'circus' ||
  626. options.testRunner === 'jest-circus'
  627. ) {
  628. options.testRunner = require.resolve('jest-circus/runner');
  629. } else if (options.testRunner === 'jasmine2') {
  630. options.testRunner = require.resolve('jest-jasmine2');
  631. }
  632. if (!options.coverageDirectory) {
  633. options.coverageDirectory = path().resolve(options.rootDir, 'coverage');
  634. }
  635. setupBabelJest(options); // TODO: Type this properly
  636. const newOptions = {..._Defaults.default};
  637. if (options.resolver) {
  638. newOptions.resolver = (0, _utils.resolve)(null, {
  639. filePath: options.resolver,
  640. key: 'resolver',
  641. rootDir: options.rootDir
  642. });
  643. }
  644. validateExtensionsToTreatAsEsm(options.extensionsToTreatAsEsm);
  645. if (options.watchman == null) {
  646. options.watchman = _Defaults.default.watchman;
  647. }
  648. const optionKeys = Object.keys(options);
  649. optionKeys.reduce((newOptions, key) => {
  650. // The resolver has been resolved separately; skip it
  651. if (key === 'resolver') {
  652. return newOptions;
  653. } // This is cheating, because it claims that all keys of InitialOptions are Required.
  654. // We only really know it's Required for oldOptions[key], not for oldOptions.someOtherKey,
  655. // so oldOptions[key] is the only way it should be used.
  656. const oldOptions = options;
  657. let value;
  658. switch (key) {
  659. case 'collectCoverageOnlyFrom':
  660. value = normalizeCollectCoverageOnlyFrom(oldOptions, key);
  661. break;
  662. case 'setupFiles':
  663. case 'setupFilesAfterEnv':
  664. case 'snapshotSerializers':
  665. {
  666. const option = oldOptions[key];
  667. value =
  668. option &&
  669. option.map(filePath =>
  670. (0, _utils.resolve)(newOptions.resolver, {
  671. filePath,
  672. key,
  673. rootDir: options.rootDir
  674. })
  675. );
  676. }
  677. break;
  678. case 'modulePaths':
  679. case 'roots':
  680. {
  681. const option = oldOptions[key];
  682. value =
  683. option &&
  684. option.map(filePath =>
  685. path().resolve(
  686. options.rootDir,
  687. (0, _utils.replaceRootDirInPath)(options.rootDir, filePath)
  688. )
  689. );
  690. }
  691. break;
  692. case 'collectCoverageFrom':
  693. value = normalizeCollectCoverageFrom(oldOptions, key);
  694. break;
  695. case 'cacheDirectory':
  696. case 'coverageDirectory':
  697. {
  698. const option = oldOptions[key];
  699. value =
  700. option &&
  701. path().resolve(
  702. options.rootDir,
  703. (0, _utils.replaceRootDirInPath)(options.rootDir, option)
  704. );
  705. }
  706. break;
  707. case 'dependencyExtractor':
  708. case 'globalSetup':
  709. case 'globalTeardown':
  710. case 'moduleLoader':
  711. case 'snapshotResolver':
  712. case 'testResultsProcessor':
  713. case 'testRunner':
  714. case 'filter':
  715. {
  716. const option = oldOptions[key];
  717. value =
  718. option &&
  719. (0, _utils.resolve)(newOptions.resolver, {
  720. filePath: option,
  721. key,
  722. rootDir: options.rootDir
  723. });
  724. }
  725. break;
  726. case 'runner':
  727. {
  728. const option = oldOptions[key];
  729. value =
  730. option &&
  731. (0, _jestResolve().resolveRunner)(newOptions.resolver, {
  732. filePath: option,
  733. requireResolveFunction: require.resolve,
  734. rootDir: options.rootDir
  735. });
  736. }
  737. break;
  738. case 'prettierPath':
  739. {
  740. // We only want this to throw if "prettierPath" is explicitly passed
  741. // from config or CLI, and the requested path isn't found. Otherwise we
  742. // set it to null and throw an error lazily when it is used.
  743. const option = oldOptions[key];
  744. value =
  745. option &&
  746. (0, _utils.resolve)(newOptions.resolver, {
  747. filePath: option,
  748. key,
  749. optional: option === _Defaults.default[key],
  750. rootDir: options.rootDir
  751. });
  752. }
  753. break;
  754. case 'moduleNameMapper':
  755. const moduleNameMapper = oldOptions[key];
  756. value =
  757. moduleNameMapper &&
  758. Object.keys(moduleNameMapper).map(regex => {
  759. const item = moduleNameMapper && moduleNameMapper[regex];
  760. return (
  761. item && [
  762. regex,
  763. (0, _utils._replaceRootDirTags)(options.rootDir, item)
  764. ]
  765. );
  766. });
  767. break;
  768. case 'transform':
  769. const transform = oldOptions[key];
  770. value =
  771. transform &&
  772. Object.keys(transform).map(regex => {
  773. const transformElement = transform[regex];
  774. return [
  775. regex,
  776. (0, _utils.resolve)(newOptions.resolver, {
  777. filePath: Array.isArray(transformElement)
  778. ? transformElement[0]
  779. : transformElement,
  780. key,
  781. rootDir: options.rootDir
  782. }),
  783. Array.isArray(transformElement) ? transformElement[1] : {}
  784. ];
  785. });
  786. break;
  787. case 'coveragePathIgnorePatterns':
  788. case 'modulePathIgnorePatterns':
  789. case 'testPathIgnorePatterns':
  790. case 'transformIgnorePatterns':
  791. case 'watchPathIgnorePatterns':
  792. case 'unmockedModulePathPatterns':
  793. value = normalizeUnmockedModulePathPatterns(oldOptions, key);
  794. break;
  795. case 'haste':
  796. value = {...oldOptions[key]};
  797. if (value.hasteImplModulePath != null) {
  798. const resolvedHasteImpl = (0, _utils.resolve)(newOptions.resolver, {
  799. filePath: (0, _utils.replaceRootDirInPath)(
  800. options.rootDir,
  801. value.hasteImplModulePath
  802. ),
  803. key: 'haste.hasteImplModulePath',
  804. rootDir: options.rootDir
  805. });
  806. value.hasteImplModulePath = resolvedHasteImpl || undefined;
  807. }
  808. break;
  809. case 'projects':
  810. value = (oldOptions[key] || [])
  811. .map(project =>
  812. typeof project === 'string'
  813. ? (0, _utils._replaceRootDirTags)(options.rootDir, project)
  814. : project
  815. )
  816. .reduce((projects, project) => {
  817. // Project can be specified as globs. If a glob matches any files,
  818. // We expand it to these paths. If not, we keep the original path
  819. // for the future resolution.
  820. const globMatches =
  821. typeof project === 'string' ? (0, _glob().sync)(project) : [];
  822. return projects.concat(globMatches.length ? globMatches : project);
  823. }, []);
  824. break;
  825. case 'moduleDirectories':
  826. case 'testMatch':
  827. {
  828. const replacedRootDirTags = (0, _utils._replaceRootDirTags)(
  829. (0, _utils.escapeGlobCharacters)(options.rootDir),
  830. oldOptions[key]
  831. );
  832. if (replacedRootDirTags) {
  833. value = Array.isArray(replacedRootDirTags)
  834. ? replacedRootDirTags.map(_jestUtil().replacePathSepForGlob)
  835. : (0, _jestUtil().replacePathSepForGlob)(replacedRootDirTags);
  836. } else {
  837. value = replacedRootDirTags;
  838. }
  839. }
  840. break;
  841. case 'testRegex':
  842. {
  843. const option = oldOptions[key];
  844. value = option
  845. ? (Array.isArray(option) ? option : [option]).map(
  846. _jestRegexUtil().replacePathSepForRegex
  847. )
  848. : [];
  849. }
  850. break;
  851. case 'moduleFileExtensions': {
  852. value = oldOptions[key];
  853. if (
  854. Array.isArray(value) && // If it's the wrong type, it can throw at a later time
  855. (options.runner === undefined ||
  856. options.runner === _Defaults.default.runner) && // Only require 'js' for the default jest-runner
  857. !value.includes('js')
  858. ) {
  859. const errorMessage =
  860. " moduleFileExtensions must include 'js':\n" +
  861. ' but instead received:\n' +
  862. ` ${_chalk().default.bold.red(JSON.stringify(value))}`; // If `js` is not included, any dependency Jest itself injects into
  863. // the environment, like jasmine or sourcemap-support, will need to
  864. // `require` its modules with a file extension. This is not plausible
  865. // in the long run, so it's way easier to just fail hard early.
  866. // We might consider throwing if `json` is missing as well, as it's a
  867. // fair assumption from modules that they can do
  868. // `require('some-package/package') without the trailing `.json` as it
  869. // works in Node normally.
  870. throw createConfigError(
  871. errorMessage +
  872. "\n Please change your configuration to include 'js'."
  873. );
  874. }
  875. break;
  876. }
  877. case 'bail': {
  878. const bail = oldOptions[key];
  879. if (typeof bail === 'boolean') {
  880. value = bail ? 1 : 0;
  881. } else if (typeof bail === 'string') {
  882. value = 1; // If Jest is invoked as `jest --bail someTestPattern` then need to
  883. // move the pattern from the `bail` configuration and into `argv._`
  884. // to be processed as an extra parameter
  885. argv._.push(bail);
  886. } else {
  887. value = oldOptions[key];
  888. }
  889. break;
  890. }
  891. case 'displayName': {
  892. const displayName = oldOptions[key];
  893. /**
  894. * Ensuring that displayName shape is correct here so that the
  895. * reporters can trust the shape of the data
  896. */
  897. if (typeof displayName === 'object') {
  898. const {name, color} = displayName;
  899. if (
  900. !name ||
  901. !color ||
  902. typeof name !== 'string' ||
  903. typeof color !== 'string'
  904. ) {
  905. const errorMessage =
  906. ` Option "${_chalk().default.bold(
  907. 'displayName'
  908. )}" must be of type:\n\n` +
  909. ' {\n' +
  910. ' name: string;\n' +
  911. ' color: string;\n' +
  912. ' }\n';
  913. throw createConfigError(errorMessage);
  914. }
  915. value = oldOptions[key];
  916. } else {
  917. value = {
  918. color: (0, _color.getDisplayNameColor)(options.runner),
  919. name: displayName
  920. };
  921. }
  922. break;
  923. }
  924. case 'testTimeout': {
  925. if (oldOptions[key] < 0) {
  926. throw createConfigError(
  927. ` Option "${_chalk().default.bold(
  928. 'testTimeout'
  929. )}" must be a natural number.`
  930. );
  931. }
  932. value = oldOptions[key];
  933. break;
  934. }
  935. case 'automock':
  936. case 'cache':
  937. case 'changedSince':
  938. case 'changedFilesWithAncestor':
  939. case 'clearMocks':
  940. case 'collectCoverage':
  941. case 'coverageProvider':
  942. case 'coverageReporters':
  943. case 'coverageThreshold':
  944. case 'detectLeaks':
  945. case 'detectOpenHandles':
  946. case 'errorOnDeprecated':
  947. case 'expand':
  948. case 'extensionsToTreatAsEsm':
  949. case 'extraGlobals':
  950. case 'globals':
  951. case 'findRelatedTests':
  952. case 'forceCoverageMatch':
  953. case 'forceExit':
  954. case 'injectGlobals':
  955. case 'lastCommit':
  956. case 'listTests':
  957. case 'logHeapUsage':
  958. case 'maxConcurrency':
  959. case 'name':
  960. case 'noStackTrace':
  961. case 'notify':
  962. case 'notifyMode':
  963. case 'onlyChanged':
  964. case 'onlyFailures':
  965. case 'outputFile':
  966. case 'passWithNoTests':
  967. case 'replname':
  968. case 'reporters':
  969. case 'resetMocks':
  970. case 'resetModules':
  971. case 'restoreMocks':
  972. case 'rootDir':
  973. case 'runTestsByPath':
  974. case 'silent':
  975. case 'skipFilter':
  976. case 'skipNodeResolution':
  977. case 'slowTestThreshold':
  978. case 'snapshotFormat':
  979. case 'testEnvironment':
  980. case 'testEnvironmentOptions':
  981. case 'testFailureExitCode':
  982. case 'testLocationInResults':
  983. case 'testNamePattern':
  984. case 'testURL':
  985. case 'timers':
  986. case 'useStderr':
  987. case 'verbose':
  988. case 'watch':
  989. case 'watchAll':
  990. case 'watchman':
  991. value = oldOptions[key];
  992. break;
  993. case 'watchPlugins':
  994. value = (oldOptions[key] || []).map(watchPlugin => {
  995. if (typeof watchPlugin === 'string') {
  996. return {
  997. config: {},
  998. path: (0, _jestResolve().resolveWatchPlugin)(
  999. newOptions.resolver,
  1000. {
  1001. filePath: watchPlugin,
  1002. requireResolveFunction: require.resolve,
  1003. rootDir: options.rootDir
  1004. }
  1005. )
  1006. };
  1007. } else {
  1008. return {
  1009. config: watchPlugin[1] || {},
  1010. path: (0, _jestResolve().resolveWatchPlugin)(
  1011. newOptions.resolver,
  1012. {
  1013. filePath: watchPlugin[0],
  1014. requireResolveFunction: require.resolve,
  1015. rootDir: options.rootDir
  1016. }
  1017. )
  1018. };
  1019. }
  1020. });
  1021. break;
  1022. } // @ts-expect-error: automock is missing in GlobalConfig, so what
  1023. newOptions[key] = value;
  1024. return newOptions;
  1025. }, newOptions);
  1026. if (
  1027. options.watchman &&
  1028. (_options$haste = options.haste) !== null &&
  1029. _options$haste !== void 0 &&
  1030. _options$haste.enableSymlinks
  1031. ) {
  1032. throw new (_jestValidate().ValidationError)(
  1033. 'Validation Error',
  1034. 'haste.enableSymlinks is incompatible with watchman',
  1035. 'Either set haste.enableSymlinks to false or do not use watchman'
  1036. );
  1037. }
  1038. newOptions.roots.forEach((root, i) => {
  1039. verifyDirectoryExists(root, `roots[${i}]`);
  1040. });
  1041. try {
  1042. // try to resolve windows short paths, ignoring errors (permission errors, mostly)
  1043. newOptions.cwd = (0, _jestUtil().tryRealpath)(process.cwd());
  1044. } catch {
  1045. // ignored
  1046. }
  1047. newOptions.testSequencer = (0, _jestResolve().resolveSequencer)(
  1048. newOptions.resolver,
  1049. {
  1050. filePath:
  1051. options.testSequencer ||
  1052. require.resolve(_Defaults.default.testSequencer),
  1053. requireResolveFunction: require.resolve,
  1054. rootDir: options.rootDir
  1055. }
  1056. );
  1057. if (newOptions.runner === _Defaults.default.runner) {
  1058. newOptions.runner = require.resolve(newOptions.runner);
  1059. }
  1060. newOptions.nonFlagArgs =
  1061. (_argv$_ = argv._) === null || _argv$_ === void 0
  1062. ? void 0
  1063. : _argv$_.map(arg => `${arg}`);
  1064. newOptions.testPathPattern = buildTestPathPattern(argv);
  1065. newOptions.json = !!argv.json;
  1066. newOptions.testFailureExitCode = parseInt(newOptions.testFailureExitCode, 10);
  1067. if (
  1068. newOptions.lastCommit ||
  1069. newOptions.changedFilesWithAncestor ||
  1070. newOptions.changedSince
  1071. ) {
  1072. newOptions.onlyChanged = true;
  1073. }
  1074. if (argv.all) {
  1075. newOptions.onlyChanged = false;
  1076. newOptions.onlyFailures = false;
  1077. } else if (newOptions.testPathPattern) {
  1078. // When passing a test path pattern we don't want to only monitor changed
  1079. // files unless `--watch` is also passed.
  1080. newOptions.onlyChanged = newOptions.watch;
  1081. }
  1082. if (!newOptions.onlyChanged) {
  1083. newOptions.onlyChanged = false;
  1084. }
  1085. if (!newOptions.lastCommit) {
  1086. newOptions.lastCommit = false;
  1087. }
  1088. if (!newOptions.onlyFailures) {
  1089. newOptions.onlyFailures = false;
  1090. }
  1091. if (!newOptions.watchAll) {
  1092. newOptions.watchAll = false;
  1093. } // as unknown since it can happen. We really need to fix the types here
  1094. if (newOptions.moduleNameMapper === _Defaults.default.moduleNameMapper) {
  1095. newOptions.moduleNameMapper = [];
  1096. }
  1097. newOptions.updateSnapshot =
  1098. argv.ci && !argv.updateSnapshot
  1099. ? 'none'
  1100. : argv.updateSnapshot
  1101. ? 'all'
  1102. : 'new';
  1103. newOptions.maxConcurrency = parseInt(newOptions.maxConcurrency, 10);
  1104. newOptions.maxWorkers = (0, _getMaxWorkers.default)(argv, options);
  1105. if (newOptions.testRegex.length && options.testMatch) {
  1106. throw createConfigError(
  1107. ` Configuration options ${_chalk().default.bold('testMatch')} and` +
  1108. ` ${_chalk().default.bold('testRegex')} cannot be used together.`
  1109. );
  1110. }
  1111. if (newOptions.testRegex.length && !options.testMatch) {
  1112. // Prevent the default testMatch conflicting with any explicitly
  1113. // configured `testRegex` value
  1114. newOptions.testMatch = [];
  1115. } // If argv.json is set, coverageReporters shouldn't print a text report.
  1116. if (argv.json) {
  1117. newOptions.coverageReporters = (newOptions.coverageReporters || []).filter(
  1118. reporter => reporter !== 'text'
  1119. );
  1120. } // If collectCoverage is enabled while using --findRelatedTests we need to
  1121. // avoid having false negatives in the generated coverage report.
  1122. // The following: `--findRelatedTests '/rootDir/file1.js' --coverage`
  1123. // Is transformed to: `--findRelatedTests '/rootDir/file1.js' --coverage --collectCoverageFrom 'file1.js'`
  1124. // where arguments to `--collectCoverageFrom` should be globs (or relative
  1125. // paths to the rootDir)
  1126. if (newOptions.collectCoverage && argv.findRelatedTests) {
  1127. let collectCoverageFrom = newOptions.nonFlagArgs.map(filename => {
  1128. filename = (0, _utils.replaceRootDirInPath)(options.rootDir, filename);
  1129. return path().isAbsolute(filename)
  1130. ? path().relative(options.rootDir, filename)
  1131. : filename;
  1132. }); // Don't override existing collectCoverageFrom options
  1133. if (newOptions.collectCoverageFrom) {
  1134. collectCoverageFrom = collectCoverageFrom.reduce((patterns, filename) => {
  1135. if (
  1136. (0, _micromatch().default)(
  1137. [
  1138. (0, _jestUtil().replacePathSepForGlob)(
  1139. path().relative(options.rootDir, filename)
  1140. )
  1141. ],
  1142. newOptions.collectCoverageFrom
  1143. ).length === 0
  1144. ) {
  1145. return patterns;
  1146. }
  1147. return [...patterns, filename];
  1148. }, newOptions.collectCoverageFrom);
  1149. }
  1150. newOptions.collectCoverageFrom = collectCoverageFrom;
  1151. } else if (!newOptions.collectCoverageFrom) {
  1152. newOptions.collectCoverageFrom = [];
  1153. }
  1154. if (!newOptions.findRelatedTests) {
  1155. newOptions.findRelatedTests = false;
  1156. }
  1157. if (!newOptions.projects) {
  1158. newOptions.projects = [];
  1159. }
  1160. if (!newOptions.extraGlobals) {
  1161. newOptions.extraGlobals = [];
  1162. }
  1163. if (!newOptions.forceExit) {
  1164. newOptions.forceExit = false;
  1165. }
  1166. if (!newOptions.logHeapUsage) {
  1167. newOptions.logHeapUsage = false;
  1168. }
  1169. return {
  1170. hasDeprecationWarnings,
  1171. options: newOptions
  1172. };
  1173. }