@nx/jest 22.6.0-beta.12 → 22.6.0-beta.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +4 -4
- package/src/plugins/plugin.d.ts +10 -0
- package/src/plugins/plugin.d.ts.map +1 -1
- package/src/plugins/plugin.js +263 -52
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nx/jest",
|
|
3
|
-
"version": "22.6.0-beta.
|
|
3
|
+
"version": "22.6.0-beta.14",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "The Nx Plugin for Jest contains executors and generators allowing your workspace to use the powerful Jest testing capabilities.",
|
|
6
6
|
"repository": {
|
|
@@ -37,8 +37,8 @@
|
|
|
37
37
|
"dependencies": {
|
|
38
38
|
"@jest/reporters": "^30.0.2",
|
|
39
39
|
"@jest/test-result": "^30.0.2",
|
|
40
|
-
"@nx/devkit": "22.6.0-beta.
|
|
41
|
-
"@nx/js": "22.6.0-beta.
|
|
40
|
+
"@nx/devkit": "22.6.0-beta.14",
|
|
41
|
+
"@nx/js": "22.6.0-beta.14",
|
|
42
42
|
"@phenomnomnominal/tsquery": "~6.1.4",
|
|
43
43
|
"identity-obj-proxy": "3.0.0",
|
|
44
44
|
"jest-config": "^30.0.2",
|
|
@@ -52,7 +52,7 @@
|
|
|
52
52
|
"yargs-parser": "21.1.1"
|
|
53
53
|
},
|
|
54
54
|
"devDependencies": {
|
|
55
|
-
"nx": "22.6.0-beta.
|
|
55
|
+
"nx": "22.6.0-beta.14"
|
|
56
56
|
},
|
|
57
57
|
"publishConfig": {
|
|
58
58
|
"access": "public"
|
package/src/plugins/plugin.d.ts
CHANGED
|
@@ -12,6 +12,16 @@ export interface JestPluginOptions {
|
|
|
12
12
|
* and test matcher instead of Jest's.
|
|
13
13
|
*/
|
|
14
14
|
disableJestRuntime?: boolean;
|
|
15
|
+
/**
|
|
16
|
+
* Whether to use Jest's resolver (jest-resolve) for resolving config file
|
|
17
|
+
* references (presets, transforms, setup files, module name mappers, etc.)
|
|
18
|
+
* as task inputs. When false, uses path-based classification which is fast
|
|
19
|
+
* but cannot follow symlinks or honor custom moduleDirectories/modulePaths.
|
|
20
|
+
* Enable this if your config references workspace-linked packages or relies
|
|
21
|
+
* on Jest-specific resolution behavior.
|
|
22
|
+
* @default true when disableJestRuntime is false, false otherwise
|
|
23
|
+
*/
|
|
24
|
+
useJestResolver?: boolean;
|
|
15
25
|
}
|
|
16
26
|
export declare const createNodes: CreateNodesV2<JestPluginOptions>;
|
|
17
27
|
export declare const createNodesV2: CreateNodesV2<JestPluginOptions>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../../../../../packages/jest/src/plugins/plugin.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,aAAa,EASd,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../../../../../packages/jest/src/plugins/plugin.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,aAAa,EASd,MAAM,YAAY,CAAC;AA6BpB,MAAM,WAAW,iBAAiB;IAChC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;IAEtB;;OAEG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;OAIG;IACH,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B;;;;;;;;OAQG;IACH,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B;AAmBD,eAAO,MAAM,WAAW,EAAE,aAAa,CAAC,iBAAiB,CAiFxD,CAAC;AAEF,eAAO,MAAM,aAAa,kCAAc,CAAC"}
|
package/src/plugins/plugin.js
CHANGED
|
@@ -17,6 +17,7 @@ const plugins_1 = require("nx/src/utils/plugins");
|
|
|
17
17
|
const workspace_context_1 = require("nx/src/utils/workspace-context");
|
|
18
18
|
const versions_1 = require("../utils/versions");
|
|
19
19
|
const pmc = (0, devkit_1.getPackageManagerCommand)();
|
|
20
|
+
const REPORTER_BUILTINS = new Set(['default', 'github-actions', 'summary']);
|
|
20
21
|
function readTargetsCache(cachePath) {
|
|
21
22
|
return process.env.NX_CACHE_PROJECT_GRAPH !== 'false' && (0, node_fs_1.existsSync)(cachePath)
|
|
22
23
|
? (0, devkit_1.readJsonFile)(cachePath)
|
|
@@ -147,8 +148,13 @@ async function buildJestTargets(configFilePath, projectRoot, options, context, p
|
|
|
147
148
|
});
|
|
148
149
|
// Not normalizing it here since also affects options for convert-to-inferred.
|
|
149
150
|
const disableJestRuntime = options.disableJestRuntime !== false;
|
|
151
|
+
const useJestResolver = options.useJestResolver ?? !disableJestRuntime;
|
|
152
|
+
// Jest defaults rootDir to the config file's directory, but allows overrides
|
|
153
|
+
const rootDir = rawConfig.rootDir
|
|
154
|
+
? (0, node_path_1.resolve)((0, node_path_1.dirname)(absConfigFilePath), rawConfig.rootDir)
|
|
155
|
+
: (0, node_path_1.resolve)(context.workspaceRoot, projectRoot);
|
|
150
156
|
const cache = (target.cache = true);
|
|
151
|
-
const inputs = (target.inputs = getInputs(namedInputs, rawConfig
|
|
157
|
+
const inputs = (target.inputs = await getInputs(namedInputs, rawConfig, rootDir, projectRoot, context.workspaceRoot, presetCache, useJestResolver));
|
|
152
158
|
let metadata;
|
|
153
159
|
const groupName = options?.ciGroupName ?? (0, plugins_1.deriveGroupNameFromTarget)(options?.ciTargetName);
|
|
154
160
|
if (disableJestRuntime) {
|
|
@@ -156,7 +162,7 @@ async function buildJestTargets(configFilePath, projectRoot, options, context, p
|
|
|
156
162
|
? (0, node_path_1.join)(context.workspaceRoot, projectRoot, rawConfig.coverageDirectory)
|
|
157
163
|
: undefined, undefined, context));
|
|
158
164
|
if (options?.ciTargetName) {
|
|
159
|
-
const { specs, testMatch } = await getTestPaths(projectRoot, rawConfig,
|
|
165
|
+
const { specs, testMatch } = await getTestPaths(projectRoot, rawConfig, rootDir, context, presetCache);
|
|
160
166
|
const targetGroup = [];
|
|
161
167
|
const dependsOn = [];
|
|
162
168
|
metadata = {
|
|
@@ -341,71 +347,79 @@ async function buildJestTargets(configFilePath, projectRoot, options, context, p
|
|
|
341
347
|
}
|
|
342
348
|
return { targets, metadata };
|
|
343
349
|
}
|
|
344
|
-
function getInputs(namedInputs,
|
|
350
|
+
async function getInputs(namedInputs, rawConfig, rootDir, projectRoot, workspaceRoot, presetCache, useJestResolver) {
|
|
345
351
|
const inputs = [
|
|
346
352
|
...('production' in namedInputs
|
|
347
353
|
? ['default', '^production']
|
|
348
354
|
: ['default', '^default']),
|
|
349
355
|
];
|
|
350
356
|
const externalDependencies = ['jest'];
|
|
351
|
-
const
|
|
352
|
-
|
|
353
|
-
|
|
357
|
+
const resolvedModulePaths = rawConfig.modulePaths?.map((p) => replaceRootDirInPath(rootDir, p));
|
|
358
|
+
const jestResolve = useJestResolver
|
|
359
|
+
? requireJestUtil('jest-resolve', projectRoot, workspaceRoot).default
|
|
360
|
+
: null;
|
|
361
|
+
const presetInput = jestResolve
|
|
362
|
+
? resolvePresetInputWithJestResolver(rawConfig.preset, rootDir, projectRoot, workspaceRoot, jestResolve, rawConfig.moduleDirectories, resolvedModulePaths)
|
|
363
|
+
: resolvePresetInputWithoutJestResolver(rawConfig.preset, rootDir, projectRoot, workspaceRoot);
|
|
364
|
+
// Track preset file path to avoid duplicating it with config-derived inputs
|
|
365
|
+
let presetInputPath = null;
|
|
354
366
|
if (presetInput) {
|
|
355
367
|
if (typeof presetInput !== 'string' &&
|
|
356
368
|
'externalDependencies' in presetInput) {
|
|
357
369
|
externalDependencies.push(...presetInput.externalDependencies);
|
|
358
370
|
}
|
|
359
371
|
else {
|
|
372
|
+
presetInputPath = presetInput;
|
|
360
373
|
inputs.push(presetInput);
|
|
361
374
|
}
|
|
362
375
|
}
|
|
376
|
+
const resolveFilePath = jestResolve
|
|
377
|
+
? createJestResolveFilePathResolver(rootDir, projectRoot, workspaceRoot, jestResolve, rawConfig.moduleDirectories, resolvedModulePaths)
|
|
378
|
+
: createFilePathResolverWithoutJest(rootDir, projectRoot, workspaceRoot);
|
|
379
|
+
const configInputs = await getConfigFileInputs(rawConfig, rootDir, presetCache, resolveFilePath);
|
|
380
|
+
for (const fileInput of configInputs.fileInputs) {
|
|
381
|
+
if (fileInput !== presetInputPath) {
|
|
382
|
+
inputs.push(fileInput);
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
for (const dep of configInputs.externalDeps) {
|
|
386
|
+
if (!externalDependencies.includes(dep)) {
|
|
387
|
+
externalDependencies.push(dep);
|
|
388
|
+
}
|
|
389
|
+
}
|
|
363
390
|
inputs.push({ externalDependencies });
|
|
364
391
|
return inputs;
|
|
365
392
|
}
|
|
366
|
-
function resolvePresetInputWithoutJestResolver(presetValue, projectRoot, workspaceRoot) {
|
|
393
|
+
function resolvePresetInputWithoutJestResolver(presetValue, rootDir, projectRoot, workspaceRoot) {
|
|
367
394
|
if (!presetValue)
|
|
368
395
|
return null;
|
|
369
|
-
const presetPath = replaceRootDirInPath(
|
|
370
|
-
const
|
|
371
|
-
if (
|
|
372
|
-
return { externalDependencies: [presetValue] };
|
|
373
|
-
}
|
|
374
|
-
if (presetPath.startsWith('..')) {
|
|
375
|
-
const relativePath = (0, node_path_1.relative)(workspaceRoot, (0, node_path_1.join)(projectRoot, presetPath));
|
|
376
|
-
return (0, node_path_1.join)('{workspaceRoot}', relativePath);
|
|
377
|
-
}
|
|
378
|
-
else {
|
|
379
|
-
const relativePath = (0, node_path_1.relative)(projectRoot, presetPath);
|
|
380
|
-
return (0, node_path_1.join)('{projectRoot}', relativePath);
|
|
396
|
+
const presetPath = replaceRootDirInPath(rootDir, presetValue);
|
|
397
|
+
const isNpmLike = !presetValue.startsWith('.') && !(0, node_path_1.isAbsolute)(presetPath);
|
|
398
|
+
if (isNpmLike) {
|
|
399
|
+
return { externalDependencies: [extractPackageName(presetValue)] };
|
|
381
400
|
}
|
|
401
|
+
const absoluteProjectRoot = (0, node_path_1.resolve)(workspaceRoot, projectRoot);
|
|
402
|
+
return classifyResolvedPath((0, node_path_1.resolve)(rootDir, presetPath), absoluteProjectRoot, workspaceRoot);
|
|
382
403
|
}
|
|
383
404
|
// preset resolution adapted from:
|
|
384
405
|
// https://github.com/jestjs/jest/blob/c54bccd657fb4cf060898717c09f633b4da3eec4/packages/jest-config/src/normalize.ts#L122
|
|
385
|
-
function resolvePresetInputWithJestResolver(presetValue, projectRoot, workspaceRoot) {
|
|
406
|
+
function resolvePresetInputWithJestResolver(presetValue, rootDir, projectRoot, workspaceRoot, jestResolve, moduleDirectories, modulePaths) {
|
|
386
407
|
if (!presetValue)
|
|
387
408
|
return null;
|
|
388
|
-
let presetPath = replaceRootDirInPath(
|
|
389
|
-
const isNpmPackage = !presetValue.startsWith('.') && !(0, node_path_1.isAbsolute)(presetPath);
|
|
409
|
+
let presetPath = replaceRootDirInPath(rootDir, presetValue);
|
|
390
410
|
presetPath = presetPath.startsWith('.')
|
|
391
411
|
? presetPath
|
|
392
412
|
: (0, node_path_1.join)(presetPath, 'jest-preset');
|
|
393
|
-
const { default: jestResolve } = requireJestUtil('jest-resolve', projectRoot, workspaceRoot);
|
|
394
|
-
const absoluteProjectRoot = (0, node_path_1.join)(workspaceRoot, projectRoot);
|
|
395
413
|
const presetModule = jestResolve.findNodeModule(presetPath, {
|
|
396
|
-
basedir:
|
|
414
|
+
basedir: rootDir,
|
|
397
415
|
extensions: ['.json', '.js', '.cjs', '.mjs'],
|
|
416
|
+
moduleDirectory: moduleDirectories,
|
|
417
|
+
paths: modulePaths,
|
|
398
418
|
});
|
|
399
419
|
if (!presetModule) {
|
|
400
420
|
return null;
|
|
401
421
|
}
|
|
402
|
-
|
|
403
|
-
return { externalDependencies: [presetValue] };
|
|
404
|
-
}
|
|
405
|
-
const relativePath = (0, node_path_1.relative)(absoluteProjectRoot, presetModule);
|
|
406
|
-
return relativePath.startsWith('..')
|
|
407
|
-
? (0, node_path_1.join)('{workspaceRoot}', (0, node_path_1.join)(projectRoot, relativePath))
|
|
408
|
-
: (0, node_path_1.join)('{projectRoot}', relativePath);
|
|
422
|
+
return classifyResolvedPath(presetModule, (0, node_path_1.resolve)(workspaceRoot, projectRoot), workspaceRoot);
|
|
409
423
|
}
|
|
410
424
|
// Adapted from here https://github.com/jestjs/jest/blob/c13bca3/packages/jest-config/src/utils.ts#L57-L69
|
|
411
425
|
function replaceRootDirInPath(rootDir, filePath) {
|
|
@@ -414,6 +428,79 @@ function replaceRootDirInPath(rootDir, filePath) {
|
|
|
414
428
|
}
|
|
415
429
|
return (0, node_path_1.resolve)(rootDir, (0, node_path_1.normalize)(`./${filePath.slice('<rootDir>'.length)}`));
|
|
416
430
|
}
|
|
431
|
+
function classifyResolvedPath(absolutePath, absoluteProjectRoot, workspaceRoot) {
|
|
432
|
+
const relToWorkspace = (0, devkit_1.normalizePath)((0, node_path_1.relative)(workspaceRoot, absolutePath));
|
|
433
|
+
if (relToWorkspace.includes('node_modules/')) {
|
|
434
|
+
const nmIndex = relToWorkspace.lastIndexOf('node_modules/');
|
|
435
|
+
const afterNm = relToWorkspace.slice(nmIndex + 'node_modules/'.length);
|
|
436
|
+
return { externalDependencies: [extractPackageName(afterNm)] };
|
|
437
|
+
}
|
|
438
|
+
const relToProject = (0, devkit_1.normalizePath)((0, node_path_1.relative)(absoluteProjectRoot, absolutePath));
|
|
439
|
+
if (relToProject.startsWith('..')) {
|
|
440
|
+
return (0, devkit_1.joinPathFragments)('{workspaceRoot}', relToWorkspace);
|
|
441
|
+
}
|
|
442
|
+
return (0, devkit_1.joinPathFragments)('{projectRoot}', relToProject);
|
|
443
|
+
}
|
|
444
|
+
function extractPackageName(value) {
|
|
445
|
+
const parts = value.split('/');
|
|
446
|
+
return value.startsWith('@') ? `${parts[0]}/${parts[1]}` : parts[0];
|
|
447
|
+
}
|
|
448
|
+
function createFilePathResolverWithoutJest(rootDir, projectRoot, workspaceRoot) {
|
|
449
|
+
const absoluteProjectRoot = (0, node_path_1.resolve)(workspaceRoot, projectRoot);
|
|
450
|
+
return (filePath) => {
|
|
451
|
+
const resolvedPath = replaceRootDirInPath(rootDir, filePath);
|
|
452
|
+
if (looksLikePackageName(filePath, resolvedPath)) {
|
|
453
|
+
return { externalDependencies: [extractPackageName(filePath)] };
|
|
454
|
+
}
|
|
455
|
+
return classifyResolvedPath((0, node_path_1.resolve)(rootDir, resolvedPath), absoluteProjectRoot, workspaceRoot);
|
|
456
|
+
};
|
|
457
|
+
}
|
|
458
|
+
function resolveWithPrefixFallback(filePath, prefix, resolver) {
|
|
459
|
+
if (!filePath.startsWith('.') &&
|
|
460
|
+
!filePath.startsWith('<rootDir>') &&
|
|
461
|
+
!(0, node_path_1.isAbsolute)(filePath) &&
|
|
462
|
+
!filePath.startsWith(prefix)) {
|
|
463
|
+
const prefixed = resolver(`${prefix}${filePath}`);
|
|
464
|
+
if (prefixed)
|
|
465
|
+
return prefixed;
|
|
466
|
+
}
|
|
467
|
+
return resolver(filePath);
|
|
468
|
+
}
|
|
469
|
+
function looksLikePackageName(filePath, resolvedPath) {
|
|
470
|
+
return (!filePath.startsWith('.') &&
|
|
471
|
+
!filePath.startsWith('<rootDir>') &&
|
|
472
|
+
!(0, node_path_1.isAbsolute)(resolvedPath));
|
|
473
|
+
}
|
|
474
|
+
function createJestResolveFilePathResolver(rootDir, projectRoot, workspaceRoot, jestResolve, moduleDirectories, modulePaths) {
|
|
475
|
+
const absoluteProjectRoot = (0, node_path_1.resolve)(workspaceRoot, projectRoot);
|
|
476
|
+
const cache = new Map();
|
|
477
|
+
return (filePath) => {
|
|
478
|
+
if (cache.has(filePath)) {
|
|
479
|
+
return cache.get(filePath);
|
|
480
|
+
}
|
|
481
|
+
const resolvedPath = replaceRootDirInPath(rootDir, filePath);
|
|
482
|
+
let result;
|
|
483
|
+
const absolutePath = jestResolve.findNodeModule(resolvedPath, {
|
|
484
|
+
basedir: rootDir,
|
|
485
|
+
extensions: ['.js', '.json', '.cjs', '.mjs', '.mts', '.cts', '.node'],
|
|
486
|
+
moduleDirectory: moduleDirectories,
|
|
487
|
+
paths: modulePaths,
|
|
488
|
+
});
|
|
489
|
+
if (!absolutePath) {
|
|
490
|
+
if (looksLikePackageName(filePath, resolvedPath)) {
|
|
491
|
+
result = { externalDependencies: [extractPackageName(filePath)] };
|
|
492
|
+
}
|
|
493
|
+
else {
|
|
494
|
+
result = null;
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
else {
|
|
498
|
+
result = classifyResolvedPath(absolutePath, absoluteProjectRoot, workspaceRoot);
|
|
499
|
+
}
|
|
500
|
+
cache.set(filePath, result);
|
|
501
|
+
return result;
|
|
502
|
+
};
|
|
503
|
+
}
|
|
417
504
|
function getOutputs(projectRoot, coverageDirectory, outputFile, context) {
|
|
418
505
|
function getOutput(path) {
|
|
419
506
|
const relativePath = (0, node_path_1.relative)((0, node_path_1.join)(context.workspaceRoot, projectRoot), path);
|
|
@@ -465,14 +552,14 @@ function requireJestUtil(packageName, projectRoot, workspaceRoot) {
|
|
|
465
552
|
paths: [(0, node_path_1.dirname)(resolvedJestCorePaths[jestPath])],
|
|
466
553
|
}));
|
|
467
554
|
}
|
|
468
|
-
async function getTestPaths(projectRoot, rawConfig,
|
|
469
|
-
const testMatch = await getJestOption(rawConfig,
|
|
555
|
+
async function getTestPaths(projectRoot, rawConfig, rootDir, context, presetCache) {
|
|
556
|
+
const testMatch = await getJestOption(rawConfig, rootDir, 'testMatch', presetCache);
|
|
470
557
|
let paths = await (0, workspace_context_1.globWithWorkspaceContext)(context.workspaceRoot, (testMatch || [
|
|
471
558
|
// Default copied from https://github.com/jestjs/jest/blob/d1a2ed7/packages/jest-config/src/Defaults.ts#L84
|
|
472
559
|
'**/__tests__/**/*.?([mc])[jt]s?(x)',
|
|
473
560
|
'**/?(*.)+(spec|test).?([mc])[jt]s?(x)',
|
|
474
561
|
]).map((pattern) => (0, node_path_1.join)(projectRoot, pattern)), []);
|
|
475
|
-
const testRegex = await getJestOption(rawConfig,
|
|
562
|
+
const testRegex = await getJestOption(rawConfig, rootDir, 'testRegex', presetCache);
|
|
476
563
|
if (testRegex) {
|
|
477
564
|
const testRegexes = Array.isArray(rawConfig.testRegex)
|
|
478
565
|
? rawConfig.testRegex.map((r) => new RegExp(r))
|
|
@@ -481,27 +568,151 @@ async function getTestPaths(projectRoot, rawConfig, absConfigFilePath, context,
|
|
|
481
568
|
}
|
|
482
569
|
return { specs: paths, testMatch };
|
|
483
570
|
}
|
|
484
|
-
async function
|
|
485
|
-
if (rawConfig
|
|
486
|
-
return
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
571
|
+
async function loadPresetConfig(rawConfig, rootDir, presetCache) {
|
|
572
|
+
if (!rawConfig.preset)
|
|
573
|
+
return null;
|
|
574
|
+
const presetValue = replaceRootDirInPath(rootDir, rawConfig.preset);
|
|
575
|
+
let presetPath;
|
|
576
|
+
if (presetValue.startsWith('.') || (0, node_path_1.isAbsolute)(presetValue)) {
|
|
577
|
+
presetPath = (0, node_path_1.resolve)(rootDir, presetValue);
|
|
578
|
+
}
|
|
579
|
+
else {
|
|
490
580
|
try {
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
presetCache[presetPath] = preset;
|
|
495
|
-
}
|
|
496
|
-
if (preset[optionName])
|
|
497
|
-
return preset[optionName];
|
|
581
|
+
presetPath = require.resolve((0, node_path_1.join)(presetValue, 'jest-preset'), {
|
|
582
|
+
paths: [rootDir],
|
|
583
|
+
});
|
|
498
584
|
}
|
|
499
585
|
catch {
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
586
|
+
return null;
|
|
587
|
+
}
|
|
588
|
+
}
|
|
589
|
+
try {
|
|
590
|
+
if (!presetCache[presetPath]) {
|
|
591
|
+
presetCache[presetPath] = (0, config_utils_1.loadConfigFile)(presetPath);
|
|
504
592
|
}
|
|
593
|
+
return (await presetCache[presetPath]);
|
|
594
|
+
}
|
|
595
|
+
catch {
|
|
596
|
+
// If preset fails to load, ignore the error and continue.
|
|
597
|
+
// This is safe and less jarring for users. They will need to fix the
|
|
598
|
+
// preset for Jest to run, and at that point we can read in the correct
|
|
599
|
+
// value.
|
|
600
|
+
return null;
|
|
505
601
|
}
|
|
602
|
+
}
|
|
603
|
+
async function getConfigFileInputs(rawConfig, rootDir, presetCache, resolveFilePath) {
|
|
604
|
+
const fileInputs = new Set();
|
|
605
|
+
const externalDeps = new Set();
|
|
606
|
+
const preset = await loadPresetConfig(rawConfig, rootDir, presetCache);
|
|
607
|
+
function addInput(input) {
|
|
608
|
+
if (!input)
|
|
609
|
+
return;
|
|
610
|
+
if (typeof input === 'string') {
|
|
611
|
+
fileInputs.add(input);
|
|
612
|
+
}
|
|
613
|
+
else {
|
|
614
|
+
input.externalDependencies.forEach((d) => externalDeps.add(d));
|
|
615
|
+
}
|
|
616
|
+
}
|
|
617
|
+
// Replaced properties: rawConfig[prop] wins over preset[prop]
|
|
618
|
+
for (const prop of [
|
|
619
|
+
'resolver',
|
|
620
|
+
'globalSetup',
|
|
621
|
+
'globalTeardown',
|
|
622
|
+
'snapshotResolver',
|
|
623
|
+
'testResultsProcessor',
|
|
624
|
+
]) {
|
|
625
|
+
const value = rawConfig[prop] ?? preset?.[prop];
|
|
626
|
+
if (typeof value === 'string') {
|
|
627
|
+
addInput(resolveFilePath(value));
|
|
628
|
+
}
|
|
629
|
+
}
|
|
630
|
+
// runner uses jest-runner- prefix resolution
|
|
631
|
+
const runner = rawConfig.runner ?? preset?.runner;
|
|
632
|
+
if (typeof runner === 'string') {
|
|
633
|
+
addInput(resolveWithPrefixFallback(runner, 'jest-runner-', resolveFilePath));
|
|
634
|
+
}
|
|
635
|
+
// Concatenated properties: preset values + config values
|
|
636
|
+
for (const prop of ['setupFiles', 'setupFilesAfterEnv']) {
|
|
637
|
+
const values = [
|
|
638
|
+
...(preset?.[prop] ?? []),
|
|
639
|
+
...(rawConfig[prop] ?? []),
|
|
640
|
+
];
|
|
641
|
+
for (const value of values) {
|
|
642
|
+
if (typeof value === 'string') {
|
|
643
|
+
addInput(resolveFilePath(value));
|
|
644
|
+
}
|
|
645
|
+
}
|
|
646
|
+
}
|
|
647
|
+
// Merged: moduleNameMapper — config keys win (skip values with backreferences like $1)
|
|
648
|
+
const moduleNameMapper = {
|
|
649
|
+
...(preset?.moduleNameMapper ?? {}),
|
|
650
|
+
...(rawConfig.moduleNameMapper ?? {}),
|
|
651
|
+
};
|
|
652
|
+
for (const value of Object.values(moduleNameMapper)) {
|
|
653
|
+
const values = Array.isArray(value) ? value : [value];
|
|
654
|
+
for (const v of values) {
|
|
655
|
+
if (typeof v !== 'string')
|
|
656
|
+
continue;
|
|
657
|
+
if (/\$\d/.test(v))
|
|
658
|
+
continue;
|
|
659
|
+
addInput(resolveFilePath(v));
|
|
660
|
+
}
|
|
661
|
+
}
|
|
662
|
+
// Merged: transform — config keys win
|
|
663
|
+
const transform = {
|
|
664
|
+
...(preset?.transform ?? {}),
|
|
665
|
+
...(rawConfig.transform ?? {}),
|
|
666
|
+
};
|
|
667
|
+
for (const value of Object.values(transform)) {
|
|
668
|
+
let transformPath;
|
|
669
|
+
if (Array.isArray(value)) {
|
|
670
|
+
transformPath = value[0];
|
|
671
|
+
}
|
|
672
|
+
else if (typeof value === 'string') {
|
|
673
|
+
transformPath = value;
|
|
674
|
+
}
|
|
675
|
+
else {
|
|
676
|
+
continue;
|
|
677
|
+
}
|
|
678
|
+
addInput(resolveFilePath(transformPath));
|
|
679
|
+
}
|
|
680
|
+
// Replaced: snapshotSerializers, reporters, watchPlugins
|
|
681
|
+
const snapshotSerializers = rawConfig.snapshotSerializers ??
|
|
682
|
+
preset?.snapshotSerializers ??
|
|
683
|
+
[];
|
|
684
|
+
for (const value of snapshotSerializers) {
|
|
685
|
+
if (typeof value === 'string') {
|
|
686
|
+
addInput(resolveFilePath(value));
|
|
687
|
+
}
|
|
688
|
+
}
|
|
689
|
+
const reporters = rawConfig.reporters ?? preset?.reporters ?? [];
|
|
690
|
+
for (const entry of reporters) {
|
|
691
|
+
const name = Array.isArray(entry) ? entry[0] : entry;
|
|
692
|
+
if (typeof name !== 'string')
|
|
693
|
+
continue;
|
|
694
|
+
if (REPORTER_BUILTINS.has(name))
|
|
695
|
+
continue;
|
|
696
|
+
addInput(resolveFilePath(name));
|
|
697
|
+
}
|
|
698
|
+
// watchPlugins uses jest-watch- prefix resolution
|
|
699
|
+
const watchPlugins = rawConfig.watchPlugins ?? preset?.watchPlugins ?? [];
|
|
700
|
+
for (const entry of watchPlugins) {
|
|
701
|
+
const name = Array.isArray(entry) ? entry[0] : entry;
|
|
702
|
+
if (typeof name !== 'string')
|
|
703
|
+
continue;
|
|
704
|
+
addInput(resolveWithPrefixFallback(name, 'jest-watch-', resolveFilePath));
|
|
705
|
+
}
|
|
706
|
+
return {
|
|
707
|
+
fileInputs: [...fileInputs],
|
|
708
|
+
externalDeps: [...externalDeps],
|
|
709
|
+
};
|
|
710
|
+
}
|
|
711
|
+
async function getJestOption(rawConfig, rootDir, optionName, presetCache) {
|
|
712
|
+
if (rawConfig[optionName])
|
|
713
|
+
return rawConfig[optionName];
|
|
714
|
+
const preset = await loadPresetConfig(rawConfig, rootDir, presetCache);
|
|
715
|
+
if (preset?.[optionName])
|
|
716
|
+
return preset[optionName];
|
|
506
717
|
return undefined;
|
|
507
718
|
}
|