@nx/jest 17.0.3 → 17.0.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.
Files changed (40) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +9 -4
  3. package/generators.json +2 -2
  4. package/index.d.ts +1 -1
  5. package/index.js +2 -1
  6. package/migrations.json +14 -0
  7. package/package.json +6 -4
  8. package/plugin.d.ts +1 -0
  9. package/plugin.js +6 -0
  10. package/src/generators/configuration/configuration.d.ts +1 -0
  11. package/src/generators/configuration/configuration.js +42 -7
  12. package/src/generators/configuration/files/jest.config.ts__tmpl__ +1 -1
  13. package/src/generators/configuration/files-angular/jest.config.ts__tmpl__ +1 -1
  14. package/src/generators/configuration/lib/create-files.d.ts +1 -1
  15. package/src/generators/configuration/lib/create-files.js +2 -1
  16. package/src/generators/configuration/lib/create-jest-config.d.ts +3 -0
  17. package/src/generators/configuration/lib/create-jest-config.js +102 -0
  18. package/src/generators/configuration/lib/ensure-dependencies.d.ts +3 -0
  19. package/src/generators/configuration/lib/ensure-dependencies.js +34 -0
  20. package/src/generators/configuration/lib/update-jestconfig.js +6 -1
  21. package/src/generators/configuration/lib/update-vscode-recommended-extensions.d.ts +2 -0
  22. package/src/generators/configuration/lib/update-vscode-recommended-extensions.js +18 -0
  23. package/src/generators/configuration/lib/update-workspace.js +1 -8
  24. package/src/generators/configuration/schema.d.ts +8 -0
  25. package/src/generators/configuration/schema.json +1 -1
  26. package/src/generators/init/init.d.ts +4 -3
  27. package/src/generators/init/init.js +66 -130
  28. package/src/generators/init/schema.d.ts +5 -8
  29. package/src/generators/init/schema.json +13 -20
  30. package/src/migrations/update-17-1-0/move-options-to-target-defaults.d.ts +2 -0
  31. package/src/migrations/update-17-1-0/move-options-to-target-defaults.js +117 -0
  32. package/src/plugins/plugin.d.ts +6 -0
  33. package/src/plugins/plugin.js +130 -0
  34. package/src/utils/config/find-root-jest-files.js +3 -0
  35. package/src/utils/config/get-jest-projects.d.ts +16 -1
  36. package/src/utils/config/get-jest-projects.js +98 -3
  37. package/src/utils/config/is-preset-cjs.d.ts +2 -0
  38. package/src/utils/config/is-preset-cjs.js +15 -0
  39. package/src/utils/versions.d.ts +1 -1
  40. package/src/utils/versions.js +1 -1
@@ -1,79 +1,27 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.jestInitGenerator = void 0;
3
+ exports.jestInitGeneratorInternal = exports.jestInitGenerator = void 0;
4
4
  const devkit_1 = require("@nx/devkit");
5
- const js_1 = require("@nx/js");
6
- const find_root_jest_files_1 = require("../../utils/config/find-root-jest-files");
5
+ const update_package_scripts_1 = require("@nx/devkit/src/utils/update-package-scripts");
6
+ const plugin_1 = require("../../plugins/plugin");
7
7
  const versions_1 = require("../../utils/versions");
