@nx/jest 23.0.0-beta.20 → 23.0.0-beta.22
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/executors/jest/jest.impl.js +0 -10
- package/dist/src/executors/jest/schema.d.ts +0 -7
- package/dist/src/executors/jest/schema.json +0 -5
- package/dist/src/generators/configuration/configuration.js +2 -5
- package/dist/src/generators/configuration/lib/ensure-dependencies.js +1 -1
- package/dist/src/generators/configuration/schema.d.ts +0 -4
- package/dist/src/generators/configuration/schema.json +0 -6
- package/dist/src/generators/convert-to-inferred/convert-to-inferred.js +2 -0
- package/dist/src/generators/init/init.js +3 -5
- package/dist/src/generators/init/schema.json +1 -1
- package/dist/src/migrations/update-23-0-0/migrate-jest-configuration-skip-setup-file.d.ts +2 -0
- package/dist/src/migrations/update-23-0-0/migrate-jest-configuration-skip-setup-file.js +62 -0
- package/dist/src/migrations/update-23-0-0/migrate-jest-configuration-skip-setup-file.md +91 -0
- package/dist/src/migrations/update-23-0-0/migrate-jest-executor-setup-file.d.ts +2 -0
- package/dist/src/migrations/update-23-0-0/migrate-jest-executor-setup-file.js +476 -0
- package/dist/src/migrations/update-23-0-0/migrate-jest-executor-setup-file.md +169 -0
- package/dist/src/utils/assert-supported-jest-version.d.ts +2 -0
- package/dist/src/utils/assert-supported-jest-version.js +11 -0
- package/dist/src/utils/versions.d.ts +13 -2
- package/dist/src/utils/versions.js +26 -46
- package/migrations.json +29 -8
- package/package.json +16 -4
- package/dist/src/utils/version-utils.d.ts +0 -2
- package/dist/src/utils/version-utils.js +0 -18
|
@@ -42,7 +42,6 @@ function getExtraArgs(options, schema) {
|
|
|
42
42
|
return extraArgs;
|
|
43
43
|
}
|
|
44
44
|
async function parseJestConfig(options, context, multiProjects = false) {
|
|
45
|
-
let jestConfig;
|
|
46
45
|
// support passing extra args to jest cli supporting 3rd party plugins
|
|
47
46
|
// like 'jest-runner-groups' --group arg
|
|
48
47
|
const extraArgs = getExtraArgs(options, schema_json_1.default);
|
|
@@ -84,15 +83,6 @@ async function parseJestConfig(options, context, multiProjects = false) {
|
|
|
84
83
|
};
|
|
85
84
|
if (!multiProjects) {
|
|
86
85
|
options.jestConfig = path.resolve(context.root, options.jestConfig);
|
|
87
|
-
jestConfig = (await (0, jest_config_1.readConfig)(config, options.jestConfig)).projectConfig;
|
|
88
|
-
}
|
|
89
|
-
// for backwards compatibility
|
|
90
|
-
if (options.setupFile && !multiProjects) {
|
|
91
|
-
const setupFilesAfterEnvSet = new Set([
|
|
92
|
-
...(jestConfig.setupFilesAfterEnv ?? []),
|
|
93
|
-
path.resolve(context.root, options.setupFile),
|
|
94
|
-
]);
|
|
95
|
-
config.setupFilesAfterEnv = Array.from(setupFilesAfterEnvSet);
|
|
96
86
|
}
|
|
97
87
|
if (options.testFile) {
|
|
98
88
|
config._.push(options.testFile);
|
|
@@ -37,11 +37,4 @@ export interface JestExecutorOptions {
|
|
|
37
37
|
watchAll?: boolean;
|
|
38
38
|
testLocationInResults?: boolean;
|
|
39
39
|
testTimeout?: number;
|
|
40
|
-
|
|
41
|
-
/**
|
|
42
|
-
* @deprecated Use the `setupFilesAfterEnv` option in the Jest configuration
|
|
43
|
-
* file instead. See https://jestjs.io/docs/configuration#setupfilesafterenv-array.
|
|
44
|
-
* It will be removed in Nx v22.
|
|
45
|
-
*/
|
|
46
|
-
setupFile?: string;
|
|
47
40
|
}
|
|
@@ -66,11 +66,6 @@
|
|
|
66
66
|
"x-completion-type": "file",
|
|
67
67
|
"x-completion-glob": "tsconfig.*.json"
|
|
68
68
|
},
|
|
69
|
-
"setupFile": {
|
|
70
|
-
"description": "The name of a setup file used by Jest.",
|
|
71
|
-
"type": "string",
|
|
72
|
-
"x-deprecated": "Use the `setupFilesAfterEnv` option in the Jest configuration file instead. See https://jestjs.io/docs/configuration#setupfilesafterenv-array. It will be removed in Nx v22."
|
|
73
|
-
},
|
|
74
69
|
"bail": {
|
|
75
70
|
"alias": "b",
|
|
76
71
|
"description": "Exit the test suite immediately after `n` number of failing tests. (https://jestjs.io/docs/cli#--bail)",
|
|
@@ -8,6 +8,7 @@ const js_1 = require("@nx/js");
|
|
|
8
8
|
const internal_2 = require("@nx/js/internal");
|
|
9
9
|
const config_file_1 = require("../../utils/config/config-file");
|
|
10
10
|
const init_1 = require("../init/init");
|
|
11
|
+
const assert_supported_jest_version_1 = require("../../utils/assert-supported-jest-version");
|
|
11
12
|
const deprecation_1 = require("../../utils/deprecation");
|
|
12
13
|
const check_for_test_target_1 = require("./lib/check-for-test-target");
|
|
13
14
|
const create_files_1 = require("./lib/create-files");
|
|
@@ -20,7 +21,6 @@ const schemaDefaults = {
|
|
|
20
21
|
setupFile: 'none',
|
|
21
22
|
babelJest: false,
|
|
22
23
|
supportTsx: false,
|
|
23
|
-
skipSetupFile: false,
|
|
24
24
|
skipSerializers: false,
|
|
25
25
|
testEnvironment: 'jsdom',
|
|
26
26
|
};
|
|
@@ -42,10 +42,6 @@ function normalizeOptions(tree, options) {
|
|
|
42
42
|
['swc', 'babel'].includes(options.compiler)) {
|
|
43
43
|
options.skipSerializers = true;
|
|
44
44
|
}
|
|
45
|
-
if (options.skipSetupFile) {
|
|
46
|
-
// setupFile is always 'none'
|
|
47
|
-
options.setupFile = schemaDefaults.setupFile;
|
|
48
|
-
}
|
|
49
45
|
const project = (0, devkit_1.readProjectConfiguration)(tree, options.project);
|
|
50
46
|
return {
|
|
51
47
|
...schemaDefaults,
|
|
@@ -59,6 +55,7 @@ function configurationGenerator(tree, schema) {
|
|
|
59
55
|
return configurationGeneratorInternal(tree, { addPlugin: false, ...schema });
|
|
60
56
|
}
|
|
61
57
|
async function configurationGeneratorInternal(tree, schema) {
|
|
58
|
+
(0, assert_supported_jest_version_1.assertSupportedJestVersion)(tree);
|
|
62
59
|
const options = normalizeOptions(tree, schema);
|
|
63
60
|
// we'll only add the vscode recommended extension if the jest preset does
|
|
64
61
|
// not exist, which most likely means this is a first run, in the cases it's
|
|
@@ -32,5 +32,5 @@ function ensureDependencies(tree, options) {
|
|
|
32
32
|
else if (options.compiler === 'swc') {
|
|
33
33
|
devDeps['@swc/jest'] = swcJestVersion;
|
|
34
34
|
}
|
|
35
|
-
return (0, devkit_1.addDependenciesToPackageJson)(tree, dependencies, devDeps, undefined, options.keepExistingVersions);
|
|
35
|
+
return (0, devkit_1.addDependenciesToPackageJson)(tree, dependencies, devDeps, undefined, options.keepExistingVersions ?? true);
|
|
36
36
|
}
|
|
@@ -26,10 +26,6 @@ export interface JestProjectSchema {
|
|
|
26
26
|
* @deprecated Use the `compiler` option instead. It will be removed in Nx v22.
|
|
27
27
|
*/
|
|
28
28
|
babelJest?: boolean;
|
|
29
|
-
/**
|
|
30
|
-
* @deprecated Use the `setupFile` option instead. It will be removed in Nx v22.
|
|
31
|
-
*/
|
|
32
|
-
skipSetupFile?: boolean;
|
|
33
29
|
keepExistingVersions?: boolean;
|
|
34
30
|
}
|
|
35
31
|
|
|
@@ -14,12 +14,6 @@
|
|
|
14
14
|
},
|
|
15
15
|
"x-priority": "important"
|
|
16
16
|
},
|
|
17
|
-
"skipSetupFile": {
|
|
18
|
-
"type": "boolean",
|
|
19
|
-
"description": "Skips the setup file required for angular.",
|
|
20
|
-
"default": false,
|
|
21
|
-
"x-deprecated": "Use the `setupFile` option instead. It will be removed in Nx v22."
|
|
22
|
-
},
|
|
23
17
|
"setupFile": {
|
|
24
18
|
"type": "string",
|
|
25
19
|
"enum": ["none", "angular", "web-components"],
|
|
@@ -7,8 +7,10 @@ const jest_config_1 = require("jest-config");
|
|
|
7
7
|
const node_path_1 = require("node:path");
|
|
8
8
|
const plugin_1 = require("../../plugins/plugin");
|
|
9
9
|
const config_file_1 = require("../../utils/config/config-file");
|
|
10
|
+
const assert_supported_jest_version_1 = require("../../utils/assert-supported-jest-version");
|
|
10
11
|
const versions_1 = require("../../utils/versions");
|
|
11
12
|
async function convertToInferred(tree, options) {
|
|
13
|
+
(0, assert_supported_jest_version_1.assertSupportedJestVersion)(tree);
|
|
12
14
|
const projectGraph = await (0, devkit_1.createProjectGraphAsync)();
|
|
13
15
|
const migratedProjects = await (0, internal_1.migrateProjectExecutorsToPlugin)(tree, projectGraph, '@nx/jest/plugin', plugin_1.createNodesV2, { targetName: 'test' }, [
|
|
14
16
|
{
|
|
@@ -6,6 +6,7 @@ const internal_1 = require("@nx/devkit/internal");
|
|
|
6
6
|
const devkit_1 = require("@nx/devkit");
|
|
7
7
|
const plugin_1 = require("../../plugins/plugin");
|
|
8
8
|
const config_file_1 = require("../../utils/config/config-file");
|
|
9
|
+
const assert_supported_jest_version_1 = require("../../utils/assert-supported-jest-version");
|
|
9
10
|
const versions_1 = require("../../utils/versions");
|
|
10
11
|
function updateProductionFileSet(tree) {
|
|
11
12
|
const nxJson = (0, devkit_1.readNxJson)(tree);
|
|
@@ -94,16 +95,13 @@ function updateDependencies(tree, options) {
|
|
|
94
95
|
return (0, devkit_1.addDependenciesToPackageJson)(tree, {}, {
|
|
95
96
|
'@nx/jest': nxVersion,
|
|
96
97
|
jest: jestVersion,
|
|
97
|
-
}, undefined, options.keepExistingVersions);
|
|
98
|
+
}, undefined, options.keepExistingVersions ?? true);
|
|
98
99
|
}
|
|
99
100
|
function jestInitGenerator(tree, options) {
|
|
100
101
|
return jestInitGeneratorInternal(tree, { addPlugin: false, ...options });
|
|
101
102
|
}
|
|
102
103
|
async function jestInitGeneratorInternal(tree, options) {
|
|
103
|
-
|
|
104
|
-
if (installedJestVersion) {
|
|
105
|
-
(0, versions_1.validateInstalledJestVersion)(tree);
|
|
106
|
-
}
|
|
104
|
+
(0, assert_supported_jest_version_1.assertSupportedJestVersion)(tree);
|
|
107
105
|
const nxJson = (0, devkit_1.readNxJson)(tree);
|
|
108
106
|
const addPluginDefault = process.env.NX_ADD_PLUGINS !== 'false' &&
|
|
109
107
|
nxJson.useInferencePlugins !== false;
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.default = default_1;
|
|
4
|
+
const devkit_1 = require("@nx/devkit");
|
|
5
|
+
const GENERATOR_NAME = '@nx/jest:configuration';
|
|
6
|
+
const PACKAGE = '@nx/jest';
|
|
7
|
+
const GENERATOR = 'configuration';
|
|
8
|
+
const SKIP_SETUP_FILE = 'skipSetupFile';
|
|
9
|
+
const SETUP_FILE = 'setupFile';
|
|
10
|
+
// Migrate the deprecated `skipSetupFile` option of `@nx/jest:configuration`
|
|
11
|
+
// generator defaults. `skipSetupFile: true` was equivalent to setting
|
|
12
|
+
// `setupFile: 'none'`, so rewrite to that. `skipSetupFile: false` was a no-op
|
|
13
|
+
// — drop it. Run on both `nx.json` `generators` and per-project
|
|
14
|
+
// `project.json` `generators`, in both flat (`@nx/jest:configuration`) and
|
|
15
|
+
// nested (`@nx/jest` → `configuration`) forms.
|
|
16
|
+
async function default_1(tree) {
|
|
17
|
+
const nxJson = (0, devkit_1.readNxJson)(tree);
|
|
18
|
+
if (nxJson?.generators && transformGenerators(nxJson.generators)) {
|
|
19
|
+
(0, devkit_1.updateNxJson)(tree, nxJson);
|
|
20
|
+
}
|
|
21
|
+
for (const [projectName, projectConfig] of (0, devkit_1.getProjects)(tree)) {
|
|
22
|
+
if (projectConfig.generators &&
|
|
23
|
+
transformGenerators(projectConfig.generators)) {
|
|
24
|
+
(0, devkit_1.updateProjectConfiguration)(tree, projectName, projectConfig);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
await (0, devkit_1.formatFiles)(tree);
|
|
28
|
+
}
|
|
29
|
+
function transformGenerators(generators) {
|
|
30
|
+
let changed = false;
|
|
31
|
+
if (transformDefaults(generators[GENERATOR_NAME])) {
|
|
32
|
+
if (Object.keys(generators[GENERATOR_NAME]).length === 0) {
|
|
33
|
+
delete generators[GENERATOR_NAME];
|
|
34
|
+
}
|
|
35
|
+
changed = true;
|
|
36
|
+
}
|
|
37
|
+
const nested = generators[PACKAGE];
|
|
38
|
+
if (nested &&
|
|
39
|
+
typeof nested === 'object' &&
|
|
40
|
+
transformDefaults(nested[GENERATOR])) {
|
|
41
|
+
if (nested[GENERATOR] && Object.keys(nested[GENERATOR]).length === 0) {
|
|
42
|
+
delete nested[GENERATOR];
|
|
43
|
+
}
|
|
44
|
+
if (Object.keys(nested).length === 0) {
|
|
45
|
+
delete generators[PACKAGE];
|
|
46
|
+
}
|
|
47
|
+
changed = true;
|
|
48
|
+
}
|
|
49
|
+
return changed;
|
|
50
|
+
}
|
|
51
|
+
function transformDefaults(defaults) {
|
|
52
|
+
if (!defaults || typeof defaults !== 'object')
|
|
53
|
+
return false;
|
|
54
|
+
if (!(SKIP_SETUP_FILE in defaults))
|
|
55
|
+
return false;
|
|
56
|
+
if (defaults[SKIP_SETUP_FILE] === true &&
|
|
57
|
+
defaults[SETUP_FILE] === undefined) {
|
|
58
|
+
defaults[SETUP_FILE] = 'none';
|
|
59
|
+
}
|
|
60
|
+
delete defaults[SKIP_SETUP_FILE];
|
|
61
|
+
return true;
|
|
62
|
+
}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
#### Migrate `skipSetupFile` Generator Default to `setupFile`
|
|
2
|
+
|
|
3
|
+
Migrates the previously deprecated `skipSetupFile` option of the `@nx/jest:configuration` generator. When set as a default in `nx.json` `generators` or per-project `project.json` `generators`, it is rewritten as follows:
|
|
4
|
+
|
|
5
|
+
- `skipSetupFile: true` becomes `setupFile: 'none'` (preserving the original behavior of skipping the setup file). Existing `setupFile` values are left untouched.
|
|
6
|
+
- `skipSetupFile: false` is dropped (it was a no-op).
|
|
7
|
+
|
|
8
|
+
Both flat (`@nx/jest:configuration`) and nested (`@nx/jest` → `configuration`) forms are handled.
|
|
9
|
+
|
|
10
|
+
#### Examples
|
|
11
|
+
|
|
12
|
+
Rewrite a `nx.json` generator default:
|
|
13
|
+
|
|
14
|
+
##### Before
|
|
15
|
+
|
|
16
|
+
```json title="nx.json" {4}
|
|
17
|
+
{
|
|
18
|
+
"generators": {
|
|
19
|
+
"@nx/jest:configuration": {
|
|
20
|
+
"skipSetupFile": true
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
##### After
|
|
27
|
+
|
|
28
|
+
```json title="nx.json"
|
|
29
|
+
{
|
|
30
|
+
"generators": {
|
|
31
|
+
"@nx/jest:configuration": {
|
|
32
|
+
"setupFile": "none"
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
Drop the option when set to `false`:
|
|
39
|
+
|
|
40
|
+
##### Before
|
|
41
|
+
|
|
42
|
+
```json title="nx.json" {4}
|
|
43
|
+
{
|
|
44
|
+
"generators": {
|
|
45
|
+
"@nx/jest:configuration": {
|
|
46
|
+
"skipSetupFile": false,
|
|
47
|
+
"testEnvironment": "jsdom"
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
##### After
|
|
54
|
+
|
|
55
|
+
```json title="nx.json"
|
|
56
|
+
{
|
|
57
|
+
"generators": {
|
|
58
|
+
"@nx/jest:configuration": {
|
|
59
|
+
"testEnvironment": "jsdom"
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
Rewrite a per-project generator default:
|
|
66
|
+
|
|
67
|
+
##### Before
|
|
68
|
+
|
|
69
|
+
```json title="apps/myapp/project.json" {4}
|
|
70
|
+
{
|
|
71
|
+
"generators": {
|
|
72
|
+
"@nx/jest:configuration": {
|
|
73
|
+
"skipSetupFile": true
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
##### After
|
|
80
|
+
|
|
81
|
+
```json title="apps/myapp/project.json"
|
|
82
|
+
{
|
|
83
|
+
"generators": {
|
|
84
|
+
"@nx/jest:configuration": {
|
|
85
|
+
"setupFile": "none"
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
The nested form (`@nx/jest` → `configuration`) is handled the same way.
|
|
@@ -0,0 +1,476 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.default = default_1;
|
|
4
|
+
const internal_1 = require("@nx/devkit/internal");
|
|
5
|
+
const devkit_1 = require("@nx/devkit");
|
|
6
|
+
const internal_2 = require("@nx/js/internal");
|
|
7
|
+
const devkit_internals_1 = require("nx/src/devkit-internals");
|
|
8
|
+
const project_configuration_utils_1 = require("nx/src/project-graph/utils/project-configuration-utils");
|
|
9
|
+
const path_1 = require("path");
|
|
10
|
+
const functions_1 = require("../../utils/config/functions");
|
|
11
|
+
const EXECUTOR_TO_MIGRATE = '@nx/jest:jest';
|
|
12
|
+
const ROOT_DIR_TOKEN = '<rootDir>';
|
|
13
|
+
const SETUP_FILES_AFTER_ENV = 'setupFilesAfterEnv';
|
|
14
|
+
const SETUP_FILE = 'setupFile';
|
|
15
|
+
const JEST_CONFIG = 'jestConfig';
|
|
16
|
+
const ROOT_DIR = 'rootDir';
|
|
17
|
+
let tsModule;
|
|
18
|
+
async function default_1(tree) {
|
|
19
|
+
const warnLists = {
|
|
20
|
+
unparseable: [],
|
|
21
|
+
nonLiteralRootDir: [],
|
|
22
|
+
sharedConfigConflict: [],
|
|
23
|
+
passthroughCollision: [],
|
|
24
|
+
configurationOnly: [],
|
|
25
|
+
noResolvableJestConfig: [],
|
|
26
|
+
};
|
|
27
|
+
// configPath -> the setupFile string the AST rewrite committed for it.
|
|
28
|
+
const rewrittenJestConfigs = new Map();
|
|
29
|
+
// `${project}::${target}` -> base setupFile snapshotted before mutation.
|
|
30
|
+
const baseSetupFiles = new Map();
|
|
31
|
+
// Per-project ProjectConfiguration cache so multi-target / multi-configuration
|
|
32
|
+
// projects don't re-read + re-write project.json on every callback iteration.
|
|
33
|
+
const projectConfigCache = new Map();
|
|
34
|
+
const dirtyProjects = new Set();
|
|
35
|
+
const nxJson = (0, devkit_1.readNxJson)(tree);
|
|
36
|
+
(0, internal_1.forEachExecutorOptions)(tree, EXECUTOR_TO_MIGRATE, (snapshotOptions, project, target, configuration) => {
|
|
37
|
+
if (configuration === undefined &&
|
|
38
|
+
snapshotOptions.setupFile !== undefined) {
|
|
39
|
+
baseSetupFiles.set(`${project}::${target}`, snapshotOptions.setupFile);
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
(0, internal_1.forEachExecutorOptions)(tree, EXECUTOR_TO_MIGRATE, (options, project, target, configuration) => {
|
|
43
|
+
if (options.setupFile === undefined) {
|
|
44
|
+
// Configuration passthrough that inherits the base setupFile would
|
|
45
|
+
// silently override the migrated value at runtime — warn so the user
|
|
46
|
+
// can consolidate.
|
|
47
|
+
if (configuration !== undefined &&
|
|
48
|
+
options.setupFilesAfterEnv !== undefined &&
|
|
49
|
+
baseSetupFiles.has(`${project}::${target}`)) {
|
|
50
|
+
warnLists.passthroughCollision.push(formatLocation({ project, target, configuration }));
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
// Base target inheriting `setupFile` from `nx.json` `targetDefaults`
|
|
54
|
+
// (no own value). The defaults strip-pass would otherwise leave the
|
|
55
|
+
// jest config with no setup file at runtime — migrate now using the
|
|
56
|
+
// inherited value.
|
|
57
|
+
if (configuration === undefined) {
|
|
58
|
+
migrateInheritedSetupFile(tree, project, target, nxJson, projectConfigCache, rewrittenJestConfigs, warnLists);
|
|
59
|
+
}
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
const projectConfiguration = getProjectConfig(tree, project, projectConfigCache);
|
|
63
|
+
const targetOptions = projectConfiguration.targets[target]?.options;
|
|
64
|
+
const baseSetupFile = baseSetupFiles.get(`${project}::${target}`);
|
|
65
|
+
const jestConfigPath = resolveJestConfigPath(options.jestConfig, targetOptions?.jestConfig, projectConfiguration.root, target, nxJson);
|
|
66
|
+
const location = {
|
|
67
|
+
project,
|
|
68
|
+
target,
|
|
69
|
+
configuration,
|
|
70
|
+
jestConfig: jestConfigPath,
|
|
71
|
+
};
|
|
72
|
+
const hasPassthroughInScope = options.setupFilesAfterEnv !== undefined ||
|
|
73
|
+
(configuration !== undefined &&
|
|
74
|
+
targetOptions?.setupFilesAfterEnv !== undefined);
|
|
75
|
+
if (hasPassthroughInScope) {
|
|
76
|
+
warnLists.passthroughCollision.push(formatLocation(location));
|
|
77
|
+
}
|
|
78
|
+
else if (configuration !== undefined &&
|
|
79
|
+
baseSetupFile !== options.setupFile) {
|
|
80
|
+
// Configuration's setupFile diverges from base. When the configuration
|
|
81
|
+
// also overrides `jestConfig` (separate file), we can write the setup
|
|
82
|
+
// file there without leaking to the base run. Otherwise the only safe
|
|
83
|
+
// move is to bail: writing into a shared jest config would make the
|
|
84
|
+
// configuration's setup file run for every invocation.
|
|
85
|
+
if (options.jestConfig !== undefined && jestConfigPath) {
|
|
86
|
+
migrateOneJestConfig(tree, jestConfigPath, options.setupFile, location, rewrittenJestConfigs, warnLists);
|
|
87
|
+
}
|
|
88
|
+
else {
|
|
89
|
+
warnLists.configurationOnly.push(formatLocation(location));
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
else if (!jestConfigPath) {
|
|
93
|
+
warnLists.noResolvableJestConfig.push(formatLocation(location));
|
|
94
|
+
}
|
|
95
|
+
else {
|
|
96
|
+
migrateOneJestConfig(tree, jestConfigPath, options.setupFile, location, rewrittenJestConfigs, warnLists);
|
|
97
|
+
if (configuration === undefined) {
|
|
98
|
+
migrateInheritingConfigurations(tree, projectConfiguration, target, options.setupFile, jestConfigPath, location, rewrittenJestConfigs, warnLists);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
if (configuration) {
|
|
102
|
+
stripFromConfiguration(projectConfiguration.targets[target], configuration);
|
|
103
|
+
}
|
|
104
|
+
else {
|
|
105
|
+
stripFromOptions(projectConfiguration.targets[target]);
|
|
106
|
+
}
|
|
107
|
+
dirtyProjects.add(project);
|
|
108
|
+
});
|
|
109
|
+
for (const project of dirtyProjects) {
|
|
110
|
+
(0, devkit_1.updateProjectConfiguration)(tree, project, projectConfigCache.get(project));
|
|
111
|
+
}
|
|
112
|
+
const nxJsonHadSetupFile = stripSetupFileFromNxJson(tree, nxJson);
|
|
113
|
+
await (0, devkit_1.formatFiles)(tree);
|
|
114
|
+
return buildFollowUp(warnLists, nxJsonHadSetupFile);
|
|
115
|
+
}
|
|
116
|
+
function getProjectConfig(tree, project, cache) {
|
|
117
|
+
let cached = cache.get(project);
|
|
118
|
+
if (!cached) {
|
|
119
|
+
cached = (0, devkit_1.readProjectConfiguration)(tree, project);
|
|
120
|
+
cache.set(project, cached);
|
|
121
|
+
}
|
|
122
|
+
return cached;
|
|
123
|
+
}
|
|
124
|
+
function migrateInheritingConfigurations(tree, projectConfiguration, target, baseSetupFile, baseJestConfigPath, baseLocation, rewrittenJestConfigs, warnLists) {
|
|
125
|
+
const configurations = projectConfiguration.targets[target]?.configurations ?? {};
|
|
126
|
+
for (const [configName, rawConfigOptions] of Object.entries(configurations)) {
|
|
127
|
+
const configOptions = rawConfigOptions;
|
|
128
|
+
if (configOptions.setupFile !== undefined)
|
|
129
|
+
continue;
|
|
130
|
+
if (configOptions.jestConfig === undefined)
|
|
131
|
+
continue;
|
|
132
|
+
const configJestConfigPath = expandWorkspaceRelativePath(configOptions.jestConfig, projectConfiguration.root);
|
|
133
|
+
if (configJestConfigPath === baseJestConfigPath)
|
|
134
|
+
continue;
|
|
135
|
+
migrateOneJestConfig(tree, configJestConfigPath, baseSetupFile, {
|
|
136
|
+
...baseLocation,
|
|
137
|
+
configuration: configName,
|
|
138
|
+
jestConfig: configJestConfigPath,
|
|
139
|
+
}, rewrittenJestConfigs, warnLists);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
function migrateOneJestConfig(tree, jestConfigPath, setupFile, location, rewrittenJestConfigs, warnLists) {
|
|
143
|
+
const previouslyMigrated = rewrittenJestConfigs.get(jestConfigPath);
|
|
144
|
+
if (previouslyMigrated !== undefined) {
|
|
145
|
+
if (previouslyMigrated !== setupFile) {
|
|
146
|
+
warnLists.sharedConfigConflict.push(formatLocation(location));
|
|
147
|
+
}
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
const result = pushSetupFileIntoJestConfig(tree, jestConfigPath, setupFile);
|
|
151
|
+
switch (result) {
|
|
152
|
+
case 'written':
|
|
153
|
+
case 'already-present':
|
|
154
|
+
rewrittenJestConfigs.set(jestConfigPath, setupFile);
|
|
155
|
+
break;
|
|
156
|
+
case 'custom-root-dir-non-literal':
|
|
157
|
+
warnLists.nonLiteralRootDir.push(formatLocation(location));
|
|
158
|
+
break;
|
|
159
|
+
case 'unparseable':
|
|
160
|
+
warnLists.unparseable.push(formatLocation(location));
|
|
161
|
+
break;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
// For a base target that doesn't declare its own `setupFile` but inherits
|
|
165
|
+
// one from `nx.json` `targetDefaults`, migrate the inherited value into the
|
|
166
|
+
// project's jest config — otherwise stripping `setupFile` from `nx.json`
|
|
167
|
+
// would silently drop the setup file for every inheriting target at runtime.
|
|
168
|
+
function migrateInheritedSetupFile(tree, project, target, nxJson, projectConfigCache, rewrittenJestConfigs, warnLists) {
|
|
169
|
+
if (!nxJson?.targetDefaults)
|
|
170
|
+
return;
|
|
171
|
+
const matched = (0, project_configuration_utils_1.readTargetDefaultsForTarget)(target, nxJson.targetDefaults, EXECUTOR_TO_MIGRATE);
|
|
172
|
+
const inheritedSetupFile = matched?.options?.[SETUP_FILE];
|
|
173
|
+
if (inheritedSetupFile === undefined)
|
|
174
|
+
return;
|
|
175
|
+
const projectConfiguration = getProjectConfig(tree, project, projectConfigCache);
|
|
176
|
+
const targetOptions = projectConfiguration.targets[target]?.options;
|
|
177
|
+
const expandedSetupFile = expandWorkspaceRelativePath(inheritedSetupFile, projectConfiguration.root);
|
|
178
|
+
const jestConfigPath = resolveJestConfigPath(undefined, targetOptions?.jestConfig, projectConfiguration.root, target, nxJson);
|
|
179
|
+
const location = {
|
|
180
|
+
project,
|
|
181
|
+
target,
|
|
182
|
+
jestConfig: jestConfigPath,
|
|
183
|
+
};
|
|
184
|
+
if (!jestConfigPath) {
|
|
185
|
+
warnLists.noResolvableJestConfig.push(formatLocation(location));
|
|
186
|
+
return;
|
|
187
|
+
}
|
|
188
|
+
migrateOneJestConfig(tree, jestConfigPath, expandedSetupFile, location, rewrittenJestConfigs, warnLists);
|
|
189
|
+
}
|
|
190
|
+
function stripSetupFileFromNxJson(tree, nxJson) {
|
|
191
|
+
if (!nxJson?.targetDefaults)
|
|
192
|
+
return false;
|
|
193
|
+
let changed = false;
|
|
194
|
+
let hadSetupFile = false;
|
|
195
|
+
for (const [targetOrExecutor, targetConfig] of Object.entries(nxJson.targetDefaults)) {
|
|
196
|
+
if (targetOrExecutor !== EXECUTOR_TO_MIGRATE &&
|
|
197
|
+
targetConfig.executor !== EXECUTOR_TO_MIGRATE) {
|
|
198
|
+
continue;
|
|
199
|
+
}
|
|
200
|
+
if (targetConfig.options?.setupFile !== undefined) {
|
|
201
|
+
hadSetupFile = true;
|
|
202
|
+
changed = true;
|
|
203
|
+
delete targetConfig.options.setupFile;
|
|
204
|
+
if (!Object.keys(targetConfig.options).length) {
|
|
205
|
+
delete targetConfig.options;
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
for (const config of Object.keys(targetConfig.configurations ?? {})) {
|
|
209
|
+
if (targetConfig.configurations[config]?.setupFile !== undefined) {
|
|
210
|
+
hadSetupFile = true;
|
|
211
|
+
changed = true;
|
|
212
|
+
delete targetConfig.configurations[config].setupFile;
|
|
213
|
+
if (!Object.keys(targetConfig.configurations[config]).length &&
|
|
214
|
+
(!targetConfig.defaultConfiguration ||
|
|
215
|
+
targetConfig.defaultConfiguration !== config)) {
|
|
216
|
+
delete targetConfig.configurations[config];
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
if (targetConfig.configurations &&
|
|
221
|
+
!Object.keys(targetConfig.configurations).length) {
|
|
222
|
+
delete targetConfig.configurations;
|
|
223
|
+
}
|
|
224
|
+
if (!Object.keys(targetConfig).length ||
|
|
225
|
+
(Object.keys(targetConfig).length === 1 &&
|
|
226
|
+
Object.keys(targetConfig)[0] === 'executor')) {
|
|
227
|
+
delete nxJson.targetDefaults[targetOrExecutor];
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
if (!Object.keys(nxJson.targetDefaults).length) {
|
|
231
|
+
delete nxJson.targetDefaults;
|
|
232
|
+
}
|
|
233
|
+
if (changed)
|
|
234
|
+
(0, devkit_1.updateNxJson)(tree, nxJson);
|
|
235
|
+
return hadSetupFile;
|
|
236
|
+
}
|
|
237
|
+
function buildFollowUp(warnLists, nxJsonHadSetupFile) {
|
|
238
|
+
const hasWarnings = warnLists.unparseable.length > 0 ||
|
|
239
|
+
warnLists.nonLiteralRootDir.length > 0 ||
|
|
240
|
+
warnLists.sharedConfigConflict.length > 0 ||
|
|
241
|
+
warnLists.passthroughCollision.length > 0 ||
|
|
242
|
+
warnLists.configurationOnly.length > 0 ||
|
|
243
|
+
warnLists.noResolvableJestConfig.length > 0 ||
|
|
244
|
+
nxJsonHadSetupFile;
|
|
245
|
+
if (!hasWarnings)
|
|
246
|
+
return;
|
|
247
|
+
return () => {
|
|
248
|
+
warn(warnLists.unparseable, 'The deprecated `setupFile` option of `@nx/jest:jest` was removed from the following targets, ' +
|
|
249
|
+
'but the corresponding Jest config could not be parsed automatically. Add the setup file path ' +
|
|
250
|
+
`manually to \`${SETUP_FILES_AFTER_ENV}\` in each Jest config:`);
|
|
251
|
+
warn(warnLists.nonLiteralRootDir, 'The deprecated `setupFile` option of `@nx/jest:jest` was removed from the following targets, ' +
|
|
252
|
+
'but their Jest config sets `rootDir` to a non-literal value (e.g. a function call or ' +
|
|
253
|
+
'imported variable) so the path could not be migrated automatically. Add the setup file path ' +
|
|
254
|
+
`to \`${SETUP_FILES_AFTER_ENV}\` in each Jest config using the correct \`rootDir\`-relative path:`);
|
|
255
|
+
warn(warnLists.sharedConfigConflict, 'The following targets reuse a Jest config that another target already migrated with a ' +
|
|
256
|
+
`different \`setupFile\`. Their \`setupFile\` was removed but not added to \`${SETUP_FILES_AFTER_ENV}\`, ` +
|
|
257
|
+
'since per-target setup files require separate Jest configs. Either give each target its own ' +
|
|
258
|
+
'Jest config or merge the setup files in the shared config:');
|
|
259
|
+
warn(warnLists.passthroughCollision, 'The following targets had both `setupFile` (now removed) and a `setupFilesAfterEnv` option in ' +
|
|
260
|
+
'the same scope. Pre-migration the executor was overriding the passthrough silently; ' +
|
|
261
|
+
'post-migration the passthrough wins, which may change behavior. Consolidate the setup files ' +
|
|
262
|
+
`manually under \`${SETUP_FILES_AFTER_ENV}\` in either the target options or the Jest config:`);
|
|
263
|
+
warn(warnLists.configurationOnly, 'The following targets declared `setupFile` only under a named configuration (or with a value ' +
|
|
264
|
+
"different from the base target's `setupFile`). Pre-migration that setup file ran only when " +
|
|
265
|
+
'the configuration was selected. Configuration-scoped setup files cannot be expressed in a ' +
|
|
266
|
+
'shared Jest config without leaking to the base run, so the option was removed without being ' +
|
|
267
|
+
'migrated. Add the setup file to a configuration-scoped Jest config or guard it via ' +
|
|
268
|
+
'`process.env.NX_TASK_TARGET_CONFIGURATION`:');
|
|
269
|
+
warn(warnLists.noResolvableJestConfig, 'The following targets had a `setupFile` option but no resolvable `jestConfig` (neither in the ' +
|
|
270
|
+
'target options nor in `nx.json` target defaults). The deprecated option was removed; add the ' +
|
|
271
|
+
`setup file path to \`${SETUP_FILES_AFTER_ENV}\` in the Jest config you intend the target to use:`);
|
|
272
|
+
if (nxJsonHadSetupFile) {
|
|
273
|
+
devkit_1.logger.warn('Removed the deprecated `setupFile` option from the `@nx/jest:jest` target defaults in `nx.json`. ' +
|
|
274
|
+
"If you relied on this default, add the setup file path to each project's Jest config under " +
|
|
275
|
+
`\`${SETUP_FILES_AFTER_ENV}\`.`);
|
|
276
|
+
}
|
|
277
|
+
};
|
|
278
|
+
}
|
|
279
|
+
function warn(items, header) {
|
|
280
|
+
if (items.length === 0)
|
|
281
|
+
return;
|
|
282
|
+
devkit_1.logger.warn(`${header}\n${items.map((p) => ` - ${p}`).join('\n')}`);
|
|
283
|
+
}
|
|
284
|
+
function formatLocation(loc) {
|
|
285
|
+
const targetRef = loc.configuration
|
|
286
|
+
? `${loc.target}:${loc.configuration}`
|
|
287
|
+
: loc.target;
|
|
288
|
+
const configPart = loc.jestConfig ? ` (${loc.jestConfig})` : '';
|
|
289
|
+
return `${loc.project} -> ${targetRef}${configPart}`;
|
|
290
|
+
}
|
|
291
|
+
function stripFromOptions(target) {
|
|
292
|
+
delete target.options.setupFile;
|
|
293
|
+
if (!Object.keys(target.options).length) {
|
|
294
|
+
delete target.options;
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
function stripFromConfiguration(target, configuration) {
|
|
298
|
+
delete target.configurations[configuration].setupFile;
|
|
299
|
+
if (!Object.keys(target.configurations[configuration]).length &&
|
|
300
|
+
(!target.defaultConfiguration ||
|
|
301
|
+
target.defaultConfiguration !== configuration)) {
|
|
302
|
+
delete target.configurations[configuration];
|
|
303
|
+
}
|
|
304
|
+
if (!Object.keys(target.configurations).length) {
|
|
305
|
+
delete target.configurations;
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
// Falls through `callbackOptions → targetOptions → nx.json defaults`,
|
|
309
|
+
// expanding `{projectRoot}` / `{workspaceRoot}` tokens via the canonical
|
|
310
|
+
// `interpolate` helper. Defaults lookup uses `readTargetDefaultsForTarget`
|
|
311
|
+
// for the canonical executor-key → target-name → glob-match precedence.
|
|
312
|
+
function resolveJestConfigPath(callbackJestConfig, targetJestConfig, projectRoot, target, nxJson) {
|
|
313
|
+
const explicit = callbackJestConfig ?? targetJestConfig;
|
|
314
|
+
if (explicit)
|
|
315
|
+
return expandWorkspaceRelativePath(explicit, projectRoot);
|
|
316
|
+
if (!nxJson?.targetDefaults)
|
|
317
|
+
return undefined;
|
|
318
|
+
const matched = (0, project_configuration_utils_1.readTargetDefaultsForTarget)(target, nxJson.targetDefaults, EXECUTOR_TO_MIGRATE);
|
|
319
|
+
const fromDefaults = matched?.options?.[JEST_CONFIG];
|
|
320
|
+
if (fromDefaults)
|
|
321
|
+
return expandWorkspaceRelativePath(fromDefaults, projectRoot);
|
|
322
|
+
return undefined;
|
|
323
|
+
}
|
|
324
|
+
function expandWorkspaceRelativePath(value, projectRoot) {
|
|
325
|
+
return path_1.posix.normalize((0, devkit_internals_1.interpolate)(value, {
|
|
326
|
+
projectRoot: projectRoot || '.',
|
|
327
|
+
workspaceRoot: '.',
|
|
328
|
+
}));
|
|
329
|
+
}
|
|
330
|
+
function pushSetupFileIntoJestConfig(tree, jestConfigPath, setupFileFromOptions) {
|
|
331
|
+
if (!tree.exists(jestConfigPath))
|
|
332
|
+
return 'unparseable';
|
|
333
|
+
const content = tree.read(jestConfigPath, 'utf-8');
|
|
334
|
+
if (!content)
|
|
335
|
+
return 'unparseable';
|
|
336
|
+
if (!tsModule) {
|
|
337
|
+
tsModule = (0, internal_2.ensureTypescript)();
|
|
338
|
+
}
|
|
339
|
+
let configObject;
|
|
340
|
+
try {
|
|
341
|
+
configObject = (0, functions_1.jestConfigObjectAst)(content);
|
|
342
|
+
}
|
|
343
|
+
catch {
|
|
344
|
+
return 'unparseable';
|
|
345
|
+
}
|
|
346
|
+
const configDir = path_1.posix.dirname(jestConfigPath);
|
|
347
|
+
const rootDirInfo = computeEffectiveRootDir(configDir, configObject);
|
|
348
|
+
if (rootDirInfo.kind === 'non-literal') {
|
|
349
|
+
return 'custom-root-dir-non-literal';
|
|
350
|
+
}
|
|
351
|
+
const effectiveRootDir = rootDirInfo.absolute;
|
|
352
|
+
const setupFileWithRootDir = toRootDirRelative(effectiveRootDir, setupFileFromOptions);
|
|
353
|
+
const properties = configObject.properties;
|
|
354
|
+
const existingIndex = properties.findIndex((p) => tsModule.isPropertyAssignment(p) &&
|
|
355
|
+
getPropertyName(p) === SETUP_FILES_AFTER_ENV);
|
|
356
|
+
const spreadIndices = properties
|
|
357
|
+
.map((p, i) => (tsModule.isSpreadAssignment(p) ? i : -1))
|
|
358
|
+
.filter((i) => i >= 0);
|
|
359
|
+
if (existingIndex >= 0) {
|
|
360
|
+
if (spreadIndices.some((i) => i > existingIndex)) {
|
|
361
|
+
return 'unparseable';
|
|
362
|
+
}
|
|
363
|
+
const existing = properties[existingIndex];
|
|
364
|
+
if (!tsModule.isArrayLiteralExpression(existing.initializer)) {
|
|
365
|
+
return 'unparseable';
|
|
366
|
+
}
|
|
367
|
+
const arr = existing.initializer;
|
|
368
|
+
const newPathResolved = resolveJestPath(setupFileWithRootDir, configDir, effectiveRootDir);
|
|
369
|
+
const alreadyPresent = arr.elements.some((e) => tsModule.isStringLiteral(e) &&
|
|
370
|
+
resolveJestPath(e.text, configDir, effectiveRootDir) === newPathResolved);
|
|
371
|
+
if (alreadyPresent)
|
|
372
|
+
return 'already-present';
|
|
373
|
+
const insertPos = arr.getEnd() - 1; // position of `]`
|
|
374
|
+
const hasElements = arr.elements.length > 0;
|
|
375
|
+
let newContent;
|
|
376
|
+
if (hasElements) {
|
|
377
|
+
const lastElement = arr.elements[arr.elements.length - 1];
|
|
378
|
+
const between = content.slice(lastElement.getEnd(), insertPos);
|
|
379
|
+
const hasTrailingComma = /,/.test(between);
|
|
380
|
+
const sep = hasTrailingComma ? ' ' : ', ';
|
|
381
|
+
newContent =
|
|
382
|
+
content.slice(0, insertPos) +
|
|
383
|
+
`${sep}'${setupFileWithRootDir}'` +
|
|
384
|
+
content.slice(insertPos);
|
|
385
|
+
}
|
|
386
|
+
else {
|
|
387
|
+
newContent =
|
|
388
|
+
content.slice(0, insertPos) +
|
|
389
|
+
`'${setupFileWithRootDir}'` +
|
|
390
|
+
content.slice(insertPos);
|
|
391
|
+
}
|
|
392
|
+
tree.write(jestConfigPath, newContent);
|
|
393
|
+
return 'written';
|
|
394
|
+
}
|
|
395
|
+
// Object-spread "last wins": mirror it with a nullish-coalescing fallback
|
|
396
|
+
// ordered last-spread-first so the emitted property resolves to the same
|
|
397
|
+
// array the runtime would have seen pre-migration. `as any` lets the chain
|
|
398
|
+
// compile when the spread source's type omits `setupFilesAfterEnv`.
|
|
399
|
+
const spreadExpressions = properties
|
|
400
|
+
.filter((p) => tsModule.isSpreadAssignment(p))
|
|
401
|
+
.map((p) => p.expression.getText());
|
|
402
|
+
const isTs = /\.(c|m)?tsx?$/.test(jestConfigPath);
|
|
403
|
+
const wrap = (expr) => isTs
|
|
404
|
+
? `((${expr}) as any)?.${SETUP_FILES_AFTER_ENV}`
|
|
405
|
+
: `(${expr})?.${SETUP_FILES_AFTER_ENV}`;
|
|
406
|
+
let spreadElement;
|
|
407
|
+
if (spreadExpressions.length === 1) {
|
|
408
|
+
spreadElement = `...${wrap(spreadExpressions[0])} ?? []`;
|
|
409
|
+
}
|
|
410
|
+
else if (spreadExpressions.length > 1) {
|
|
411
|
+
const fallbacks = [...spreadExpressions].reverse().map(wrap);
|
|
412
|
+
spreadElement = `...(${fallbacks.join(' ?? ')} ?? [])`;
|
|
413
|
+
}
|
|
414
|
+
const arrayLiteral = spreadElement
|
|
415
|
+
? `[${spreadElement}, '${setupFileWithRootDir}']`
|
|
416
|
+
: `['${setupFileWithRootDir}']`;
|
|
417
|
+
const newProp = `${SETUP_FILES_AFTER_ENV}: ${arrayLiteral}`;
|
|
418
|
+
const insertPos = configObject.getEnd() - 1; // position of `}`
|
|
419
|
+
const hasProps = properties.length > 0;
|
|
420
|
+
let insertion;
|
|
421
|
+
if (hasProps) {
|
|
422
|
+
const lastProp = properties[properties.length - 1];
|
|
423
|
+
const between = content.slice(lastProp.getEnd(), insertPos);
|
|
424
|
+
const hasTrailingComma = /,/.test(between);
|
|
425
|
+
insertion = hasTrailingComma ? ` ${newProp},` : `, ${newProp}`;
|
|
426
|
+
}
|
|
427
|
+
else {
|
|
428
|
+
insertion = newProp;
|
|
429
|
+
}
|
|
430
|
+
const newContent = content.slice(0, insertPos) + insertion + content.slice(insertPos);
|
|
431
|
+
tree.write(jestConfigPath, newContent);
|
|
432
|
+
return 'written';
|
|
433
|
+
}
|
|
434
|
+
function computeEffectiveRootDir(configDir, configObject) {
|
|
435
|
+
const rootDirNode = configObject.properties.find((p) => tsModule.isPropertyAssignment(p) && getPropertyName(p) === ROOT_DIR);
|
|
436
|
+
if (!rootDirNode) {
|
|
437
|
+
return { kind: 'static', absolute: configDir };
|
|
438
|
+
}
|
|
439
|
+
const initializer = rootDirNode.initializer;
|
|
440
|
+
if (tsModule.isStringLiteral(initializer) ||
|
|
441
|
+
tsModule.isNoSubstitutionTemplateLiteral(initializer)) {
|
|
442
|
+
const value = initializer.text;
|
|
443
|
+
if (path_1.posix.isAbsolute(value))
|
|
444
|
+
return { kind: 'non-literal' };
|
|
445
|
+
return {
|
|
446
|
+
kind: 'static',
|
|
447
|
+
absolute: path_1.posix.normalize(path_1.posix.join(configDir, value)),
|
|
448
|
+
};
|
|
449
|
+
}
|
|
450
|
+
return { kind: 'non-literal' };
|
|
451
|
+
}
|
|
452
|
+
function getPropertyName(p) {
|
|
453
|
+
if (tsModule.isIdentifier(p.name) ||
|
|
454
|
+
tsModule.isStringLiteral(p.name) ||
|
|
455
|
+
tsModule.isNoSubstitutionTemplateLiteral(p.name)) {
|
|
456
|
+
return p.name.text;
|
|
457
|
+
}
|
|
458
|
+
return undefined;
|
|
459
|
+
}
|
|
460
|
+
function toRootDirRelative(effectiveRootDir, workspacePath) {
|
|
461
|
+
return `${ROOT_DIR_TOKEN}/${path_1.posix.relative(effectiveRootDir, workspacePath)}`;
|
|
462
|
+
}
|
|
463
|
+
// Normalize a `setupFilesAfterEnv` entry to a workspace-root-relative path
|
|
464
|
+
// for dedup. Handles `<rootDir>/...`, `./...`, and absolute strings.
|
|
465
|
+
function resolveJestPath(rawValue, configDir, rootDir) {
|
|
466
|
+
if (rawValue.startsWith(ROOT_DIR_TOKEN)) {
|
|
467
|
+
const rest = rawValue.slice(ROOT_DIR_TOKEN.length).replace(/^\/+/, '');
|
|
468
|
+
return path_1.posix.normalize(path_1.posix.join(rootDir, rest));
|
|
469
|
+
}
|
|
470
|
+
if (path_1.posix.isAbsolute(rawValue))
|
|
471
|
+
return rawValue;
|
|
472
|
+
if (rawValue.startsWith('./') || rawValue.startsWith('../')) {
|
|
473
|
+
return path_1.posix.normalize(path_1.posix.join(configDir, rawValue));
|
|
474
|
+
}
|
|
475
|
+
return rawValue;
|
|
476
|
+
}
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
#### Migrate `setupFile` Option to `setupFilesAfterEnv`
|
|
2
|
+
|
|
3
|
+
Migrates the previously deprecated `setupFile` option of the `@nx/jest:jest` executor. The setup file path is appended to the `setupFilesAfterEnv` array in the project's Jest configuration (using `<rootDir>/...` form), and the deprecated option is removed from `project.json` and `nx.json` target defaults.
|
|
4
|
+
|
|
5
|
+
If the Jest configuration cannot be parsed automatically (e.g. it exports a factory function or assigns `setupFilesAfterEnv` to a non-array value), the deprecated option is still removed and a warning is logged listing the affected projects so the setup file path can be moved manually.
|
|
6
|
+
|
|
7
|
+
#### Examples
|
|
8
|
+
|
|
9
|
+
Push the setup file into the project's Jest configuration and remove the option from `project.json`:
|
|
10
|
+
|
|
11
|
+
##### Before
|
|
12
|
+
|
|
13
|
+
```json title="apps/myapp/project.json" {7}
|
|
14
|
+
{
|
|
15
|
+
"targets": {
|
|
16
|
+
"test": {
|
|
17
|
+
"executor": "@nx/jest:jest",
|
|
18
|
+
"options": {
|
|
19
|
+
"jestConfig": "apps/myapp/jest.config.ts",
|
|
20
|
+
"setupFile": "apps/myapp/src/test-setup.ts"
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
```ts title="apps/myapp/jest.config.ts"
|
|
28
|
+
export default {
|
|
29
|
+
displayName: 'myapp',
|
|
30
|
+
};
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
##### After
|
|
34
|
+
|
|
35
|
+
```json title="apps/myapp/project.json"
|
|
36
|
+
{
|
|
37
|
+
"targets": {
|
|
38
|
+
"test": {
|
|
39
|
+
"executor": "@nx/jest:jest",
|
|
40
|
+
"options": {
|
|
41
|
+
"jestConfig": "apps/myapp/jest.config.ts"
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
```ts title="apps/myapp/jest.config.ts"
|
|
49
|
+
export default {
|
|
50
|
+
displayName: 'myapp',
|
|
51
|
+
setupFilesAfterEnv: ['<rootDir>/src/test-setup.ts'],
|
|
52
|
+
};
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
Append to an existing `setupFilesAfterEnv` array:
|
|
56
|
+
|
|
57
|
+
##### Before
|
|
58
|
+
|
|
59
|
+
```json title="apps/myapp/project.json" {7}
|
|
60
|
+
{
|
|
61
|
+
"targets": {
|
|
62
|
+
"test": {
|
|
63
|
+
"executor": "@nx/jest:jest",
|
|
64
|
+
"options": {
|
|
65
|
+
"jestConfig": "apps/myapp/jest.config.ts",
|
|
66
|
+
"setupFile": "apps/myapp/src/test-setup.ts"
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
```ts title="apps/myapp/jest.config.ts"
|
|
74
|
+
export default {
|
|
75
|
+
displayName: 'myapp',
|
|
76
|
+
setupFilesAfterEnv: ['<rootDir>/src/existing-setup.ts'],
|
|
77
|
+
};
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
##### After
|
|
81
|
+
|
|
82
|
+
```json title="apps/myapp/project.json"
|
|
83
|
+
{
|
|
84
|
+
"targets": {
|
|
85
|
+
"test": {
|
|
86
|
+
"executor": "@nx/jest:jest",
|
|
87
|
+
"options": {
|
|
88
|
+
"jestConfig": "apps/myapp/jest.config.ts"
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
```ts title="apps/myapp/jest.config.ts"
|
|
96
|
+
export default {
|
|
97
|
+
displayName: 'myapp',
|
|
98
|
+
setupFilesAfterEnv: [
|
|
99
|
+
'<rootDir>/src/existing-setup.ts',
|
|
100
|
+
'<rootDir>/src/test-setup.ts',
|
|
101
|
+
],
|
|
102
|
+
};
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
Remove the option from a target default using the `@nx/jest:jest` executor:
|
|
106
|
+
|
|
107
|
+
##### Before
|
|
108
|
+
|
|
109
|
+
```json title="nx.json" {7}
|
|
110
|
+
{
|
|
111
|
+
"targetDefaults": {
|
|
112
|
+
"test": {
|
|
113
|
+
"executor": "@nx/jest:jest",
|
|
114
|
+
"options": {
|
|
115
|
+
"jestConfig": "{projectRoot}/jest.config.ts",
|
|
116
|
+
"setupFile": "{projectRoot}/src/test-setup.ts"
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
##### After
|
|
124
|
+
|
|
125
|
+
```json title="nx.json"
|
|
126
|
+
{
|
|
127
|
+
"targetDefaults": {
|
|
128
|
+
"test": {
|
|
129
|
+
"executor": "@nx/jest:jest",
|
|
130
|
+
"options": {
|
|
131
|
+
"jestConfig": "{projectRoot}/jest.config.ts"
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
Per-project paths don't make sense as workspace defaults, so the option is removed without rewriting individual project Jest configs. A warning is logged so the setup file path can be added to each project's Jest config manually if needed.
|
|
139
|
+
|
|
140
|
+
Remove the option from a target default using the `@nx/jest:jest` executor as the key:
|
|
141
|
+
|
|
142
|
+
##### Before
|
|
143
|
+
|
|
144
|
+
```json title="nx.json" {6}
|
|
145
|
+
{
|
|
146
|
+
"targetDefaults": {
|
|
147
|
+
"@nx/jest:jest": {
|
|
148
|
+
"options": {
|
|
149
|
+
"jestConfig": "{projectRoot}/jest.config.ts",
|
|
150
|
+
"setupFile": "{projectRoot}/src/test-setup.ts"
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
##### After
|
|
158
|
+
|
|
159
|
+
```json title="nx.json"
|
|
160
|
+
{
|
|
161
|
+
"targetDefaults": {
|
|
162
|
+
"@nx/jest:jest": {
|
|
163
|
+
"options": {
|
|
164
|
+
"jestConfig": "{projectRoot}/jest.config.ts"
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
```
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.assertSupportedJestVersion = assertSupportedJestVersion;
|
|
4
|
+
const internal_1 = require("@nx/devkit/internal");
|
|
5
|
+
const versions_1 = require("./versions");
|
|
6
|
+
function assertSupportedJestVersion(tree) {
|
|
7
|
+
(0, internal_1.assertSupportedPackageVersion)(tree, 'jest', versions_1.minSupportedJestVersion);
|
|
8
|
+
// ts-jest installs on an independent versioning train from jest, so its
|
|
9
|
+
// floor is asserted separately.
|
|
10
|
+
(0, internal_1.assertSupportedPackageVersion)(tree, 'ts-jest', versions_1.minSupportedTsJestVersion);
|
|
11
|
+
}
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { type Tree } from '@nx/devkit';
|
|
2
|
+
export declare const minSupportedJestVersion = "29.0.0";
|
|
3
|
+
export declare const minSupportedTsJestVersion = "29.0.0";
|
|
2
4
|
export declare const latestVersions: {
|
|
3
5
|
nxVersion: any;
|
|
4
6
|
jestVersion: string;
|
|
@@ -17,12 +19,21 @@ export type VersionMap = {
|
|
|
17
19
|
[key in SupportedVersions]: Record<PackageVersionNames, string>;
|
|
18
20
|
};
|
|
19
21
|
export declare const versionMap: VersionMap;
|
|
20
|
-
export declare function versions(tree: Tree):
|
|
22
|
+
export declare function versions(tree: Tree): {
|
|
23
|
+
nxVersion: any;
|
|
24
|
+
jestVersion: string;
|
|
25
|
+
babelJestVersion: string;
|
|
26
|
+
jestTypesVersion: string;
|
|
27
|
+
tsJestVersion: string;
|
|
28
|
+
tslibVersion: string;
|
|
29
|
+
swcJestVersion: string;
|
|
30
|
+
typesNodeVersion: string;
|
|
31
|
+
tsNodeVersion: string;
|
|
32
|
+
};
|
|
21
33
|
export declare function getInstalledJestVersion(tree?: Tree): string | null;
|
|
22
34
|
export declare function getInstalledJestVersionInfo(tree?: Tree): {
|
|
23
35
|
version: string | null;
|
|
24
36
|
major: number | null;
|
|
25
37
|
};
|
|
26
38
|
export declare function getInstalledJestMajorVersion(tree?: Tree): number | null;
|
|
27
|
-
export declare function validateInstalledJestVersion(tree?: Tree): void;
|
|
28
39
|
export {};
|
|
@@ -1,15 +1,17 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.versionMap = exports.latestVersions = void 0;
|
|
3
|
+
exports.versionMap = exports.latestVersions = exports.minSupportedTsJestVersion = exports.minSupportedJestVersion = void 0;
|
|
4
4
|
exports.versions = versions;
|
|
5
5
|
exports.getInstalledJestVersion = getInstalledJestVersion;
|
|
6
6
|
exports.getInstalledJestVersionInfo = getInstalledJestVersionInfo;
|
|
7
7
|
exports.getInstalledJestMajorVersion = getInstalledJestMajorVersion;
|
|
8
|
-
exports.validateInstalledJestVersion = validateInstalledJestVersion;
|
|
9
8
|
const devkit_1 = require("@nx/devkit");
|
|
9
|
+
const internal_1 = require("@nx/devkit/internal");
|
|
10
10
|
const path_1 = require("path");
|
|
11
11
|
const semver_1 = require("semver");
|
|
12
12
|
const nxVersion = require((0, path_1.join)('@nx/jest', 'package.json')).version;
|
|
13
|
+
exports.minSupportedJestVersion = '29.0.0';
|
|
14
|
+
exports.minSupportedTsJestVersion = '29.0.0';
|
|
13
15
|
// Jest is pinned to 30.3.x because jest-runtime@30.4.0 added a call to
|
|
14
16
|
// `_moduleMocker.clearMocksOnScope()`, which doesn't exist on the
|
|
15
17
|
// jest-mock@29 ModuleMocker that React Native's preset still feeds in
|
|
@@ -20,6 +22,9 @@ exports.latestVersions = {
|
|
|
20
22
|
jestVersion: '~30.3.0',
|
|
21
23
|
babelJestVersion: '~30.3.0',
|
|
22
24
|
jestTypesVersion: '~30.0.0',
|
|
25
|
+
// ts-jest has not shipped a v30 — 29.x is its latest line and its peers
|
|
26
|
+
// already span jest 29 and 30 (`jest: '^29.0.0 || ^30.0.0'`), so a jest-30
|
|
27
|
+
// workspace correctly stays on ts-jest 29.x.
|
|
23
28
|
tsJestVersion: '^29.4.0',
|
|
24
29
|
tslibVersion: '^2.3.0',
|
|
25
30
|
swcJestVersion: '~0.2.38',
|
|
@@ -27,8 +32,6 @@ exports.latestVersions = {
|
|
|
27
32
|
tsNodeVersion: '10.9.1',
|
|
28
33
|
};
|
|
29
34
|
const supportedMajorVersions = [29, 30];
|
|
30
|
-
const minSupportedMajorVersion = Math.min(...supportedMajorVersions);
|
|
31
|
-
const currentMajorVersion = Math.max(...supportedMajorVersions);
|
|
32
35
|
exports.versionMap = {
|
|
33
36
|
29: {
|
|
34
37
|
nxVersion,
|
|
@@ -49,22 +52,28 @@ function versions(tree) {
|
|
|
49
52
|
return exports.latestVersions;
|
|
50
53
|
}
|
|
51
54
|
const jestMajorVersion = (0, semver_1.major)(installedJestVersion);
|
|
52
|
-
|
|
53
|
-
return exports.versionMap[jestMajorVersion];
|
|
54
|
-
}
|
|
55
|
-
const backwardCompatibleVersions = supportedMajorVersions.slice(0, -1);
|
|
56
|
-
throw new Error(`You're currently using an unsupported Jest version: ${installedJestVersion}. Supported major versions are ${backwardCompatibleVersions.join(', ')} and ${currentMajorVersion}.`);
|
|
55
|
+
return exports.versionMap[jestMajorVersion] ?? exports.latestVersions;
|
|
57
56
|
}
|
|
58
57
|
function getInstalledJestVersion(tree) {
|
|
58
|
+
if (!tree) {
|
|
59
|
+
// Fall back to `@nx/jest`'s own jest when the workspace cwd can't resolve
|
|
60
|
+
// one (e.g. inferred-plugin createNodes runs against an empty workspace).
|
|
61
|
+
return (0, internal_1.getInstalledPackageVersion)('jest') ?? getJestVersionFromRequire();
|
|
62
|
+
}
|
|
63
|
+
const installedVersion = (0, devkit_1.getDependencyVersionFromPackageJson)(tree, 'jest');
|
|
64
|
+
if (!installedVersion) {
|
|
65
|
+
return null;
|
|
66
|
+
}
|
|
67
|
+
if (installedVersion === 'latest' || installedVersion === 'next') {
|
|
68
|
+
return ((0, semver_1.clean)(exports.latestVersions.jestVersion) ??
|
|
69
|
+
(0, semver_1.coerce)(exports.latestVersions.jestVersion)?.version ??
|
|
70
|
+
null);
|
|
71
|
+
}
|
|
72
|
+
return (0, semver_1.clean)(installedVersion) ?? (0, semver_1.coerce)(installedVersion)?.version ?? null;
|
|
73
|
+
}
|
|
74
|
+
function getJestVersionFromRequire() {
|
|
59
75
|
try {
|
|
60
|
-
|
|
61
|
-
if (tree) {
|
|
62
|
-
version = getJestVersionFromTree(tree);
|
|
63
|
-
}
|
|
64
|
-
else {
|
|
65
|
-
version = getJestVersionFromFileSystem();
|
|
66
|
-
}
|
|
67
|
-
return version;
|
|
76
|
+
return require('jest').getVersion();
|
|
68
77
|
}
|
|
69
78
|
catch {
|
|
70
79
|
return null;
|
|
@@ -80,32 +89,3 @@ function getInstalledJestMajorVersion(tree) {
|
|
|
80
89
|
const installedJestVersion = getInstalledJestVersion(tree);
|
|
81
90
|
return installedJestVersion ? (0, semver_1.major)(installedJestVersion) : null;
|
|
82
91
|
}
|
|
83
|
-
function validateInstalledJestVersion(tree) {
|
|
84
|
-
const { version, major } = getInstalledJestVersionInfo(tree);
|
|
85
|
-
if (!version) {
|
|
86
|
-
return;
|
|
87
|
-
}
|
|
88
|
-
if (major < minSupportedMajorVersion || major > currentMajorVersion) {
|
|
89
|
-
const backwardCompatibleVersions = supportedMajorVersions.slice(0, -1);
|
|
90
|
-
throw new Error(`You're currently using an unsupported Jest version: ${version}. Supported major versions are ${backwardCompatibleVersions.join(', ')} and ${currentMajorVersion}.`);
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
function getJestVersionFromTree(tree) {
|
|
94
|
-
const installedVersion = (0, devkit_1.getDependencyVersionFromPackageJson)(tree, 'jest');
|
|
95
|
-
if (!installedVersion) {
|
|
96
|
-
return null;
|
|
97
|
-
}
|
|
98
|
-
if (installedVersion === 'latest' || installedVersion === 'next') {
|
|
99
|
-
return ((0, semver_1.clean)(exports.latestVersions.jestVersion) ??
|
|
100
|
-
(0, semver_1.coerce)(exports.latestVersions.jestVersion)?.version);
|
|
101
|
-
}
|
|
102
|
-
return (0, semver_1.clean)(installedVersion) ?? (0, semver_1.coerce)(installedVersion)?.version;
|
|
103
|
-
}
|
|
104
|
-
function getJestVersionFromFileSystem() {
|
|
105
|
-
try {
|
|
106
|
-
const { getVersion } = require('jest');
|
|
107
|
-
return getVersion();
|
|
108
|
-
}
|
|
109
|
-
catch { }
|
|
110
|
-
return null;
|
|
111
|
-
}
|
package/migrations.json
CHANGED
|
@@ -4,23 +4,27 @@
|
|
|
4
4
|
"cli": "nx",
|
|
5
5
|
"version": "20.0.0-beta.5",
|
|
6
6
|
"description": "Replace usage of `getJestProjects` with `getJestProjectsAsync`.",
|
|
7
|
-
"implementation": "./dist/src/migrations/update-20-0-0/replace-getJestProjects-with-getJestProjectsAsync"
|
|
7
|
+
"implementation": "./dist/src/migrations/update-20-0-0/replace-getJestProjects-with-getJestProjectsAsync",
|
|
8
|
+
"documentation": "./dist/src/migrations/update-20-0-0/replace-getJestProjects-with-getJestProjectsAsync.md"
|
|
8
9
|
},
|
|
9
10
|
"replace-getJestProjects-with-getJestProjectsAsync-v21": {
|
|
10
11
|
"cli": "nx",
|
|
11
12
|
"version": "21.0.0-beta.9",
|
|
12
13
|
"description": "Replace usage of `getJestProjects` with `getJestProjectsAsync`.",
|
|
13
|
-
"implementation": "./dist/src/migrations/update-21-0-0/replace-getJestProjects-with-getJestProjectsAsync"
|
|
14
|
+
"implementation": "./dist/src/migrations/update-21-0-0/replace-getJestProjects-with-getJestProjectsAsync",
|
|
15
|
+
"documentation": "./dist/src/migrations/update-21-0-0/replace-getJestProjects-with-getJestProjectsAsync.md"
|
|
14
16
|
},
|
|
15
17
|
"remove-tsconfig-option-from-jest-executor": {
|
|
16
18
|
"version": "21.0.0-beta.10",
|
|
17
19
|
"description": "Remove the previously deprecated and unused `tsConfig` option from the `@nx/jest:jest` executor.",
|
|
18
|
-
"implementation": "./dist/src/migrations/update-21-0-0/remove-tsconfig-option-from-jest-executor"
|
|
20
|
+
"implementation": "./dist/src/migrations/update-21-0-0/remove-tsconfig-option-from-jest-executor",
|
|
21
|
+
"documentation": "./dist/src/migrations/update-21-0-0/remove-tsconfig-option-from-jest-executor.md"
|
|
19
22
|
},
|
|
20
23
|
"rename-test-path-pattern": {
|
|
21
24
|
"version": "21.3.0-beta.3",
|
|
22
25
|
"description": "Rename the CLI option `testPathPattern` to `testPathPatterns`.",
|
|
23
|
-
"implementation": "./dist/src/migrations/update-21-3-0/rename-test-path-pattern"
|
|
26
|
+
"implementation": "./dist/src/migrations/update-21-3-0/rename-test-path-pattern",
|
|
27
|
+
"documentation": "./dist/src/migrations/update-21-3-0/rename-test-path-pattern.md"
|
|
24
28
|
},
|
|
25
29
|
"replace-removed-matcher-aliases": {
|
|
26
30
|
"version": "21.3.0-beta.3",
|
|
@@ -28,12 +32,14 @@
|
|
|
28
32
|
"jest": ">=30.0.0"
|
|
29
33
|
},
|
|
30
34
|
"description": "Replace removed matcher aliases in Jest v30 with their corresponding matcher",
|
|
31
|
-
"implementation": "./dist/src/migrations/update-21-3-0/replace-removed-matcher-aliases"
|
|
35
|
+
"implementation": "./dist/src/migrations/update-21-3-0/replace-removed-matcher-aliases",
|
|
36
|
+
"documentation": "./dist/src/migrations/update-21-3-0/replace-removed-matcher-aliases.md"
|
|
32
37
|
},
|
|
33
38
|
"convert-jest-config-to-cjs": {
|
|
34
39
|
"version": "22.2.0-beta.2",
|
|
35
40
|
"description": "Convert jest.config.ts files from ESM to CJS syntax (export default -> module.exports, import -> require) for projects using CommonJS resolution to ensure correct loading under Node.js type-stripping.",
|
|
36
|
-
"implementation": "./dist/src/migrations/update-22-2-0/convert-jest-config-to-cjs"
|
|
41
|
+
"implementation": "./dist/src/migrations/update-22-2-0/convert-jest-config-to-cjs",
|
|
42
|
+
"documentation": "./dist/src/migrations/update-22-2-0/convert-jest-config-to-cjs.md"
|
|
37
43
|
},
|
|
38
44
|
"replace-removed-matcher-aliases-v22-3": {
|
|
39
45
|
"version": "22.3.2-beta.0",
|
|
@@ -41,7 +47,8 @@
|
|
|
41
47
|
"jest": ">=30.0.0"
|
|
42
48
|
},
|
|
43
49
|
"description": "Replace removed matcher aliases in Jest v30 with their corresponding matcher",
|
|
44
|
-
"implementation": "./dist/src/migrations/update-21-3-0/replace-removed-matcher-aliases"
|
|
50
|
+
"implementation": "./dist/src/migrations/update-21-3-0/replace-removed-matcher-aliases",
|
|
51
|
+
"documentation": "./dist/src/migrations/update-21-3-0/replace-removed-matcher-aliases.md"
|
|
45
52
|
},
|
|
46
53
|
"update-snapshot-guide-link": {
|
|
47
54
|
"version": "23.0.0-beta.10",
|
|
@@ -49,7 +56,8 @@
|
|
|
49
56
|
"jest": ">=30.0.0"
|
|
50
57
|
},
|
|
51
58
|
"description": "Update the Jest snapshot guide link in `.snap` files from the legacy `https://goo.gl/fbAQLP` URL to `https://jestjs.io/docs/snapshot-testing`, which Jest v30 now requires.",
|
|
52
|
-
"implementation": "./dist/src/migrations/update-23-0-0/update-snapshot-guide-link"
|
|
59
|
+
"implementation": "./dist/src/migrations/update-23-0-0/update-snapshot-guide-link",
|
|
60
|
+
"documentation": "./dist/src/migrations/update-23-0-0/update-snapshot-guide-link.md"
|
|
53
61
|
},
|
|
54
62
|
"rewrite-jest-internal-subpath-imports": {
|
|
55
63
|
"version": "23.0.0-beta.16",
|
|
@@ -60,6 +68,16 @@
|
|
|
60
68
|
"version": "23.0.0-beta.16",
|
|
61
69
|
"description": "Replaces the removed `jestProjectGenerator` export from `@nx/jest` with its replacement `configurationGenerator`.",
|
|
62
70
|
"implementation": "./dist/src/migrations/update-23-0-0/rewrite-jest-project-generator"
|
|
71
|
+
},
|
|
72
|
+
"migrate-jest-executor-setup-file": {
|
|
73
|
+
"version": "23.0.0-beta.22",
|
|
74
|
+
"description": "Migrate the deprecated `setupFile` option of the `@nx/jest:jest` executor: push the file path into `setupFilesAfterEnv` in the project's Jest config and remove the option from `project.json` and `nx.json` target defaults.",
|
|
75
|
+
"implementation": "./dist/src/migrations/update-23-0-0/migrate-jest-executor-setup-file"
|
|
76
|
+
},
|
|
77
|
+
"migrate-jest-configuration-skip-setup-file": {
|
|
78
|
+
"version": "23.0.0-beta.22",
|
|
79
|
+
"description": "Migrate the deprecated `skipSetupFile` option of the `@nx/jest:configuration` generator stored as a default in `nx.json` or per-project `project.json` to `setupFile: 'none'` (when `true`) or remove it (when `false`).",
|
|
80
|
+
"implementation": "./dist/src/migrations/update-23-0-0/migrate-jest-configuration-skip-setup-file"
|
|
63
81
|
}
|
|
64
82
|
},
|
|
65
83
|
"packageJsonUpdates": {
|
|
@@ -69,6 +87,9 @@
|
|
|
69
87
|
"incompatibleWith": {
|
|
70
88
|
"@angular-devkit/build-angular": "< 21.0.0"
|
|
71
89
|
},
|
|
90
|
+
"requires": {
|
|
91
|
+
"jest": ">=29.0.0 <30.0.0"
|
|
92
|
+
},
|
|
72
93
|
"packages": {
|
|
73
94
|
"jest": {
|
|
74
95
|
"version": "~30.0.0",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nx/jest",
|
|
3
|
-
"version": "23.0.0-beta.
|
|
3
|
+
"version": "23.0.0-beta.22",
|
|
4
4
|
"private": false,
|
|
5
5
|
"type": "commonjs",
|
|
6
6
|
"files": [
|
|
@@ -90,6 +90,18 @@
|
|
|
90
90
|
"default": "./dist/internal.js"
|
|
91
91
|
}
|
|
92
92
|
},
|
|
93
|
+
"peerDependencies": {
|
|
94
|
+
"jest": "^29.0.0 || ^30.0.0",
|
|
95
|
+
"ts-jest": "^29.0.0"
|
|
96
|
+
},
|
|
97
|
+
"peerDependenciesMeta": {
|
|
98
|
+
"jest": {
|
|
99
|
+
"optional": true
|
|
100
|
+
},
|
|
101
|
+
"ts-jest": {
|
|
102
|
+
"optional": true
|
|
103
|
+
}
|
|
104
|
+
},
|
|
93
105
|
"dependencies": {
|
|
94
106
|
"@jest/reporters": "^30.0.2",
|
|
95
107
|
"@jest/test-result": "^30.0.2",
|
|
@@ -104,11 +116,11 @@
|
|
|
104
116
|
"semver": "^7.6.3",
|
|
105
117
|
"tslib": "^2.3.0",
|
|
106
118
|
"yargs-parser": "21.1.1",
|
|
107
|
-
"@nx/devkit": "23.0.0-beta.
|
|
108
|
-
"@nx/js": "23.0.0-beta.
|
|
119
|
+
"@nx/devkit": "23.0.0-beta.22",
|
|
120
|
+
"@nx/js": "23.0.0-beta.22"
|
|
109
121
|
},
|
|
110
122
|
"devDependencies": {
|
|
111
|
-
"nx": "23.0.0-beta.
|
|
123
|
+
"nx": "23.0.0-beta.22"
|
|
112
124
|
},
|
|
113
125
|
"publishConfig": {
|
|
114
126
|
"access": "public"
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.getInstalledJestVersion = getInstalledJestVersion;
|
|
4
|
-
exports.getInstalledJestMajorVersion = getInstalledJestMajorVersion;
|
|
5
|
-
const jest_1 = require("jest");
|
|
6
|
-
const semver_1 = require("semver");
|
|
7
|
-
function getInstalledJestVersion() {
|
|
8
|
-
try {
|
|
9
|
-
return (0, jest_1.getVersion)();
|
|
10
|
-
}
|
|
11
|
-
catch {
|
|
12
|
-
return null;
|
|
13
|
-
}
|
|
14
|
-
}
|
|
15
|
-
function getInstalledJestMajorVersion() {
|
|
16
|
-
const installedVersion = getInstalledJestVersion();
|
|
17
|
-
return installedVersion ? (0, semver_1.major)(installedVersion) : null;
|
|
18
|
-
}
|