@nx/jest 23.1.0-beta.3 → 23.1.0-beta.5
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/generators/configuration/configuration.js +14 -8
- package/dist/src/generators/init/init.js +36 -19
- package/dist/src/migrations/update-21-0-0/remove-tsconfig-option-from-jest-executor.js +15 -20
- package/dist/src/migrations/update-21-3-0/rename-test-path-pattern.js +12 -15
- package/dist/src/migrations/update-23-0-0/migrate-jest-executor-setup-file.js +24 -31
- package/dist/src/migrations/update-23-0-0/migrate-jest-executor-setup-file.md +1 -1
- package/dist/src/migrations/update-23-1-0/set-ts-jest-isolated-modules.md +10 -0
- package/dist/src/migrations/update-23-1-0/verify-typecheck.md +14 -0
- package/migrations.json +3 -2
- package/package.json +4 -4
|
@@ -3,8 +3,9 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.configurationGenerator = configurationGenerator;
|
|
4
4
|
exports.configurationGeneratorInternal = configurationGeneratorInternal;
|
|
5
5
|
const devkit_1 = require("@nx/devkit");
|
|
6
|
+
const internal_1 = require("@nx/devkit/internal");
|
|
6
7
|
const js_1 = require("@nx/js");
|
|
7
|
-
const
|
|
8
|
+
const internal_2 = require("@nx/js/internal");
|
|
8
9
|
const config_file_1 = require("../../utils/config/config-file");
|
|
9
10
|
const init_1 = require("../init/init");
|
|
10
11
|
const assert_supported_jest_version_1 = require("../../utils/assert-supported-jest-version");
|
|
@@ -47,7 +48,7 @@ function normalizeOptions(tree, options) {
|
|
|
47
48
|
...options,
|
|
48
49
|
keepExistingVersions: options.keepExistingVersions ?? true,
|
|
49
50
|
rootProject: project.root === '.' || project.root === '',
|
|
50
|
-
isTsSolutionSetup: (0,
|
|
51
|
+
isTsSolutionSetup: (0, internal_2.isUsingTsSolutionSetup)(tree),
|
|
51
52
|
};
|
|
52
53
|
}
|
|
53
54
|
function configurationGenerator(tree, schema) {
|
|
@@ -93,12 +94,17 @@ async function configurationGeneratorInternal(tree, schema) {
|
|
|
93
94
|
ignoreTestOutput(tree);
|
|
94
95
|
// in the TS solution setup, the test target depends on the build outputs
|
|
95
96
|
// so we need to setup the task pipeline accordingly
|
|
96
|
-
const nxJson = (0, devkit_1.readNxJson)(tree);
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
nxJson.targetDefaults
|
|
100
|
-
|
|
101
|
-
|
|
97
|
+
const nxJson = (0, devkit_1.readNxJson)(tree) ?? {};
|
|
98
|
+
// A bare `target` locator matches only the unfiltered generic entry, so we
|
|
99
|
+
// extend the workspace-wide baseline rather than a project-scoped one.
|
|
100
|
+
const existing = (0, internal_1.findTargetDefault)(nxJson.targetDefaults, {
|
|
101
|
+
target: options.targetName,
|
|
102
|
+
});
|
|
103
|
+
const dependsOn = Array.from(new Set([...(existing?.dependsOn ?? []), '^build']));
|
|
104
|
+
(0, internal_1.upsertTargetDefault)(tree, nxJson, {
|
|
105
|
+
target: options.targetName,
|
|
106
|
+
dependsOn,
|
|
107
|
+
});
|
|
102
108
|
(0, devkit_1.updateNxJson)(tree, nxJson);
|
|
103
109
|
}
|
|
104
110
|
if (!schema.skipFormat) {
|
|
@@ -29,27 +29,44 @@ function updateProductionFileSet(tree) {
|
|
|
29
29
|
(0, devkit_1.updateNxJson)(tree, nxJson);
|
|
30
30
|
}
|
|
31
31
|
function addJestTargetDefaults(tree, presetExt) {
|
|
32
|
-
const nxJson = (0, devkit_1.readNxJson)(tree);
|
|
33
|
-
nxJson.targetDefaults ??= {};
|
|
34
|
-
nxJson.targetDefaults['@nx/jest:jest'] ??= {};
|
|
32
|
+
const nxJson = (0, devkit_1.readNxJson)(tree) ?? {};
|
|
35
33
|
const productionFileSet = nxJson.namedInputs?.production;
|
|
36
|
-
|
|
34
|
+
// Manage the workspace-wide `@nx/jest:jest` default; `upsertTargetDefault`
|
|
35
|
+
// updates the unfiltered entry (or creates one), leaving any project- or
|
|
36
|
+
// plugin-scoped jest overrides the user authored untouched.
|
|
37
|
+
const existing = (0, internal_1.findTargetDefault)(nxJson.targetDefaults, {
|
|
38
|
+
executor: '@nx/jest:jest',
|
|
39
|
+
});
|
|
40
|
+
const patch = createJestDefaultPatch(existing, productionFileSet, presetExt);
|
|
41
|
+
if (Object.keys(patch).length > 0) {
|
|
42
|
+
(0, internal_1.upsertTargetDefault)(tree, nxJson, { executor: '@nx/jest:jest', ...patch });
|
|
43
|
+
(0, devkit_1.updateNxJson)(tree, nxJson);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
function createJestDefaultPatch(existing, productionFileSet, presetExt) {
|
|
47
|
+
const patch = {};
|
|
48
|
+
if (existing?.cache === undefined)
|
|
49
|
+
patch.cache = true;
|
|
37
50
|
// Test targets depend on all their project's sources + production sources of dependencies
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
51
|
+
if (existing?.inputs === undefined) {
|
|
52
|
+
patch.inputs = [
|
|
53
|
+
'default',
|
|
54
|
+
productionFileSet ? '^production' : '^default',
|
|
55
|
+
`{workspaceRoot}/jest.preset.${presetExt}`,
|
|
56
|
+
];
|
|
57
|
+
}
|
|
58
|
+
if (existing?.options === undefined) {
|
|
59
|
+
patch.options = { passWithNoTests: true };
|
|
60
|
+
}
|
|
61
|
+
if (existing?.configurations === undefined) {
|
|
62
|
+
patch.configurations = {
|
|
63
|
+
ci: {
|
|
64
|
+
ci: true,
|
|
65
|
+
codeCoverage: true,
|
|
66
|
+
},
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
return patch;
|
|
53
70
|
}
|
|
54
71
|
function updateDependencies(tree, options) {
|
|
55
72
|
const { jestVersion, nxVersion } = (0, versions_1.versions)(tree);
|
|
@@ -19,29 +19,24 @@ async function default_1(tree) {
|
|
|
19
19
|
}
|
|
20
20
|
(0, devkit_1.updateProjectConfiguration)(tree, project, projectConfiguration);
|
|
21
21
|
});
|
|
22
|
-
// update options from nx.json target defaults
|
|
22
|
+
// update options from nx.json target defaults. `updateTargetDefault` walks
|
|
23
|
+
// both the object and filtered array value forms, drops entries left with
|
|
24
|
+
// nothing but their executor locator, and collapses lone unfiltered ones
|
|
25
|
+
// back to the object form.
|
|
23
26
|
const nxJson = (0, devkit_1.readNxJson)(tree);
|
|
24
|
-
if (nxJson
|
|
25
|
-
|
|
26
|
-
if (
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
if (targetConfig.options) {
|
|
31
|
-
updateOptions(targetConfig);
|
|
32
|
-
}
|
|
33
|
-
Object.keys(targetConfig.configurations ?? {}).forEach((config) => {
|
|
34
|
-
updateConfiguration(targetConfig, config);
|
|
27
|
+
if (nxJson?.targetDefaults) {
|
|
28
|
+
(0, internal_1.updateTargetDefault)(nxJson, { executor: EXECUTOR_TO_MIGRATE }, (config) => {
|
|
29
|
+
if (config.options)
|
|
30
|
+
updateOptions(config);
|
|
31
|
+
Object.keys(config.configurations ?? {}).forEach((configuration) => {
|
|
32
|
+
updateConfiguration(config, configuration);
|
|
35
33
|
});
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
34
|
+
// Drop the entry once nothing but its executor locator remains.
|
|
35
|
+
const keys = Object.keys(config);
|
|
36
|
+
if (keys.length === 0 || (keys.length === 1 && keys[0] === 'executor')) {
|
|
37
|
+
return null;
|
|
40
38
|
}
|
|
41
|
-
|
|
42
|
-
delete nxJson.targetDefaults;
|
|
43
|
-
}
|
|
44
|
-
}
|
|
39
|
+
});
|
|
45
40
|
(0, devkit_1.updateNxJson)(tree, nxJson);
|
|
46
41
|
}
|
|
47
42
|
await (0, devkit_1.formatFiles)(tree);
|
|
@@ -14,24 +14,21 @@ async function default_1(tree) {
|
|
|
14
14
|
renameTestPathPattern(config);
|
|
15
15
|
(0, devkit_1.updateProjectConfiguration)(tree, project, projectConfiguration);
|
|
16
16
|
});
|
|
17
|
-
// update options from nx.json target defaults
|
|
17
|
+
// update options from nx.json target defaults. Migration order isn't
|
|
18
|
+
// guaranteed, so a default may already be in the filtered array shape;
|
|
19
|
+
// `updateTargetDefault` walks both the object and array value forms.
|
|
18
20
|
const nxJson = (0, devkit_1.readNxJson)(tree);
|
|
19
|
-
if (
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
if (targetConfig.options) {
|
|
28
|
-
renameTestPathPattern(targetConfig.options);
|
|
29
|
-
}
|
|
30
|
-
Object.values(targetConfig.configurations ?? {}).forEach((config) => {
|
|
31
|
-
renameTestPathPattern(config);
|
|
21
|
+
if (nxJson?.targetDefaults) {
|
|
22
|
+
(0, internal_1.updateTargetDefault)(nxJson, { executor: '@nx/jest:jest' }, (config) => {
|
|
23
|
+
if (config.options) {
|
|
24
|
+
renameTestPathPattern(config.options);
|
|
25
|
+
}
|
|
26
|
+
Object.values(config.configurations ?? {}).forEach((c) => {
|
|
27
|
+
renameTestPathPattern(c);
|
|
28
|
+
});
|
|
32
29
|
});
|
|
30
|
+
(0, devkit_1.updateNxJson)(tree, nxJson);
|
|
33
31
|
}
|
|
34
|
-
(0, devkit_1.updateNxJson)(tree, nxJson);
|
|
35
32
|
await (0, devkit_1.formatFiles)(tree);
|
|
36
33
|
}
|
|
37
34
|
function renameTestPathPattern(config) {
|
|
@@ -190,47 +190,40 @@ function migrateInheritedSetupFile(tree, project, target, nxJson, projectConfigC
|
|
|
190
190
|
function stripSetupFileFromNxJson(tree, nxJson) {
|
|
191
191
|
if (!nxJson?.targetDefaults)
|
|
192
192
|
return false;
|
|
193
|
-
let changed = false;
|
|
194
193
|
let hadSetupFile = false;
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
if (
|
|
194
|
+
// Migration order isn't guaranteed, so a default may already be in the
|
|
195
|
+
// filtered array shape; `updateTargetDefault` walks both value forms, drops
|
|
196
|
+
// entries the callback empties, and collapses lone unfiltered ones back to
|
|
197
|
+
// the object form.
|
|
198
|
+
(0, internal_1.updateTargetDefault)(nxJson, { executor: EXECUTOR_TO_MIGRATE }, (config) => {
|
|
199
|
+
if (config.options?.setupFile !== undefined) {
|
|
201
200
|
hadSetupFile = true;
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
delete targetConfig.options;
|
|
201
|
+
delete config.options.setupFile;
|
|
202
|
+
if (!Object.keys(config.options).length) {
|
|
203
|
+
delete config.options;
|
|
206
204
|
}
|
|
207
205
|
}
|
|
208
|
-
for (const
|
|
209
|
-
if (
|
|
206
|
+
for (const configuration of Object.keys(config.configurations ?? {})) {
|
|
207
|
+
if (config.configurations[configuration]?.setupFile !== undefined) {
|
|
210
208
|
hadSetupFile = true;
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
delete targetConfig.configurations[config];
|
|
209
|
+
delete config.configurations[configuration].setupFile;
|
|
210
|
+
if (!Object.keys(config.configurations[configuration]).length &&
|
|
211
|
+
(!config.defaultConfiguration ||
|
|
212
|
+
config.defaultConfiguration !== configuration)) {
|
|
213
|
+
delete config.configurations[configuration];
|
|
217
214
|
}
|
|
218
215
|
}
|
|
219
216
|
}
|
|
220
|
-
if (
|
|
221
|
-
|
|
222
|
-
delete targetConfig.configurations;
|
|
217
|
+
if (config.configurations && !Object.keys(config.configurations).length) {
|
|
218
|
+
delete config.configurations;
|
|
223
219
|
}
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
220
|
+
// Drop the entry once nothing but its executor locator remains.
|
|
221
|
+
const keys = Object.keys(config);
|
|
222
|
+
if (keys.length === 0 || (keys.length === 1 && keys[0] === 'executor')) {
|
|
223
|
+
return null;
|
|
228
224
|
}
|
|
229
|
-
}
|
|
230
|
-
if (
|
|
231
|
-
delete nxJson.targetDefaults;
|
|
232
|
-
}
|
|
233
|
-
if (changed)
|
|
225
|
+
});
|
|
226
|
+
if (hadSetupFile)
|
|
234
227
|
(0, devkit_1.updateNxJson)(tree, nxJson);
|
|
235
228
|
return hadSetupFile;
|
|
236
229
|
}
|
|
@@ -137,7 +137,7 @@ Remove the option from a target default using the `@nx/jest:jest` executor:
|
|
|
137
137
|
|
|
138
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
139
|
|
|
140
|
-
Remove the option from a target default
|
|
140
|
+
Remove the option from a target default entry matching on the `@nx/jest:jest` executor:
|
|
141
141
|
|
|
142
142
|
##### Before
|
|
143
143
|
|
|
@@ -39,3 +39,13 @@ TypeScript 6 and above resolves `exports` under `bundler` with `commonjs`, so th
|
|
|
39
39
|
}
|
|
40
40
|
}
|
|
41
41
|
```
|
|
42
|
+
|
|
43
|
+
#### Verifying the workspace
|
|
44
|
+
|
|
45
|
+
After the migration runs, verify the workspace still typechecks and fix anything `isolatedModules` surfaced:
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
nx run-many -t typecheck
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
`isolatedModules` can fail typecheck (TS1205 - re-exporting a type needs `export type`; TS2748 - const enum access) or break a project's tests at runtime even when typecheck passes. The cause is a package that re-exports a value through both `module.exports` and an ESM `export` (for example napi bindings exposing a `const enum`); per-file transpilation cannot preserve it, and consumers of that const enum break too. To fix a broken project, remove `isolatedModules` from its `tsconfig.spec.json`; if that brings back the `TS2307: Cannot find module` error this migration was added to prevent, that project needs `isolatedModules`, so fix the source instead.
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# Verify typecheck after the Nx 23.1 migration
|
|
2
|
+
|
|
3
|
+
This migration enables `isolatedModules` on ts-jest spec configs. Run
|
|
4
|
+
`nx run-many -t typecheck` and fix any project it broke.
|
|
5
|
+
|
|
6
|
+
`isolatedModules` can fail typecheck (TS1205 - a re-exported type needs `export type`;
|
|
7
|
+
TS2748 - const enum access) or break a project's tests at runtime. To fix a broken
|
|
8
|
+
project, remove `isolatedModules` from its `tsconfig.spec.json` and re-run. If a
|
|
9
|
+
`TS2307: Cannot find module` error then appears for a workspace library, that project
|
|
10
|
+
needs `isolatedModules` - keep it and fix the source instead (avoid mixing
|
|
11
|
+
`module.exports` with an ESM `export`, and avoid cross-file `const enum`).
|
|
12
|
+
|
|
13
|
+
Re-run until the projects this migration touched typecheck. See the migration
|
|
14
|
+
documentation for details.
|
package/migrations.json
CHANGED
|
@@ -79,12 +79,13 @@
|
|
|
79
79
|
"documentation": "./dist/src/migrations/update-23-0-0/migrate-create-nodes-v2-to-create-nodes.md"
|
|
80
80
|
},
|
|
81
81
|
"set-ts-jest-isolated-modules": {
|
|
82
|
-
"version": "23.1.0-beta.
|
|
82
|
+
"version": "23.1.0-beta.4",
|
|
83
83
|
"requires": {
|
|
84
84
|
"ts-jest": ">=29.2.0"
|
|
85
85
|
},
|
|
86
|
-
"description": "Set `isolatedModules: true` in `tsconfig.spec.json` for ts-jest projects on TypeScript < 6
|
|
86
|
+
"description": "Set `isolatedModules: true` in `tsconfig.spec.json` for ts-jest projects on TypeScript < 6 (ts-jest 29.2+ forces `moduleResolution: node10` on the CommonJS path, which ignores package `exports` maps and breaks resolution of exports-only workspace libraries), then verify the workspace still typechecks and remedy any failures the change surfaced.",
|
|
87
87
|
"implementation": "./dist/src/migrations/update-23-1-0/set-ts-jest-isolated-modules",
|
|
88
|
+
"prompt": "./dist/src/migrations/update-23-1-0/verify-typecheck.md",
|
|
88
89
|
"documentation": "./dist/src/migrations/update-23-1-0/set-ts-jest-isolated-modules.md"
|
|
89
90
|
}
|
|
90
91
|
},
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nx/jest",
|
|
3
|
-
"version": "23.1.0-beta.
|
|
3
|
+
"version": "23.1.0-beta.5",
|
|
4
4
|
"private": false,
|
|
5
5
|
"type": "commonjs",
|
|
6
6
|
"files": [
|
|
@@ -117,11 +117,11 @@
|
|
|
117
117
|
"semver": "^7.6.3",
|
|
118
118
|
"tslib": "^2.3.0",
|
|
119
119
|
"yargs-parser": "21.1.1",
|
|
120
|
-
"@nx/devkit": "23.1.0-beta.
|
|
121
|
-
"@nx/js": "23.1.0-beta.
|
|
120
|
+
"@nx/devkit": "23.1.0-beta.5",
|
|
121
|
+
"@nx/js": "23.1.0-beta.5"
|
|
122
122
|
},
|
|
123
123
|
"devDependencies": {
|
|
124
|
-
"nx": "23.1.0-beta.
|
|
124
|
+
"nx": "23.1.0-beta.5"
|
|
125
125
|
},
|
|
126
126
|
"publishConfig": {
|
|
127
127
|
"access": "public"
|