index.js 15 KB

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