8
- const schemaDefaults = {
9
- compiler: 'tsc',
10
- js: false,
11
- rootProject: false,
12
- testEnvironment: 'jsdom',
13
- };
14
- function generateGlobalConfig(tree, isJS) {
15
- const contents = isJS
16
- ? (0, devkit_1.stripIndents) `
17
- const { getJestProjects } = require('@nx/jest');
18
-
19
- module.exports = {
20
- projects: getJestProjects()
21
- };`
22
- : (0, devkit_1.stripIndents) `
23
- import { getJestProjects } from '@nx/jest';
24
-
25
- export default {
26
- projects: getJestProjects()
27
- };`;
28
- tree.write(`jest.config.${isJS ? 'js' : 'ts'}`, contents);
29
- }
30
- function createJestConfig(tree, options) {
31
- if (!tree.exists('jest.preset.js')) {
32
- // preset is always js file.
33
- tree.write(`jest.preset.js`, `
34
- const nxPreset = require('@nx/jest/preset').default;
35
-
36
- module.exports = { ...nxPreset }`);
37
- addTestInputs(tree);
38
- }
39
- if (options.rootProject) {
40
- // we don't want any config to be made because the `configurationGenerator` will do it.
41
- // will copy the template config file
42
- return;
43
- }
44
- const rootJestPath = (0, find_root_jest_files_1.findRootJestConfig)(tree);
45
- if (!rootJestPath) {
46
- // if there's not root jest config, we will create one and return
47
- // this can happen when:
48
- // - root jest config was renamed => in which case there is migration needed
49
- // - root project didn't have jest setup => again, no migration is needed
50
- generateGlobalConfig(tree, options.js);
51
- return;
52
- }
53
- if (tree.exists(rootJestPath)) {
54
- // moving from root project config to monorepo-style config
55
- const projects = (0, devkit_1.getProjects)(tree);
56
- const projectNames = Array.from(projects.keys());
57
- const rootProject = projectNames.find((projectName) => projects.get(projectName)?.root === '.');
58
- // root project might have been removed,
59
- // if it's missing there's nothing to migrate
60
- if (rootProject) {
61
- const rootProjectConfig = projects.get(rootProject);
62
- const jestTarget = Object.values(rootProjectConfig.targets || {}).find((t) => t?.executor === '@nx/jest:jest' || t?.executor === '@nrwl/jest:jest');
63
- const isProjectConfig = jestTarget?.options?.jestConfig === rootJestPath;
64
- // if root project doesn't have jest target, there's nothing to migrate
65
- if (isProjectConfig) {
66
- const jestProjectConfig = `jest.config.${rootProjectConfig.projectType === 'application' ? 'app' : 'lib'}.${options.js ? 'js' : 'ts'}`;
67
- tree.rename(rootJestPath, jestProjectConfig);
68
- jestTarget.options.jestConfig = jestProjectConfig;
69
- (0, devkit_1.updateProjectConfiguration)(tree, rootProject, rootProjectConfig);
70
- }
71
- // generate new global config as it was move to project config or is missing
72
- generateGlobalConfig(tree, options.js);
73
- }
8
+ const is_preset_cjs_1 = require("../../utils/config/is-preset-cjs");
9
+ function addPlugin(tree) {
10
+ const nxJson = (0, devkit_1.readNxJson)(tree);
11
+ nxJson.plugins ??= [];
12
+ if (!nxJson.plugins.some((p) => typeof p === 'string'
13
+ ? p === '@nx/jest/plugin'
14
+ : p.plugin === '@nx/jest/plugin')) {
15
+ nxJson.plugins.push({
16
+ plugin: '@nx/jest/plugin',
17
+ options: {
18
+ targetName: 'test',
19
+ },
20
+ });
74
21
  }
22
+ (0, devkit_1.updateNxJson)(tree, nxJson);
75
23
  }
76
- function addTestInputs(tree) {
24
+ function updateProductionFileSet(tree, presetExt) {
77
25
  const nxJson = (0, devkit_1.readNxJson)(tree);
78
26
  const productionFileSet = nxJson.namedInputs?.production;
79
27
  if (productionFileSet) {
@@ -91,80 +39,68 @@ function addTestInputs(tree) {
91
39
  // Dedupe and set
92
40
  nxJson.namedInputs.production = Array.from(new Set(productionFileSet));
93
41
  }
94
- // Test targets depend on all their project's sources + production sources of dependencies
42
+ (0, devkit_1.updateNxJson)(tree, nxJson);
43
+ }
44
+ function addJestTargetDefaults(tree, presetEnv) {
45
+ const nxJson = (0, devkit_1.readNxJson)(tree);
95
46
  nxJson.targetDefaults ??= {};
96
- nxJson.targetDefaults.test ??= {};
97
- nxJson.targetDefaults.test.inputs ??= [
47
+ nxJson.targetDefaults['@nx/jest:jest'] ??= {};
48
+ const productionFileSet = nxJson.namedInputs?.production;
49
+ nxJson.targetDefaults['@nx/jest:jest'].cache ??= true;
50
+ // Test targets depend on all their project's sources + production sources of dependencies
51
+ nxJson.targetDefaults['@nx/jest:jest'].inputs ??= [
98
52
  'default',
99
53
  productionFileSet ? '^production' : '^default',
54
+ `{workspaceRoot}/jest.preset.${presetEnv}`,
100
55
  ];
101
- nxJson.targetDefaults.test.inputs.push('{workspaceRoot}/jest.preset.js');
56
+ nxJson.targetDefaults['@nx/jest:jest'].options ??= {
57
+ passWithNoTests: true,
58
+ };
59
+ nxJson.targetDefaults['@nx/jest:jest'].configurations ??= {
60
+ ci: {
61
+ ci: true,
62
+ codeCoverage: true,
63
+ },
64
+ };
102
65
  (0, devkit_1.updateNxJson)(tree, nxJson);
103
66
  }
104
67
  function updateDependencies(tree, options) {
105
- const dependencies = {
106
- tslib: versions_1.tslibVersion,
107
- };
108
- const devDeps = {
68
+ return (0, devkit_1.addDependenciesToPackageJson)(tree, {}, {
109
69
  '@nx/jest': versions_1.nxVersion,
110
70
  jest: versions_1.jestVersion,
111
- // because the default jest-preset uses ts-jest,
112
- // jest will throw an error if it's not installed
113
- // even if not using it in overriding transformers
114
- 'ts-jest': versions_1.tsJestVersion,
115
- };
116
- if (options.testEnvironment !== 'none') {
117
- devDeps[`jest-environment-${options.testEnvironment}`] = versions_1.jestVersion;
118
- }
119
- if (!options.js) {
120
- devDeps['ts-node'] = versions_1.tsNodeVersion;
121
- devDeps['@types/jest'] = versions_1.jestTypesVersion;
122
- devDeps['@types/node'] = versions_1.typesNodeVersion;
123
- }
124
- if (options.compiler === 'babel' || options.babelJest) {
125
- devDeps['babel-jest'] = versions_1.babelJestVersion;
126
- // in some cases @nx/js will not already be present i.e. node only projects
127
- devDeps['@nx/js'] = versions_1.nxVersion;
128
- }
129
- else if (options.compiler === 'swc') {
130
- devDeps['@swc/jest'] = versions_1.swcJestVersion;
131
- }
132
- return (0, devkit_1.addDependenciesToPackageJson)(tree, dependencies, devDeps);
71
+ }, undefined, options.keepExistingVersions);
133
72
  }
134
- function updateExtensions(host) {
135
- if (!host.exists('.vscode/extensions.json')) {
136
- return;
137
- }
138
- (0, devkit_1.updateJson)(host, '.vscode/extensions.json', (json) => {
139
- json.recommendations = json.recommendations || [];
140
- const extension = 'firsttris.vscode-jest-runner';
141
- if (!json.recommendations.includes(extension)) {
142
- json.recommendations.push(extension);
143
- }
144
- return json;
145
- });
73
+ function jestInitGenerator(tree, options) {
74
+ return jestInitGeneratorInternal(tree, { addPlugin: false, ...options });
146
75
  }
147
- async function jestInitGenerator(tree, schema) {
148
- const options = normalizeOptions(schema);
76
+ exports.jestInitGenerator = jestInitGenerator;
77
+ async function jestInitGeneratorInternal(tree, options) {
78
+ const nxJson = (0, devkit_1.readNxJson)(tree);
79
+ const addPluginDefault = process.env.NX_ADD_PLUGINS !== 'false' &&
80
+ nxJson.useInferencePlugins !== false;
81
+ options.addPlugin ??= addPluginDefault;
82
+ const presetExt = (0, is_preset_cjs_1.isPresetCjs)(tree) ? 'cjs' : 'js';
83
+ if (!tree.exists('jest.preset.js') && !tree.exists('jest.preset.cjs')) {
84
+ updateProductionFileSet(tree, presetExt);
85
+ if (options.addPlugin) {
86
+ addPlugin(tree);
87
+ }
88
+ else {
89
+ addJestTargetDefaults(tree, presetExt);
90
+ }
91
+ }
149
92
  const tasks = [];
150
- tasks.push(await (0, js_1.initGenerator)(tree, {
151
- ...schema,
152
- skipFormat: true,
153
- }));
154
- createJestConfig(tree, options);
155
93
  if (!options.skipPackageJson) {
156
- (0, devkit_1.removeDependenciesFromPackageJson)(tree, ['@nx/jest'], []);
157
- const installTask = updateDependencies(tree, options);
158
- tasks.push(installTask);
94
+ tasks.push((0, devkit_1.removeDependenciesFromPackageJson)(tree, ['@nx/jest'], []));
95
+ tasks.push(updateDependencies(tree, options));
96
+ }
97
+ if (options.updatePackageScripts) {
98
+ await (0, update_package_scripts_1.updatePackageScripts)(tree, plugin_1.createNodes);
99
+ }
100
+ if (!options.skipFormat) {
101
+ await (0, devkit_1.formatFiles)(tree);
159
102
  }
160
- updateExtensions(tree);
161
103
  return (0, devkit_1.runTasksInSerial)(...tasks);
162
104
  }
163
- exports.jestInitGenerator = jestInitGenerator;
164
- function normalizeOptions(options) {
165
- return {
166
- ...schemaDefaults,
167
- ...options,
168
- };
169
- }
105
+ exports.jestInitGeneratorInternal = jestInitGeneratorInternal;
170
106
  exports.default = jestInitGenerator;
@@ -1,11 +1,8 @@
1
1
  export interface JestInitSchema {
2
- compiler?: 'tsc' | 'babel' | 'swc';
3
- js?: boolean;
2
+ skipFormat?: boolean;
4
3
  skipPackageJson?: boolean;
5
- testEnvironment?: 'node' | 'jsdom' | 'none';
6
- /**
7
- * @deprecated
8
- */
9
- babelJest?: boolean;
10
- rootProject?: boolean;
4
+ keepExistingVersions?: boolean;
5
+ updatePackageScripts?: boolean;
6
+
7
+ addPlugin?: boolean;
11
8
  }
@@ -1,16 +1,16 @@
1
1
  {
2
- "$schema": "http://json-schema.org/schema",
2
+ "$schema": "https://json-schema.org/schema",
3
3
  "$id": "NxJestInit",
4
4
  "cli": "nx",
5
5
  "title": "Jest init",
6
6
  "description": "Add Jest Configuration to a workspace.",
7
7
  "type": "object",
8
8
  "properties": {
9
- "babelJest": {
9
+ "skipFormat": {
10
+ "description": "Skip formatting files.",
10
11
  "type": "boolean",
11
- "alias": "babel-jest",
12
- "description": "Use `babel-jest` instead of `ts-jest`.",
13
- "default": false
12
+ "default": false,
13
+ "x-priority": "internal"
14
14
  },
15
15
  "skipPackageJson": {
16
16
  "type": "boolean",
@@ -18,24 +18,17 @@
18
18
  "description": "Do not add dependencies to `package.json`.",
19
19
  "x-priority": "internal"
20
20
  },
21
- "testEnvironment": {
22
- "type": "string",
23
- "enum": ["jsdom", "node", "none"],
24
- "description": "The test environment for jest. This controls which jest-environment-* package is installed",
25
- "default": "jsdom",
26
- "x-priority": "important"
27
- },
28
- "js": {
21
+ "keepExistingVersions": {
29
22
  "type": "boolean",
30
- "default": false,
31
- "description": "Use JavaScript instead of TypeScript for config files"
23
+ "x-priority": "internal",
24
+ "description": "Keep existing dependencies versions",
25
+ "default": false
32
26
  },
33
- "rootProject": {
34
- "description": "initialize Jest for an application at the root of the workspace",
27
+ "updatePackageScripts": {
35
28
  "type": "boolean",
36
- "default": false,
37
- "hidden": true,
38
- "x-priority": "internal"
29
+ "x-priority": "internal",
30
+ "description": "Update `package.json` scripts with inferred targets",
31
+ "default": false
39
32
  }
40
33
  },
41
34
  "required": []
@@ -0,0 +1,2 @@
1
+ import { Tree } from '@nx/devkit';
2
+ export default function update(tree: Tree): Promise<void>;
@@ -0,0 +1,117 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const devkit_1 = require("@nx/devkit");
4
+ const executor_options_utils_1 = require("@nx/devkit/src/generators/executor-options-utils");
5
+ const project_configuration_utils_1 = require("nx/src/project-graph/utils/project-configuration-utils");
6
+ async function update(tree) {
7
+ const nxJson = (0, devkit_1.readNxJson)(tree);
8
+ // Don't override anything if there are already target defaults for jest
9
+ if (nxJson.targetDefaults?.['@nx/jest:jest']) {
10
+ return;
11
+ }
12
+ nxJson.targetDefaults ??= {};
13
+ /**
14
+ * A set of targets which does not use any other executors
15
+ */
16
+ const jestTargets = new Set();
17
+ const graph = await (0, devkit_1.createProjectGraphAsync)();
18
+ (0, executor_options_utils_1.forEachExecutorOptionsInGraph)(graph, '@nx/jest:jest', (value, proj, targetName) => {
19
+ jestTargets.add(targetName);
20
+ });
21
+ // Workspace does not use jest?
22
+ if (jestTargets.size === 0) {
23
+ return;
24
+ }
25
+ // Use the project graph so targets which are inferred are considered
26
+ const projects = graph.nodes;
27
+ const projectMap = (0, devkit_1.getProjects)(tree);
28
+ const jestDefaults = (nxJson.targetDefaults['@nx/jest:jest'] = {});
29
+ // All jest targets have the same name
30
+ if (jestTargets.size === 1) {
31
+ const targetName = Array.from(jestTargets)[0];
32
+ if (nxJson.targetDefaults[targetName]) {
33
+ Object.assign(jestDefaults, nxJson.targetDefaults[targetName]);
34
+ }
35
+ }
36
+ jestDefaults.cache ??= true;
37
+ const inputs = ['default'];
38
+ inputs.push(nxJson.namedInputs?.production ? '^production' : '^default');
39
+ if (tree.exists('jest.preset.js')) {
40
+ inputs.push('{workspaceRoot}/jest.preset.js');
41
+ }
42
+ jestDefaults.inputs ??= inputs;
43
+ // Remember if there were already defaults so we don't assume the executor default
44
+ const passWithNoTestsPreviouslyInDefaults = jestDefaults.options?.passWithNoTests !== undefined;
45
+ const ciCiPreviouslyInDefaults = jestDefaults.configurations?.ci?.ci !== undefined;
46
+ const ciCodeCoveragePreviouslyInDefaults = jestDefaults.configurations?.ci?.codeCoverage !== undefined;
47
+ jestDefaults.options ??= {};
48
+ jestDefaults.options.passWithNoTests ??= true;
49
+ jestDefaults.configurations ??= {};
50
+ jestDefaults.configurations.ci ??= {};
51
+ jestDefaults.configurations.ci.ci ??= true;
52
+ jestDefaults.configurations.ci.codeCoverage ??= true;
53
+ // Cleanup old target defaults
54
+ for (const [targetDefaultKey, targetDefault] of Object.entries(nxJson.targetDefaults)) {
55
+ if (!isTargetDefaultUsed(targetDefault, nxJson.targetDefaults, projects, projectMap)) {
56
+ delete nxJson.targetDefaults[targetDefaultKey];
57
+ }
58
+ }
59
+ (0, devkit_1.updateNxJson)(tree, nxJson);
60
+ (0, executor_options_utils_1.forEachExecutorOptions)(tree, '@nx/jest:jest', (value, proj, targetName, configuration) => {
61
+ const projConfig = projectMap.get(proj);
62
+ if (!configuration) {
63
+ // Options
64
+ if (value.passWithNoTests === jestDefaults.options.passWithNoTests) {
65
+ delete projConfig.targets[targetName].options.passWithNoTests;
66
+ }
67
+ else if (!passWithNoTestsPreviouslyInDefaults) {
68
+ projConfig.targets[targetName].options.passWithNoTests ??= false;
69
+ }
70
+ if (Object.keys(projConfig.targets[targetName].options).length === 0) {
71
+ delete projConfig.targets[targetName].options;
72
+ }
73
+ }
74
+ else if (configuration === 'ci') {
75
+ // CI Config
76
+ if (value.ci === jestDefaults.configurations.ci.ci) {
77
+ delete projConfig.targets[targetName].configurations.ci.ci;
78
+ }
79
+ else if (ciCiPreviouslyInDefaults) {
80
+ projConfig.targets[targetName].configurations.ci.ci ??= false;
81
+ }
82
+ if (value.codeCoverage === jestDefaults.configurations.ci.codeCoverage) {
83
+ delete projConfig.targets[targetName].configurations.ci.codeCoverage;
84
+ }
85
+ else if (ciCodeCoveragePreviouslyInDefaults) {
86
+ projConfig.targets[targetName].configurations.ci.codeCoverage ??=
87
+ false;
88
+ }
89
+ if (Object.keys(projConfig.targets[targetName].configurations.ci)
90
+ .length === 0) {
91
+ delete projConfig.targets[targetName].configurations.ci;
92
+ }
93
+ if (Object.keys(projConfig.targets[targetName].configurations).length ===
94
+ 0) {
95
+ delete projConfig.targets[targetName].configurations;
96
+ }
97
+ }
98
+ (0, devkit_1.updateProjectConfiguration)(tree, proj, projConfig);
99
+ });
100
+ await (0, devkit_1.formatFiles)(tree);
101
+ }
102
+ exports.default = update;
103
+ /**
104
+ * Checks every target on every project to see if one of them uses the target default
105
+ */
106
+ function isTargetDefaultUsed(targetDefault, targetDefaults, projects, projectMap) {
107
+ for (const p of Object.values(projects)) {
108
+ for (const targetName in p.data?.targets ?? {}) {
109
+ if ((0, project_configuration_utils_1.readTargetDefaultsForTarget)(targetName, targetDefaults,
110
+ // It might seem like we should use the graph here too but we don't want to pass an executor which was processed in the graph
111
+ projectMap.get(p.name)?.targets?.[targetName]?.executor) === targetDefault) {
112
+ return true;
113
+ }
114
+ }
115
+ }
116
+ return false;
117
+ }
@@ -0,0 +1,6 @@
1
+ import { CreateDependencies, CreateNodes } from '@nx/devkit';
2
+ export interface JestPluginOptions {
3
+ targetName?: string;
4
+ }
5
+ export declare const createDependencies: CreateDependencies;
6
+ export declare const createNodes: CreateNodes<JestPluginOptions>;
@@ -0,0 +1,130 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createNodes = exports.createDependencies = void 0;
4
+ const devkit_1 = require("@nx/devkit");
5
+ const path_1 = require("path");
6
+ const project_configuration_utils_1 = require("nx/src/project-graph/utils/project-configuration-utils");
7
+ const get_named_inputs_1 = require("@nx/devkit/src/utils/get-named-inputs");
8
+ const fs_1 = require("fs");
9
+ const jest_config_1 = require("jest-config");
10
+ const cache_directory_1 = require("nx/src/utils/cache-directory");
11
+ const calculate_hash_for_create_nodes_1 = require("@nx/devkit/src/utils/calculate-hash-for-create-nodes");
12
+ const package_json_workspaces_1 = require("nx/src/plugins/package-json-workspaces");
13
+ const globs_1 = require("nx/src/utils/globs");
14
+ const minimatch_1 = require("minimatch");
15
+ const cachePath = (0, path_1.join)(cache_directory_1.projectGraphCacheDirectory, 'jest.hash');
16
+ const targetsCache = (0, fs_1.existsSync)(cachePath) ? readTargetsCache() : {};
17
+ const calculatedTargets = {};
18
+ function readTargetsCache() {
19
+ return (0, devkit_1.readJsonFile)(cachePath);
20
+ }
21
+ function writeTargetsToCache(targets) {
22
+ (0, devkit_1.writeJsonFile)(cachePath, targets);
23
+ }
24
+ const createDependencies = () => {
25
+ writeTargetsToCache(calculatedTargets);
26
+ return [];
27
+ };
28
+ exports.createDependencies = createDependencies;
29
+ exports.createNodes = [
30
+ '**/jest.config.{cjs,mjs,js,cts,mts,ts}',
31
+ async (configFilePath, options, context) => {
32
+ const projectRoot = (0, path_1.dirname)(configFilePath);
33
+ const packageManagerWorkspacesGlob = (0, globs_1.combineGlobPatterns)((0, package_json_workspaces_1.getGlobPatternsFromPackageManagerWorkspaces)(context.workspaceRoot));
34
+ // Do not create a project if package.json and project.json isn't there.
35
+ const siblingFiles = (0, fs_1.readdirSync)((0, path_1.join)(context.workspaceRoot, projectRoot));
36
+ if (!siblingFiles.includes('package.json') &&
37
+ !siblingFiles.includes('project.json')) {
38
+ return {};
39
+ }
40
+ else if (!siblingFiles.includes('project.json') &&
41
+ siblingFiles.includes('package.json')) {
42
+ const path = (0, devkit_1.joinPathFragments)(projectRoot, 'package.json');
43
+ const isPackageJsonProject = (0, minimatch_1.minimatch)(path, packageManagerWorkspacesGlob);
44
+ if (!isPackageJsonProject) {
45
+ return {};
46
+ }
47
+ }
48
+ const jestConfigContent = (0, fs_1.readFileSync)((0, path_1.resolve)(context.workspaceRoot, configFilePath), 'utf-8');
49
+ if (jestConfigContent.includes('getJestProjectsAsync()')) {
50
+ // The `getJestProjectsAsync` function uses the project graph, which leads to a
51
+ // circular dependency. We can skip this since it's no intended to be used for
52
+ // an Nx project.
53
+ return {};
54
+ }
55
+ options = normalizeOptions(options);
56
+ const hash = (0, calculate_hash_for_create_nodes_1.calculateHashForCreateNodes)(projectRoot, options, context);
57
+ const targets = targetsCache[hash] ??
58
+ (await buildJestTargets(configFilePath, projectRoot, options, context));
59
+ calculatedTargets[hash] = targets;
60
+ return {
61
+ projects: {
62
+ [projectRoot]: {
63
+ root: projectRoot,
64
+ targets: targets,
65
+ },
66
+ },
67
+ };
68
+ },
69
+ ];
70
+ async function buildJestTargets(configFilePath, projectRoot, options, context) {
71
+ const config = await (0, jest_config_1.readConfig)({
72
+ _: [],
73
+ $0: undefined,
74
+ }, (0, path_1.resolve)(context.workspaceRoot, configFilePath));
75
+ const targetDefaults = (0, project_configuration_utils_1.readTargetDefaultsForTarget)(options.targetName, context.nxJsonConfiguration.targetDefaults, 'nx:run-commands');
76
+ const namedInputs = (0, get_named_inputs_1.getNamedInputs)(projectRoot, context);
77
+ const targets = {};
78
+ const target = (targets[options.targetName] = {
79
+ command: 'jest',
80
+ options: {
81
+ cwd: projectRoot,
82
+ },
83
+ });
84
+ if (!targetDefaults?.cache) {
85
+ target.cache = true;
86
+ }
87
+ if (!targetDefaults?.inputs) {
88
+ target.inputs = getInputs(namedInputs);
89
+ }
90
+ if (!targetDefaults?.outputs) {
91
+ target.outputs = getOutputs(projectRoot, config, context);
92
+ }
93
+ return targets;
94
+ }
95
+ function getInputs(namedInputs) {
96
+ return [
97
+ ...('production' in namedInputs
98
+ ? ['default', '^production']
99
+ : ['default', '^default']),
100
+ {
101
+ externalDependencies: ['jest'],
102
+ },
103
+ ];
104
+ }
105
+ function getOutputs(projectRoot, { globalConfig }, context) {
106
+ function getOutput(path) {
107
+ const relativePath = (0, path_1.relative)((0, path_1.join)(context.workspaceRoot, projectRoot), path);
108
+ if (relativePath.startsWith('..')) {
109
+ return (0, path_1.join)('{workspaceRoot}', (0, path_1.join)(projectRoot, relativePath));
110
+ }
111
+ else {
112
+ return (0, path_1.join)('{projectRoot}', relativePath);
113
+ }
114
+ }
115
+ const outputs = [];
116
+ for (const outputOption of [
117
+ globalConfig.coverageDirectory,
118
+ globalConfig.outputFile,
119
+ ]) {
120
+ if (outputOption) {
121
+ outputs.push(getOutput(outputOption));
122
+ }
123
+ }
124
+ return outputs;
125
+ }
126
+ function normalizeOptions(options) {
127
+ options ??= {};
128
+ options.targetName ??= 'test';
129
+ return options;
130
+ }
@@ -15,6 +15,9 @@ function findRootJestPreset(tree) {
15
15
  if (tree.exists('jest.preset.js')) {
16
16
  return 'jest.preset.js';
17
17
  }
18
+ if (tree.exists('jest.preset.cjs')) {
19
+ return 'jest.preset.cjs';
20
+ }
18
21
  return null;
19
22
  }
20
23
  exports.findRootJestPreset = findRootJestPreset;
@@ -2,7 +2,8 @@
2
2
  * Get a list of paths to all the jest config files
3
3
  * using the Nx Jest executor.
4
4
  *
5
- * This is used to configure Jest multi-project support.
5
+ * This is used to configure Jest multi-project support. To support projects
6
+ * using inferred targets @see getJestProjectsAsync
6
7
  *
7
8
  * To add a project not using the Nx Jest executor:
8
9
  * export default {
@@ -17,3 +18,17 @@ export declare function getJestProjects(): string[];
17
18
  * https://jestjs.io/docs/configuration#testpathignorepatterns-arraystring
18
19
  * */
19
20
  export declare function getNestedJestProjects(): string[];
21
+ /**
22
+ * Get a list of paths to all the jest config files
23
+ * using the Nx Jest executor and `@nx/run:commands`
24
+ * running `jest`.
25
+ *
26
+ * This is used to configure Jest multi-project support.
27
+ *
28
+ * To add a project not using the Nx Jest executor:
29
+ * export default async () => ({
30
+ * projects: [...(await getJestProjectsAsync()), '<rootDir>/path/to/jest.config.ts'];
31
+ * });
32
+ *
33
+ **/
34
+ export declare function getJestProjectsAsync(): Promise<string[]>;