@nx/jest 24.0.1 → 24.0.2
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/dist/src/plugins/plugin.js +147 -26
- package/package.json +5 -4
|
@@ -5,6 +5,8 @@ const tslib_1 = require("tslib");
|
|
|
5
5
|
const internal_1 = require("@nx/devkit/internal");
|
|
6
6
|
const devkit_1 = require("@nx/devkit");
|
|
7
7
|
const minimatch_1 = require("minimatch");
|
|
8
|
+
const picomatch = require("picomatch");
|
|
9
|
+
const node_child_process_1 = require("node:child_process");
|
|
8
10
|
const node_fs_1 = require("node:fs");
|
|
9
11
|
const node_path_1 = require("node:path");
|
|
10
12
|
const posix = tslib_1.__importStar(require("node:path/posix"));
|
|
@@ -206,7 +208,6 @@ async function buildJestTargets(rawConfig, needsDtsInputs, configFilePath, proje
|
|
|
206
208
|
[groupName]: targetGroup,
|
|
207
209
|
},
|
|
208
210
|
};
|
|
209
|
-
const specIgnoreRegexes = rawConfig.testPathIgnorePatterns?.map((p) => new RegExp(replaceRootDirInPath(projectRoot, p)));
|
|
210
211
|
for (const testPath of specs) {
|
|
211
212
|
const relativePath = (0, devkit_1.normalizePath)((0, node_path_1.relative)((0, node_path_1.join)(context.workspaceRoot, projectRoot), testPath));
|
|
212
213
|
if (relativePath.includes('../')) {
|
|
@@ -219,9 +220,6 @@ async function buildJestTargets(rawConfig, needsDtsInputs, configFilePath, proje
|
|
|
219
220
|
testMatch,
|
|
220
221
|
}, null, 2)}`);
|
|
221
222
|
}
|
|
222
|
-
if (specIgnoreRegexes?.some((regex) => regex.test(relativePath))) {
|
|
223
|
-
continue;
|
|
224
|
-
}
|
|
225
223
|
const targetName = `${options.ciTargetName}--${relativePath}`;
|
|
226
224
|
dependsOn.push({
|
|
227
225
|
target: targetName,
|
|
@@ -606,21 +604,152 @@ function requireJestUtil(packageName, projectRoot, workspaceRoot) {
|
|
|
606
604
|
paths: [(0, node_path_1.dirname)(resolvedJestCorePaths[jestPath])],
|
|
607
605
|
}));
|
|
608
606
|
}
|
|
607
|
+
// Defaults copied from https://github.com/jestjs/jest/blob/d1a2ed7/packages/jest-config/src/Defaults.ts
|
|
608
|
+
const DEFAULT_TEST_MATCH = [
|
|
609
|
+
'**/__tests__/**/*.?([mc])[jt]s?(x)',
|
|
610
|
+
'**/?(*.)+(spec|test).?([mc])[jt]s?(x)',
|
|
611
|
+
];
|
|
612
|
+
const DEFAULT_MODULE_FILE_EXTENSIONS = [
|
|
613
|
+
'js',
|
|
614
|
+
'mjs',
|
|
615
|
+
'cjs',
|
|
616
|
+
'jsx',
|
|
617
|
+
'ts',
|
|
618
|
+
'mts',
|
|
619
|
+
'cts',
|
|
620
|
+
'tsx',
|
|
621
|
+
'json',
|
|
622
|
+
'node',
|
|
623
|
+
];
|
|
624
|
+
// Mirrors how Jest selects test files: jest-haste-map's file list, then
|
|
625
|
+
// SearchSource's checks, all on the absolute path
|
|
609
626
|
async function getTestPaths(projectRoot, rawConfig, rootDir, context, presetCache) {
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
627
|
+
// Jest resolves rootDir's symlinks. Resolve the workspace root with it so
|
|
628
|
+
// file paths still compare; a default rootDir needs neither
|
|
629
|
+
let workspaceRoot = context.workspaceRoot;
|
|
630
|
+
if (rawConfig.rootDir) {
|
|
631
|
+
rootDir = tryRealpath(rootDir);
|
|
632
|
+
workspaceRoot = tryRealpath(workspaceRoot);
|
|
633
|
+
}
|
|
634
|
+
const preset = await loadPresetConfig(rawConfig, rootDir, presetCache);
|
|
635
|
+
// jest-config lets a key the config sets override the preset, even when empty
|
|
636
|
+
const getOption = (name, defaultValue) => (Object.hasOwn(rawConfig, name) ? rawConfig : preset)?.[name] ??
|
|
637
|
+
defaultValue;
|
|
638
|
+
const toArray = (value) => Array.isArray(value) ? value : [value];
|
|
639
|
+
const posixRootDir = (0, devkit_1.normalizePath)(rootDir);
|
|
640
|
+
const toRegExp = (patterns) => patterns.length > 0
|
|
641
|
+
? new RegExp(patterns
|
|
642
|
+
.map((pattern) => pattern.replaceAll('<rootDir>', posixRootDir))
|
|
643
|
+
.join('|'))
|
|
644
|
+
: undefined;
|
|
645
|
+
// jest-config reads a falsy testRegex as none
|
|
646
|
+
const testRegex = toArray(getOption('testRegex', []) || []);
|
|
647
|
+
// jest-config drops the default testMatch when testRegex is set
|
|
648
|
+
const testMatch = toArray(getOption('testMatch', testRegex.length > 0 ? [] : DEFAULT_TEST_MATCH));
|
|
649
|
+
const roots = getOption('roots', ['<rootDir>']).map((root) => `${(0, devkit_1.normalizePath)((0, node_path_1.resolve)(rootDir, replaceRootDirInPath(rootDir, root)))}/`);
|
|
650
|
+
const extensions = new Set([
|
|
651
|
+
'snap',
|
|
652
|
+
...getOption('moduleFileExtensions', DEFAULT_MODULE_FILE_EXTENSIONS),
|
|
653
|
+
]);
|
|
654
|
+
// jest-config swaps its default haste, which sets forceNodeFilesystemAPI,
|
|
655
|
+
// for any haste the config or preset sets, even an empty one
|
|
656
|
+
const hasteConfig = [rawConfig, preset].find((config) => config && Object.hasOwn(config, 'haste'));
|
|
657
|
+
const useNativeFind = !!hasteConfig &&
|
|
658
|
+
!hasteConfig.haste?.forceNodeFilesystemAPI &&
|
|
659
|
+
(await hasNativeFindSupport());
|
|
660
|
+
// jest-haste-map's native find crawler matches extensions as
|
|
661
|
+
// case-insensitive suffixes, its Node API crawler as the last extension
|
|
662
|
+
const suffixes = [...extensions].map((ext) => `.${ext}`.toLowerCase());
|
|
663
|
+
const hasExtension = useNativeFind
|
|
664
|
+
? (path) => {
|
|
665
|
+
const lowerCasePath = path.toLowerCase();
|
|
666
|
+
return suffixes.some((suffix) => lowerCasePath.endsWith(suffix));
|
|
667
|
+
}
|
|
668
|
+
: (path) => extensions.has((0, node_path_1.extname)(path).slice(1));
|
|
669
|
+
// jest-config concatenates preset and config modulePathIgnorePatterns
|
|
670
|
+
const modulePathIgnorePattern = toRegExp((preset?.modulePathIgnorePatterns ?? []).concat(rawConfig.modulePathIgnorePatterns ?? []));
|
|
671
|
+
const testPathIgnorePattern = toRegExp(getOption('testPathIgnorePatterns', ['/node_modules/']));
|
|
672
|
+
const testRegexes = testRegex.map((regex) => new RegExp(regex));
|
|
673
|
+
// Globbing from the project root already applies `**/` globs, so only other
|
|
674
|
+
// globs need a match check
|
|
675
|
+
const testMatchers = testMatch.every((pattern) => pattern.startsWith('**/'))
|
|
676
|
+
? []
|
|
677
|
+
: testMatch.map((pattern) => {
|
|
678
|
+
// Built like jest-util's: minimatch would read `(a|b)` groups literally
|
|
679
|
+
const isMatch = picomatch(replacePathSepForGlob(replaceRootDirInPath(escapeGlobCharacters(rootDir), pattern)), { dot: true }, true);
|
|
680
|
+
return {
|
|
681
|
+
isMatch,
|
|
682
|
+
negated: isMatch.state.negated || !!isMatch.state.negatedExtglob,
|
|
683
|
+
};
|
|
684
|
+
});
|
|
685
|
+
// Unless every testMatch glob is negated, a file must match a non-negated one
|
|
686
|
+
const includePatterns = testMatch.filter((_, i) => !testMatchers[i]?.negated);
|
|
687
|
+
const candidates = await (0, internal_1.globWithWorkspaceContext)(context.workspaceRoot, includePatterns.length > 0
|
|
688
|
+
? includePatterns.map((pattern) => {
|
|
689
|
+
const path = replaceRootDirInPath(rootDir, pattern);
|
|
690
|
+
return (0, node_path_1.isAbsolute)(path)
|
|
691
|
+
? (0, devkit_1.normalizePath)((0, node_path_1.relative)(workspaceRoot, path))
|
|
692
|
+
: posix.join(projectRoot, pattern);
|
|
693
|
+
})
|
|
694
|
+
: [posix.join(projectRoot, '**/*')], []);
|
|
695
|
+
const workspacePath = (0, devkit_1.normalizePath)((0, node_path_1.join)(workspaceRoot, '/'));
|
|
696
|
+
const specs = candidates.filter((file) => {
|
|
697
|
+
const path = workspacePath + file;
|
|
698
|
+
return (hasExtension(path) &&
|
|
699
|
+
!modulePathIgnorePattern?.test(path) &&
|
|
700
|
+
roots.some((root) => path.includes(root)) &&
|
|
701
|
+
(testMatchers.length === 0 || matchesGlobs(testMatchers, path)) &&
|
|
702
|
+
!testPathIgnorePattern?.test(path) &&
|
|
703
|
+
(testRegexes.length === 0 || testRegexes.some((r) => r.test(path))));
|
|
704
|
+
});
|
|
705
|
+
return { specs, testMatch };
|
|
706
|
+
}
|
|
707
|
+
function matchesGlobs(matchers, path) {
|
|
708
|
+
let kept;
|
|
709
|
+
for (const { isMatch, negated } of matchers) {
|
|
710
|
+
const matched = isMatch(path);
|
|
711
|
+
if (!matched && negated) {
|
|
712
|
+
kept = false;
|
|
713
|
+
}
|
|
714
|
+
else if (matched && !negated) {
|
|
715
|
+
kept = true;
|
|
716
|
+
}
|
|
717
|
+
}
|
|
718
|
+
return matchers.every(({ negated }) => negated)
|
|
719
|
+
? kept !== false
|
|
720
|
+
: kept === true;
|
|
721
|
+
}
|
|
722
|
+
// Ports of the jest-config and jest-util helpers Jest uses to put rootDir into
|
|
723
|
+
// testMatch globs
|
|
724
|
+
function escapeGlobCharacters(path) {
|
|
725
|
+
return path.replaceAll(/([!()*?[\\\]{}])/g, '\\$1');
|
|
726
|
+
}
|
|
727
|
+
function replacePathSepForGlob(path) {
|
|
728
|
+
return path.replaceAll(/\\(?![$()+.?^{}])/g, '/');
|
|
729
|
+
}
|
|
730
|
+
function tryRealpath(path) {
|
|
731
|
+
try {
|
|
732
|
+
return node_fs_1.realpathSync.native(path);
|
|
733
|
+
}
|
|
734
|
+
catch {
|
|
735
|
+
return path;
|
|
736
|
+
}
|
|
737
|
+
}
|
|
738
|
+
let nativeFindSupport;
|
|
739
|
+
// Port of jest-haste-map's check for a find that supports -iname, cached
|
|
740
|
+
// because the find on PATH doesn't change during a process lifetime
|
|
741
|
+
function hasNativeFindSupport() {
|
|
742
|
+
nativeFindSupport ??= new Promise((done) => {
|
|
743
|
+
try {
|
|
744
|
+
const child = (0, node_child_process_1.spawn)('find', ['.', '-type', 'f', '(', '-iname', '*.ts', '-o', '-iname', '*.js', ')'], { cwd: __dirname, stdio: 'ignore', windowsHide: true });
|
|
745
|
+
child.on('error', () => done(false));
|
|
746
|
+
child.on('exit', (code) => done(code === 0));
|
|
747
|
+
}
|
|
748
|
+
catch {
|
|
749
|
+
done(false);
|
|
750
|
+
}
|
|
751
|
+
});
|
|
752
|
+
return nativeFindSupport;
|
|
624
753
|
}
|
|
625
754
|
/**
|
|
626
755
|
* Collects workspace-relative paths to files whose CONTENT the plugin reads
|
|
@@ -939,11 +1068,3 @@ function getTsJestMajorVersion() {
|
|
|
939
1068
|
}
|
|
940
1069
|
return cachedTsJestMajorVersion;
|
|
941
1070
|
}
|
|
942
|
-
async function getJestOption(rawConfig, rootDir, optionName, presetCache) {
|
|
943
|
-
if (rawConfig[optionName])
|
|
944
|
-
return rawConfig[optionName];
|
|
945
|
-
const preset = await loadPresetConfig(rawConfig, rootDir, presetCache);
|
|
946
|
-
if (preset?.[optionName])
|
|
947
|
-
return preset[optionName];
|
|
948
|
-
return undefined;
|
|
949
|
-
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nx/jest",
|
|
3
|
-
"version": "24.0.
|
|
3
|
+
"version": "24.0.2",
|
|
4
4
|
"private": false,
|
|
5
5
|
"type": "commonjs",
|
|
6
6
|
"files": [
|
|
@@ -103,21 +103,22 @@
|
|
|
103
103
|
}
|
|
104
104
|
},
|
|
105
105
|
"dependencies": {
|
|
106
|
-
"@nx/devkit": "24.0.
|
|
107
|
-
"@nx/js": "24.0.
|
|
106
|
+
"@nx/devkit": "24.0.2",
|
|
107
|
+
"@nx/js": "24.0.2",
|
|
108
108
|
"@phenomnomnominal/tsquery": "~6.2.0",
|
|
109
109
|
"identity-obj-proxy": "3.0.0",
|
|
110
110
|
"jest-config": "^30.0.2",
|
|
111
111
|
"jest-resolve": "^30.0.2",
|
|
112
112
|
"jsonc-parser": "^3.2.0",
|
|
113
113
|
"minimatch": "10.2.5",
|
|
114
|
+
"picomatch": "4.0.4",
|
|
114
115
|
"resolve.exports": "2.0.3",
|
|
115
116
|
"semver": "^7.6.3",
|
|
116
117
|
"tslib": "^2.3.0",
|
|
117
118
|
"yargs-parser": "21.1.1"
|
|
118
119
|
},
|
|
119
120
|
"devDependencies": {
|
|
120
|
-
"nx": "24.0.
|
|
121
|
+
"nx": "24.0.2"
|
|
121
122
|
},
|
|
122
123
|
"publishConfig": {
|
|
123
124
|
"access": "public"
|