UNPKG

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