index.js 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440
  1. 'use strict';
  2. Object.defineProperty(exports, '__esModule', {
  3. value: true
  4. });
  5. exports.readConfig = readConfig;
  6. exports.readConfigs = readConfigs;
  7. Object.defineProperty(exports, 'getTestEnvironment', {
  8. enumerable: true,
  9. get: function get() {
  10. return _utils.getTestEnvironment;
  11. }
  12. });
  13. Object.defineProperty(exports, 'isJSONString', {
  14. enumerable: true,
  15. get: function get() {
  16. return _utils.isJSONString;
  17. }
  18. });
  19. Object.defineProperty(exports, 'replaceRootDirInPath', {
  20. enumerable: true,
  21. get: function get() {
  22. return _utils.replaceRootDirInPath;
  23. }
  24. });
  25. Object.defineProperty(exports, 'normalize', {
  26. enumerable: true,
  27. get: function get() {
  28. return _normalize2.default;
  29. }
  30. });
  31. Object.defineProperty(exports, 'deprecationEntries', {
  32. enumerable: true,
  33. get: function get() {
  34. return _Deprecated.default;
  35. }
  36. });
  37. Object.defineProperty(exports, 'defaults', {
  38. enumerable: true,
  39. get: function get() {
  40. return _Defaults.default;
  41. }
  42. });
  43. Object.defineProperty(exports, 'descriptions', {
  44. enumerable: true,
  45. get: function get() {
  46. return _Descriptions.default;
  47. }
  48. });
  49. function _fs() {
  50. const data = _interopRequireDefault(require('fs'));
  51. _fs = function _fs() {
  52. return data;
  53. };
  54. return data;
  55. }
  56. function _path() {
  57. const data = _interopRequireDefault(require('path'));
  58. _path = function _path() {
  59. return data;
  60. };
  61. return data;
  62. }
  63. function _chalk() {
  64. const data = _interopRequireDefault(require('chalk'));
  65. _chalk = function _chalk() {
  66. return data;
  67. };
  68. return data;
  69. }
  70. var _utils = require('./utils');
  71. var _normalize2 = _interopRequireDefault(require('./normalize'));
  72. var _resolveConfigPath = _interopRequireDefault(require('./resolveConfigPath'));
  73. var _readConfigFileAndSetRootDir = _interopRequireDefault(
  74. require('./readConfigFileAndSetRootDir')
  75. );
  76. var _Deprecated = _interopRequireDefault(require('./Deprecated'));
  77. var _Defaults = _interopRequireDefault(require('./Defaults'));
  78. var _Descriptions = _interopRequireDefault(require('./Descriptions'));
  79. function _interopRequireDefault(obj) {
  80. return obj && obj.__esModule ? obj : {default: obj};
  81. }
  82. /**
  83. * Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
  84. *
  85. * This source code is licensed under the MIT license found in the
  86. * LICENSE file in the root directory of this source tree.
  87. */
  88. function readConfig(
  89. argv,
  90. packageRootOrConfig, // Whether it needs to look into `--config` arg passed to CLI.
  91. // It only used to read initial config. If the initial config contains
  92. // `project` property, we don't want to read `--config` value and rather
  93. skipArgvConfigOption,
  94. parentConfigPath,
  95. projectIndex = Infinity
  96. ) {
  97. let rawOptions;
  98. let configPath = null;
  99. if (typeof packageRootOrConfig !== 'string') {
  100. if (parentConfigPath) {
  101. const parentConfigDirname = _path().default.dirname(parentConfigPath);
  102. rawOptions = packageRootOrConfig;
  103. rawOptions.rootDir = rawOptions.rootDir
  104. ? (0, _utils.replaceRootDirInPath)(
  105. parentConfigDirname,
  106. rawOptions.rootDir
  107. )
  108. : parentConfigDirname;
  109. } else {
  110. throw new Error(
  111. 'Jest: Cannot use configuration as an object without a file path.'
  112. );
  113. }
  114. } else if ((0, _utils.isJSONString)(argv.config)) {
  115. // A JSON string was passed to `--config` argument and we can parse it
  116. // and use as is.
  117. let config;
  118. try {
  119. config = JSON.parse(argv.config);
  120. } catch (e) {
  121. throw new Error(
  122. 'There was an error while parsing the `--config` argument as a JSON string.'
  123. );
  124. } // NOTE: we might need to resolve this dir to an absolute path in the future
  125. config.rootDir = config.rootDir || packageRootOrConfig;
  126. rawOptions = config; // A string passed to `--config`, which is either a direct path to the config
  127. // or a path to directory containing `package.json` or `jest.config.js`
  128. } else if (!skipArgvConfigOption && typeof argv.config == 'string') {
  129. configPath = (0, _resolveConfigPath.default)(argv.config, process.cwd());
  130. rawOptions = (0, _readConfigFileAndSetRootDir.default)(configPath);
  131. } else {
  132. // Otherwise just try to find config in the current rootDir.
  133. configPath = (0, _resolveConfigPath.default)(
  134. packageRootOrConfig,
  135. process.cwd()
  136. );
  137. rawOptions = (0, _readConfigFileAndSetRootDir.default)(configPath);
  138. }
  139. const _normalize = (0, _normalize2.default)(
  140. rawOptions,
  141. argv,
  142. configPath,
  143. projectIndex
  144. ),
  145. options = _normalize.options,
  146. hasDeprecationWarnings = _normalize.hasDeprecationWarnings;
  147. const _groupOptions = groupOptions(options),
  148. globalConfig = _groupOptions.globalConfig,
  149. projectConfig = _groupOptions.projectConfig;
  150. return {
  151. configPath,
  152. globalConfig,
  153. hasDeprecationWarnings,
  154. projectConfig
  155. };
  156. }
  157. const groupOptions = options => ({
  158. globalConfig: Object.freeze({
  159. bail: options.bail,
  160. changedFilesWithAncestor: options.changedFilesWithAncestor,
  161. changedSince: options.changedSince,
  162. collectCoverage: options.collectCoverage,
  163. collectCoverageFrom: options.collectCoverageFrom,
  164. collectCoverageOnlyFrom: options.collectCoverageOnlyFrom,
  165. coverageDirectory: options.coverageDirectory,
  166. coverageReporters: options.coverageReporters,
  167. coverageThreshold: options.coverageThreshold,
  168. detectLeaks: options.detectLeaks,
  169. detectOpenHandles: options.detectOpenHandles,
  170. enabledTestsMap: options.enabledTestsMap,
  171. errorOnDeprecated: options.errorOnDeprecated,
  172. expand: options.expand,
  173. extraGlobals: options.extraGlobals,
  174. filter: options.filter,
  175. findRelatedTests: options.findRelatedTests,
  176. forceExit: options.forceExit,
  177. globalSetup: options.globalSetup,
  178. globalTeardown: options.globalTeardown,
  179. json: options.json,
  180. lastCommit: options.lastCommit,
  181. listTests: options.listTests,
  182. logHeapUsage: options.logHeapUsage,
  183. maxConcurrency: options.maxConcurrency,
  184. maxWorkers: options.maxWorkers,
  185. noSCM: undefined,
  186. noStackTrace: options.noStackTrace,
  187. nonFlagArgs: options.nonFlagArgs,
  188. notify: options.notify,
  189. notifyMode: options.notifyMode,
  190. onlyChanged: options.onlyChanged,
  191. onlyFailures: options.onlyFailures,
  192. outputFile: options.outputFile,
  193. passWithNoTests: options.passWithNoTests,
  194. projects: options.projects,
  195. replname: options.replname,
  196. reporters: options.reporters,
  197. rootDir: options.rootDir,
  198. runTestsByPath: options.runTestsByPath,
  199. silent: options.silent,
  200. skipFilter: options.skipFilter,
  201. testFailureExitCode: options.testFailureExitCode,
  202. testNamePattern: options.testNamePattern,
  203. testPathPattern: options.testPathPattern,
  204. testResultsProcessor: options.testResultsProcessor,
  205. testSequencer: options.testSequencer,
  206. testTimeout: options.testTimeout,
  207. updateSnapshot: options.updateSnapshot,
  208. useStderr: options.useStderr,
  209. verbose: options.verbose,
  210. watch: options.watch,
  211. watchAll: options.watchAll,
  212. watchPlugins: options.watchPlugins,
  213. watchman: options.watchman
  214. }),
  215. projectConfig: Object.freeze({
  216. automock: options.automock,
  217. browser: options.browser,
  218. cache: options.cache,
  219. cacheDirectory: options.cacheDirectory,
  220. clearMocks: options.clearMocks,
  221. coveragePathIgnorePatterns: options.coveragePathIgnorePatterns,
  222. cwd: options.cwd,
  223. dependencyExtractor: options.dependencyExtractor,
  224. detectLeaks: options.detectLeaks,
  225. detectOpenHandles: options.detectOpenHandles,
  226. displayName: options.displayName,
  227. errorOnDeprecated: options.errorOnDeprecated,
  228. extraGlobals: options.extraGlobals,
  229. filter: options.filter,
  230. forceCoverageMatch: options.forceCoverageMatch,
  231. globalSetup: options.globalSetup,
  232. globalTeardown: options.globalTeardown,
  233. globals: options.globals,
  234. haste: options.haste,
  235. moduleDirectories: options.moduleDirectories,
  236. moduleFileExtensions: options.moduleFileExtensions,
  237. moduleLoader: options.moduleLoader,
  238. moduleNameMapper: options.moduleNameMapper,
  239. modulePathIgnorePatterns: options.modulePathIgnorePatterns,
  240. modulePaths: options.modulePaths,
  241. name: options.name,
  242. prettierPath: options.prettierPath,
  243. resetMocks: options.resetMocks,
  244. resetModules: options.resetModules,
  245. resolver: options.resolver,
  246. restoreMocks: options.restoreMocks,
  247. rootDir: options.rootDir,
  248. roots: options.roots,
  249. runner: options.runner,
  250. setupFiles: options.setupFiles,
  251. setupFilesAfterEnv: options.setupFilesAfterEnv,
  252. skipFilter: options.skipFilter,
  253. skipNodeResolution: options.skipNodeResolution,
  254. snapshotResolver: options.snapshotResolver,
  255. snapshotSerializers: options.snapshotSerializers,
  256. testEnvironment: options.testEnvironment,
  257. testEnvironmentOptions: options.testEnvironmentOptions,
  258. testLocationInResults: options.testLocationInResults,
  259. testMatch: options.testMatch,
  260. testPathIgnorePatterns: options.testPathIgnorePatterns,
  261. testRegex: options.testRegex,
  262. testRunner: options.testRunner,
  263. testURL: options.testURL,
  264. timers: options.timers,
  265. transform: options.transform,
  266. transformIgnorePatterns: options.transformIgnorePatterns,
  267. unmockedModulePathPatterns: options.unmockedModulePathPatterns,
  268. watchPathIgnorePatterns: options.watchPathIgnorePatterns
  269. })
  270. });
  271. const ensureNoDuplicateConfigs = (parsedConfigs, projects) => {
  272. if (projects.length <= 1) {
  273. return;
  274. }
  275. const configPathMap = new Map();
  276. var _iteratorNormalCompletion = true;
  277. var _didIteratorError = false;
  278. var _iteratorError = undefined;
  279. try {
  280. for (
  281. var _iterator = parsedConfigs[Symbol.iterator](), _step;
  282. !(_iteratorNormalCompletion = (_step = _iterator.next()).done);
  283. _iteratorNormalCompletion = true
  284. ) {
  285. const config = _step.value;
  286. const configPath = config.configPath;
  287. if (configPathMap.has(configPath)) {
  288. const message = `Whoops! Two projects resolved to the same config path: ${_chalk().default.bold(
  289. String(configPath)
  290. )}:
  291. Project 1: ${_chalk().default.bold(
  292. projects[parsedConfigs.findIndex(x => x === config)]
  293. )}
  294. Project 2: ${_chalk().default.bold(
  295. projects[parsedConfigs.findIndex(x => x === configPathMap.get(configPath))]
  296. )}
  297. This usually means that your ${_chalk().default.bold(
  298. '"projects"'
  299. )} config includes a directory that doesn't have any configuration recognizable by Jest. Please fix it.
  300. `;
  301. throw new Error(message);
  302. }
  303. if (configPath !== null) {
  304. configPathMap.set(configPath, config);
  305. }
  306. }
  307. } catch (err) {
  308. _didIteratorError = true;
  309. _iteratorError = err;
  310. } finally {
  311. try {
  312. if (!_iteratorNormalCompletion && _iterator.return != null) {
  313. _iterator.return();
  314. }
  315. } finally {
  316. if (_didIteratorError) {
  317. throw _iteratorError;
  318. }
  319. }
  320. }
  321. }; // Possible scenarios:
  322. // 1. jest --config config.json
  323. // 2. jest --projects p1 p2
  324. // 3. jest --projects p1 p2 --config config.json
  325. // 4. jest --projects p1
  326. // 5. jest
  327. //
  328. // If no projects are specified, process.cwd() will be used as the default
  329. // (and only) project.
  330. function readConfigs(argv, projectPaths) {
  331. let globalConfig;
  332. let hasDeprecationWarnings;
  333. let configs = [];
  334. let projects = projectPaths;
  335. let configPath;
  336. if (projectPaths.length === 1) {
  337. const parsedConfig = readConfig(argv, projects[0]);
  338. configPath = parsedConfig.configPath;
  339. if (parsedConfig.globalConfig.projects) {
  340. // If this was a single project, and its config has `projects`
  341. // settings, use that value instead.
  342. projects = parsedConfig.globalConfig.projects;
  343. }
  344. hasDeprecationWarnings = parsedConfig.hasDeprecationWarnings;
  345. globalConfig = parsedConfig.globalConfig;
  346. configs = [parsedConfig.projectConfig];
  347. if (globalConfig.projects && globalConfig.projects.length) {
  348. // Even though we had one project in CLI args, there might be more
  349. // projects defined in the config.
  350. projects = globalConfig.projects;
  351. }
  352. }
  353. if (
  354. projects.length > 1 ||
  355. (projects.length && typeof projects[0] === 'object')
  356. ) {
  357. const parsedConfigs = projects
  358. .filter(root => {
  359. // Ignore globbed files that cannot be `require`d.
  360. if (
  361. typeof root === 'string' &&
  362. _fs().default.existsSync(root) &&
  363. !_fs()
  364. .default.lstatSync(root)
  365. .isDirectory() &&
  366. !root.endsWith('.js') &&
  367. !root.endsWith('.json')
  368. ) {
  369. return false;
  370. }
  371. return true;
  372. })
  373. .map((root, projectIndex) =>
  374. readConfig(argv, root, true, configPath, projectIndex)
  375. );
  376. ensureNoDuplicateConfigs(parsedConfigs, projects);
  377. configs = parsedConfigs.map(({projectConfig}) => projectConfig);
  378. if (!hasDeprecationWarnings) {
  379. hasDeprecationWarnings = parsedConfigs.some(
  380. ({hasDeprecationWarnings}) => !!hasDeprecationWarnings
  381. );
  382. } // If no config was passed initially, use the one from the first project
  383. if (!globalConfig) {
  384. globalConfig = parsedConfigs[0].globalConfig;
  385. }
  386. }
  387. if (!globalConfig || !configs.length) {
  388. throw new Error('jest: No configuration found for any project.');
  389. }
  390. return {
  391. configs,
  392. globalConfig,
  393. hasDeprecationWarnings: !!hasDeprecationWarnings
  394. };
  395. }