normalize.js 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567
  1. 'use strict';
  2. Object.defineProperty(exports, "__esModule", {
  3. value: true
  4. });
  5. exports.default = normalize;
  6. var _crypto;
  7. function _load_crypto() {
  8. return _crypto = _interopRequireDefault(require('crypto'));
  9. }
  10. var _glob;
  11. function _load_glob() {
  12. return _glob = _interopRequireDefault(require('glob'));
  13. }
  14. var _path;
  15. function _load_path() {
  16. return _path = _interopRequireDefault(require('path'));
  17. }
  18. var _jestValidate;
  19. function _load_jestValidate() {
  20. return _jestValidate = require('jest-validate');
  21. }
  22. var _validate_pattern;
  23. function _load_validate_pattern() {
  24. return _validate_pattern = _interopRequireDefault(require('./validate_pattern'));
  25. }
  26. var _jestUtil;
  27. function _load_jestUtil() {
  28. return _jestUtil = require('jest-util');
  29. }
  30. var _chalk;
  31. function _load_chalk() {
  32. return _chalk = _interopRequireDefault(require('chalk'));
  33. }
  34. var _get_max_workers;
  35. function _load_get_max_workers() {
  36. return _get_max_workers = _interopRequireDefault(require('./get_max_workers'));
  37. }
  38. var _jestResolve;
  39. function _load_jestResolve() {
  40. return _jestResolve = _interopRequireDefault(require('jest-resolve'));
  41. }
  42. var _jestRegexUtil;
  43. function _load_jestRegexUtil() {
  44. return _jestRegexUtil = require('jest-regex-util');
  45. }
  46. var _utils;
  47. function _load_utils() {
  48. return _utils = require('./utils');
  49. }
  50. var _constants;
  51. function _load_constants() {
  52. return _constants = require('./constants');
  53. }
  54. var _reporter_validation_errors;
  55. function _load_reporter_validation_errors() {
  56. return _reporter_validation_errors = require('./reporter_validation_errors');
  57. }
  58. var _defaults;
  59. function _load_defaults() {
  60. return _defaults = _interopRequireDefault(require('./defaults'));
  61. }
  62. var _deprecated;
  63. function _load_deprecated() {
  64. return _deprecated = _interopRequireDefault(require('./deprecated'));
  65. }
  66. var _set_from_argv;
  67. function _load_set_from_argv() {
  68. return _set_from_argv = _interopRequireDefault(require('./set_from_argv'));
  69. }
  70. var _valid_config;
  71. function _load_valid_config() {
  72. return _valid_config = _interopRequireDefault(require('./valid_config'));
  73. }
  74. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
  75. function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) arr2[i] = arr[i]; return arr2; } else { return Array.from(arr); } } /**
  76. * Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
  77. *
  78. * This source code is licensed under the MIT license found in the
  79. * LICENSE file in the root directory of this source tree.
  80. *
  81. *
  82. */
  83. const ERROR = `${(_utils || _load_utils()).BULLET}Validation Error`;
  84. const JSON_EXTENSION = '.json';
  85. const PRESET_NAME = 'jest-preset' + JSON_EXTENSION;
  86. const createConfigError = message => new (_jestValidate || _load_jestValidate()).ValidationError(ERROR, message, (_utils || _load_utils()).DOCUMENTATION_NOTE);
  87. const mergeOptionWithPreset = (options, preset, optionName) => {
  88. if (options[optionName] && preset[optionName]) {
  89. options[optionName] = Object.assign({}, options[optionName], preset[optionName], options[optionName]);
  90. }
  91. };
  92. const setupPreset = (options, optionsPreset) => {
  93. let preset;
  94. const presetPath = (0, (_utils || _load_utils())._replaceRootDirInPath)(options.rootDir, optionsPreset);
  95. const presetModule = (_jestResolve || _load_jestResolve()).default.findNodeModule(presetPath.endsWith(JSON_EXTENSION) ? presetPath : (_path || _load_path()).default.join(presetPath, PRESET_NAME), {
  96. basedir: options.rootDir
  97. });
  98. try {
  99. // $FlowFixMe
  100. preset = require(presetModule);
  101. } catch (error) {
  102. if (error instanceof SyntaxError) {
  103. throw createConfigError(` Preset ${(_chalk || _load_chalk()).default.bold(presetPath)} is invalid:\n ${error.message}`);
  104. }
  105. throw createConfigError(` Preset ${(_chalk || _load_chalk()).default.bold(presetPath)} not found.`);
  106. }
  107. if (options.setupFiles) {
  108. options.setupFiles = (preset.setupFiles || []).concat(options.setupFiles);
  109. }
  110. if (options.modulePathIgnorePatterns && preset.modulePathIgnorePatterns) {
  111. options.modulePathIgnorePatterns = preset.modulePathIgnorePatterns.concat(options.modulePathIgnorePatterns);
  112. }
  113. mergeOptionWithPreset(options, preset, 'moduleNameMapper');
  114. mergeOptionWithPreset(options, preset, 'transform');
  115. return Object.assign({}, preset, options);
  116. };
  117. const setupBabelJest = options => {
  118. const basedir = options.rootDir;
  119. const transform = options.transform;
  120. let babelJest;
  121. if (transform) {
  122. const customJSPattern = Object.keys(transform).find(pattern => {
  123. const regex = new RegExp(pattern);
  124. return regex.test('a.js') || regex.test('a.jsx');
  125. });
  126. if (customJSPattern) {
  127. const jsTransformer = (_jestResolve || _load_jestResolve()).default.findNodeModule(transform[customJSPattern], { basedir });
  128. if (jsTransformer && jsTransformer.includes((_constants || _load_constants()).NODE_MODULES + 'babel-jest')) {
  129. babelJest = jsTransformer;
  130. }
  131. }
  132. } else {
  133. babelJest = (_jestResolve || _load_jestResolve()).default.findNodeModule('babel-jest', { basedir });
  134. if (babelJest) {
  135. options.transform = {
  136. [(_constants || _load_constants()).DEFAULT_JS_PATTERN]: 'babel-jest'
  137. };
  138. }
  139. }
  140. return babelJest;
  141. };
  142. const normalizeCollectCoverageOnlyFrom = (options, key) => {
  143. const collectCoverageOnlyFrom = Array.isArray(options[key]) ? options[key] // passed from argv
  144. : Object.keys(options[key]); // passed from options
  145. return collectCoverageOnlyFrom.reduce((map, filePath) => {
  146. filePath = (_path || _load_path()).default.resolve(options.rootDir, (0, (_utils || _load_utils())._replaceRootDirInPath)(options.rootDir, filePath));
  147. map[filePath] = true;
  148. return map;
  149. }, Object.create(null));
  150. };
  151. const normalizeCollectCoverageFrom = (options, key) => {
  152. let value;
  153. if (!options[key]) {
  154. value = [];
  155. }
  156. if (!Array.isArray(options[key])) {
  157. try {
  158. value = JSON.parse(options[key]);
  159. } catch (e) {}
  160. Array.isArray(value) || (value = [options[key]]);
  161. } else {
  162. value = options[key];
  163. }
  164. if (value) {
  165. value = value.map(filePath => {
  166. return filePath.replace(/^(!?)(<rootDir>\/)(.*)/, '$1$3');
  167. });
  168. }
  169. return value;
  170. };
  171. const normalizeUnmockedModulePathPatterns = (options, key) => {
  172. // _replaceRootDirTags is specifically well-suited for substituting
  173. // <rootDir> in paths (it deals with properly interpreting relative path
  174. // separators, etc).
  175. //
  176. // For patterns, direct global substitution is far more ideal, so we
  177. // special case substitutions for patterns here.
  178. return options[key].map(pattern => (0, (_jestRegexUtil || _load_jestRegexUtil()).replacePathSepForRegex)(pattern.replace(/<rootDir>/g, options.rootDir)));
  179. };
  180. const normalizePreprocessor = options => {
  181. if (options.scriptPreprocessor && options.transform) {
  182. throw createConfigError(` Options: ${(_chalk || _load_chalk()).default.bold('scriptPreprocessor')} and ${(_chalk || _load_chalk()).default.bold('transform')} cannot be used together.
  183. Please change your configuration to only use ${(_chalk || _load_chalk()).default.bold('transform')}.`);
  184. }
  185. if (options.preprocessorIgnorePatterns && options.transformIgnorePatterns) {
  186. throw createConfigError(` Options ${(_chalk || _load_chalk()).default.bold('preprocessorIgnorePatterns')} and ${(_chalk || _load_chalk()).default.bold('transformIgnorePatterns')} cannot be used together.
  187. Please change your configuration to only use ${(_chalk || _load_chalk()).default.bold('transformIgnorePatterns')}.`);
  188. }
  189. if (options.scriptPreprocessor) {
  190. options.transform = {
  191. '.*': options.scriptPreprocessor
  192. };
  193. }
  194. if (options.preprocessorIgnorePatterns) {
  195. options.transformIgnorePatterns = options.preprocessorIgnorePatterns;
  196. }
  197. delete options.scriptPreprocessor;
  198. delete options.preprocessorIgnorePatterns;
  199. return options;
  200. };
  201. const normalizeMissingOptions = options => {
  202. if (!options.name) {
  203. options.name = (_crypto || _load_crypto()).default.createHash('md5').update(options.rootDir).digest('hex');
  204. }
  205. if (!options.setupFiles) {
  206. options.setupFiles = [];
  207. }
  208. return options;
  209. };
  210. const normalizeRootDir = options => {
  211. // Assert that there *is* a rootDir
  212. if (!options.hasOwnProperty('rootDir')) {
  213. throw createConfigError(` Configuration option ${(_chalk || _load_chalk()).default.bold('rootDir')} must be specified.`);
  214. }
  215. options.rootDir = (_path || _load_path()).default.normalize(options.rootDir);
  216. return options;
  217. };
  218. const normalizeReporters = (options, basedir) => {
  219. const reporters = options.reporters;
  220. if (!reporters || !Array.isArray(reporters)) {
  221. return options;
  222. }
  223. (0, (_reporter_validation_errors || _load_reporter_validation_errors()).validateReporters)(reporters);
  224. options.reporters = reporters.map(reporterConfig => {
  225. const normalizedReporterConfig = typeof reporterConfig === 'string' ? // if reporter config is a string, we wrap it in an array
  226. // and pass an empty object for options argument, to normalize
  227. // the shape.
  228. [reporterConfig, {}] : reporterConfig;
  229. const reporterPath = (0, (_utils || _load_utils())._replaceRootDirInPath)(options.rootDir, normalizedReporterConfig[0]);
  230. if (reporterPath !== (_constants || _load_constants()).DEFAULT_REPORTER_LABEL) {
  231. const reporter = (_jestResolve || _load_jestResolve()).default.findNodeModule(reporterPath, {
  232. basedir: options.rootDir
  233. });
  234. if (!reporter) {
  235. throw new Error(`Could not resolve a module for a custom reporter.\n` + ` Module name: ${reporterPath}`);
  236. }
  237. normalizedReporterConfig[0] = reporter;
  238. }
  239. return normalizedReporterConfig;
  240. });
  241. return options;
  242. };
  243. const buildTestPathPattern = argv => {
  244. const patterns = [];
  245. if (argv._) {
  246. patterns.push.apply(patterns, _toConsumableArray(argv._));
  247. }
  248. if (argv.testPathPattern) {
  249. patterns.push.apply(patterns, _toConsumableArray(argv.testPathPattern));
  250. }
  251. const replacePosixSep = pattern => {
  252. if ((_path || _load_path()).default.sep === '/') {
  253. return pattern;
  254. }
  255. return pattern.replace(/\//g, '\\\\');
  256. };
  257. const testPathPattern = patterns.map(replacePosixSep).join('|');
  258. if ((0, (_validate_pattern || _load_validate_pattern()).default)(testPathPattern)) {
  259. return testPathPattern;
  260. } else {
  261. showTestPathPatternError(testPathPattern);
  262. return '';
  263. }
  264. };
  265. const showTestPathPatternError = testPathPattern => {
  266. (0, (_jestUtil || _load_jestUtil()).clearLine)(process.stdout);
  267. console.log((_chalk || _load_chalk()).default.red(` Invalid testPattern ${testPathPattern} supplied. ` + `Running all tests instead.`));
  268. };
  269. function normalize(options, argv) {
  270. var _validate = (0, (_jestValidate || _load_jestValidate()).validate)(options, {
  271. comment: (_utils || _load_utils()).DOCUMENTATION_NOTE,
  272. deprecatedConfig: (_deprecated || _load_deprecated()).default,
  273. exampleConfig: (_valid_config || _load_valid_config()).default
  274. });
  275. const hasDeprecationWarnings = _validate.hasDeprecationWarnings;
  276. options = normalizePreprocessor(normalizeReporters(normalizeMissingOptions(normalizeRootDir((0, (_set_from_argv || _load_set_from_argv()).default)(options, argv)))));
  277. if (options.preset) {
  278. options = setupPreset(options, options.preset);
  279. }
  280. if (options.testEnvironment) {
  281. options.testEnvironment = (0, (_utils || _load_utils()).getTestEnvironment)(options);
  282. }
  283. if (!options.roots && options.testPathDirs) {
  284. options.roots = options.testPathDirs;
  285. delete options.testPathDirs;
  286. }
  287. if (!options.roots) {
  288. options.roots = [options.rootDir];
  289. }
  290. if (!options.testRunner || options.testRunner === 'jasmine2') {
  291. options.testRunner = require.resolve('jest-jasmine2');
  292. }
  293. if (!options.coverageDirectory) {
  294. options.coverageDirectory = (_path || _load_path()).default.resolve(options.rootDir, 'coverage');
  295. }
  296. const babelJest = setupBabelJest(options);
  297. const newOptions = Object.assign({}, (_defaults || _load_defaults()).default);
  298. // Cast back to exact type
  299. options = options;
  300. Object.keys(options).reduce((newOptions, key) => {
  301. let value;
  302. switch (key) {
  303. case 'collectCoverageOnlyFrom':
  304. value = normalizeCollectCoverageOnlyFrom(options, key);
  305. break;
  306. case 'setupFiles':
  307. case 'snapshotSerializers':
  308. value = options[key] && options[key].map((_utils || _load_utils()).resolve.bind(null, options.rootDir, key));
  309. break;
  310. case 'modulePaths':
  311. case 'roots':
  312. value = options[key] && options[key].map(filePath => (_path || _load_path()).default.resolve(options.rootDir, (0, (_utils || _load_utils())._replaceRootDirInPath)(options.rootDir, filePath)));
  313. break;
  314. case 'collectCoverageFrom':
  315. value = normalizeCollectCoverageFrom(options, key);
  316. break;
  317. case 'cacheDirectory':
  318. case 'coverageDirectory':
  319. value = options[key] && (_path || _load_path()).default.resolve(options.rootDir, (0, (_utils || _load_utils())._replaceRootDirInPath)(options.rootDir, options[key]));
  320. break;
  321. case 'globalSetup':
  322. case 'globalTeardown':
  323. case 'moduleLoader':
  324. case 'resolver':
  325. case 'runner':
  326. case 'setupTestFrameworkScriptFile':
  327. case 'testResultsProcessor':
  328. case 'testRunner':
  329. value = options[key] && (0, (_utils || _load_utils()).resolve)(options.rootDir, key, options[key]);
  330. break;
  331. case 'moduleNameMapper':
  332. const moduleNameMapper = options[key];
  333. value = moduleNameMapper && Object.keys(moduleNameMapper).map(regex => {
  334. const item = moduleNameMapper && moduleNameMapper[regex];
  335. return item && [regex, (0, (_utils || _load_utils())._replaceRootDirTags)(options.rootDir, item)];
  336. });
  337. break;
  338. case 'transform':
  339. const transform = options[key];
  340. value = transform && Object.keys(transform).map(regex => [regex, (0, (_utils || _load_utils()).resolve)(options.rootDir, key, transform[regex])]);
  341. break;
  342. case 'coveragePathIgnorePatterns':
  343. case 'modulePathIgnorePatterns':
  344. case 'testPathIgnorePatterns':
  345. case 'transformIgnorePatterns':
  346. case 'watchPathIgnorePatterns':
  347. case 'unmockedModulePathPatterns':
  348. value = normalizeUnmockedModulePathPatterns(options, key);
  349. break;
  350. case 'haste':
  351. value = Object.assign({}, options[key]);
  352. if (value.hasteImplModulePath != null) {
  353. value.hasteImplModulePath = (0, (_utils || _load_utils()).resolve)(options.rootDir, 'haste.hasteImplModulePath', (0, (_utils || _load_utils())._replaceRootDirInPath)(options.rootDir, value.hasteImplModulePath));
  354. }
  355. break;
  356. case 'projects':
  357. value = (options[key] || []).map(project => (0, (_utils || _load_utils())._replaceRootDirTags)(options.rootDir, project)).reduce((projects, project) => {
  358. // Project can be specified as globs. If a glob matches any files,
  359. // We expand it to these paths. If not, we keep the original path
  360. // for the future resolution.
  361. const globMatches = typeof project === 'string' ? (_glob || _load_glob()).default.sync(project) : [];
  362. return projects.concat(globMatches.length ? globMatches : project);
  363. }, []);
  364. break;
  365. case 'moduleDirectories':
  366. case 'testMatch':
  367. value = (0, (_utils || _load_utils())._replaceRootDirTags)((0, (_utils || _load_utils()).escapeGlobCharacters)(options.rootDir), options[key]);
  368. break;
  369. case 'testRegex':
  370. value = options[key] && (0, (_jestRegexUtil || _load_jestRegexUtil()).replacePathSepForRegex)(options[key]);
  371. break;
  372. case 'automock':
  373. case 'bail':
  374. case 'browser':
  375. case 'cache':
  376. case 'changedSince':
  377. case 'changedFilesWithAncestor':
  378. case 'clearMocks':
  379. case 'collectCoverage':
  380. case 'coverageReporters':
  381. case 'coverageThreshold':
  382. case 'detectLeaks':
  383. case 'displayName':
  384. case 'expand':
  385. case 'globals':
  386. case 'findRelatedTests':
  387. case 'forceCoverageMatch':
  388. case 'forceExit':
  389. case 'lastCommit':
  390. case 'listTests':
  391. case 'logHeapUsage':
  392. case 'mapCoverage':
  393. case 'moduleFileExtensions':
  394. case 'name':
  395. case 'noStackTrace':
  396. case 'notify':
  397. case 'notifyMode':
  398. case 'onlyChanged':
  399. case 'outputFile':
  400. case 'passWithNoTests':
  401. case 'replname':
  402. case 'reporters':
  403. case 'resetMocks':
  404. case 'resetModules':
  405. case 'restoreMocks':
  406. case 'rootDir':
  407. case 'runTestsByPath':
  408. case 'silent':
  409. case 'skipNodeResolution':
  410. case 'testEnvironment':
  411. case 'testEnvironmentOptions':
  412. case 'testFailureExitCode':
  413. case 'testLocationInResults':
  414. case 'testNamePattern':
  415. case 'testURL':
  416. case 'timers':
  417. case 'useStderr':
  418. case 'verbose':
  419. case 'watch':
  420. case 'watchAll':
  421. case 'watchman':
  422. value = options[key];
  423. break;
  424. case 'watchPlugins':
  425. value = (options[key] || []).map(watchPlugin => (0, (_utils || _load_utils()).resolve)(options.rootDir, key, watchPlugin));
  426. break;
  427. }
  428. newOptions[key] = value;
  429. return newOptions;
  430. }, newOptions);
  431. newOptions.nonFlagArgs = argv._;
  432. newOptions.testPathPattern = buildTestPathPattern(argv);
  433. newOptions.json = argv.json;
  434. newOptions.testFailureExitCode = parseInt(newOptions.testFailureExitCode, 10);
  435. for (const key of ['lastCommit', 'changedFilesWithAncestor', 'changedSince']) {
  436. if (newOptions[key]) {
  437. newOptions.onlyChanged = true;
  438. }
  439. }
  440. if (argv.all) {
  441. newOptions.onlyChanged = false;
  442. } else if (newOptions.testPathPattern) {
  443. // When passing a test path pattern we don't want to only monitor changed
  444. // files unless `--watch` is also passed.
  445. newOptions.onlyChanged = newOptions.watch;
  446. }
  447. newOptions.updateSnapshot = argv.ci && !argv.updateSnapshot ? 'none' : argv.updateSnapshot ? 'all' : 'new';
  448. newOptions.maxWorkers = (0, (_get_max_workers || _load_get_max_workers()).default)(argv);
  449. if (babelJest) {
  450. const regeneratorRuntimePath = (_jestResolve || _load_jestResolve()).default.findNodeModule('regenerator-runtime/runtime', { basedir: options.rootDir });
  451. if (regeneratorRuntimePath) {
  452. newOptions.setupFiles.unshift(regeneratorRuntimePath);
  453. }
  454. }
  455. if (options.testRegex && options.testMatch) {
  456. throw createConfigError(` Configuration options ${(_chalk || _load_chalk()).default.bold('testMatch')} and` + ` ${(_chalk || _load_chalk()).default.bold('testRegex')} cannot be used together.`);
  457. }
  458. if (options.testRegex && !options.testMatch) {
  459. // Prevent the default testMatch conflicting with any explicitly
  460. // configured `testRegex` value
  461. newOptions.testMatch = [];
  462. }
  463. // If argv.json is set, coverageReporters shouldn't print a text report.
  464. if (argv.json) {
  465. newOptions.coverageReporters = (newOptions.coverageReporters || []).filter(reporter => reporter !== 'text');
  466. }
  467. return {
  468. hasDeprecationWarnings,
  469. options: newOptions
  470. };
  471. }