normalize.js 31 KB

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