@nx/jest 17.3.0-beta.2 → 17.3.0-beta.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nx/jest",
3
- "version": "17.3.0-beta.2",
3
+ "version": "17.3.0-beta.3",
4
4
  "private": false,
5
5
  "description": "The Nx Plugin for Jest contains executors and generators allowing your workspace to use the powerful Jest testing capabilities.",
6
6
  "repository": {
@@ -42,11 +42,12 @@
42
42
  "jest-config": "^29.4.1",
43
43
  "jest-resolve": "^29.4.1",
44
44
  "jest-util": "^29.4.1",
45
+ "minimatch": "3.0.5",
45
46
  "resolve.exports": "1.1.0",
46
47
  "tslib": "^2.3.0",
47
- "@nx/devkit": "17.3.0-beta.2",
48
- "@nx/js": "17.3.0-beta.2",
49
- "@nrwl/jest": "17.3.0-beta.2"
48
+ "@nx/devkit": "17.3.0-beta.3",
49
+ "@nx/js": "17.3.0-beta.3",
50
+ "@nrwl/jest": "17.3.0-beta.3"
50
51
  },
51
52
  "publishConfig": {
52
53
  "access": "public"
package/plugin.d.ts ADDED
@@ -0,0 +1 @@
1
+ export { createNodes, createDependencies, JestPluginOptions, } from './src/plugins/plugin';
package/plugin.js ADDED
@@ -0,0 +1,6 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createDependencies = exports.createNodes = void 0;
4
+ var plugin_1 = require("./src/plugins/plugin");
5
+ Object.defineProperty(exports, "createNodes", { enumerable: true, get: function () { return plugin_1.createNodes; } });
6
+ Object.defineProperty(exports, "createDependencies", { enumerable: true, get: function () { return plugin_1.createDependencies; } });
@@ -45,7 +45,13 @@ async function configurationGenerator(tree, schema) {
45
45
  (0, check_for_test_target_1.checkForTestTarget)(tree, options);
46
46
  (0, create_files_1.createFiles)(tree, options);
47
47
  (0, update_tsconfig_1.updateTsConfig)(tree, options);
48
- (0, update_workspace_1.updateWorkspace)(tree, options);
48
+ const nxJson = (0, devkit_1.readNxJson)(tree);
49
+ const hasPlugin = nxJson.plugins?.some((p) => typeof p === 'string'
50
+ ? p === '@nx/jest/plugin'
51
+ : p.plugin === '@nx/jest/plugin');
52
+ if (!hasPlugin) {
53
+ (0, update_workspace_1.updateWorkspace)(tree, options);
54
+ }
49
55
  if (!schema.skipFormat) {
50
56
  await (0, devkit_1.formatFiles)(tree);
51
57
  }
@@ -5,6 +5,7 @@ const devkit_1 = require("@nx/devkit");
5
5
  const js_1 = require("@nx/js");
6
6
  const find_root_jest_files_1 = require("../../utils/config/find-root-jest-files");
7
7
  const versions_1 = require("../../utils/versions");
8
+ const project_configuration_utils_1 = require("nx/src/project-graph/utils/project-configuration-utils");
8
9
  const schemaDefaults = {
9
10
  compiler: 'tsc',
10
11
  js: false,
@@ -27,15 +28,36 @@ function generateGlobalConfig(tree, isJS) {
27
28
  };`;
28
29
  tree.write(`jest.config.${isJS ? 'js' : 'ts'}`, contents);
29
30
  }
30
- function createJestConfig(tree, options) {
31
+ function addPlugin(tree) {
32
+ const nxJson = (0, devkit_1.readNxJson)(tree);
33
+ nxJson.plugins ??= [];
34
+ if (!nxJson.plugins.some((p) => typeof p === 'string'
35
+ ? p === '@nx/jest/plugin'
36
+ : p.plugin === '@nx/jest/plugin')) {
37
+ nxJson.plugins.push({
38
+ plugin: '@nx/jest/plugin',
39
+ options: {
40
+ targetName: 'test',
41
+ },
42
+ });
43
+ }
44
+ (0, devkit_1.updateNxJson)(tree, nxJson);
45
+ }
46
+ async function createJestConfig(tree, options) {
31
47
  if (!tree.exists('jest.preset.js')) {
32
48
  // preset is always js file.
33
49
  tree.write(`jest.preset.js`, `
34
50
  const nxPreset = require('@nx/jest/preset').default;
35
51
 
36
52
  module.exports = { ...nxPreset }`);
53
+ const shouldAddPlugin = process.env.NX_PCV3 === 'true';
54
+ if (shouldAddPlugin) {
55
+ addPlugin(tree);
56
+ }
37
57
  updateProductionFileSet(tree);
38
- addJestTargetDefaults(tree);
58
+ if (!shouldAddPlugin) {
59
+ addJestTargetDefaults(tree, shouldAddPlugin);
60
+ }
39
61
  }
40
62
  if (options.rootProject) {
41
63
  // we don't want any config to be made because the `configurationGenerator` will do it.
@@ -53,22 +75,56 @@ function createJestConfig(tree, options) {
53
75
  }
54
76
  if (tree.exists(rootJestPath)) {
55
77
  // moving from root project config to monorepo-style config
56
- const projects = (0, devkit_1.getProjects)(tree);
57
- const projectNames = Array.from(projects.keys());
58
- const rootProject = projectNames.find((projectName) => projects.get(projectName)?.root === '.');
78
+ const { nodes: projects } = await (0, devkit_1.createProjectGraphAsync)();
79
+ const projectConfigurations = Object.values(projects);
80
+ const rootProject = projectConfigurations.find((projectNode) => projectNode.data?.root === '.');
59
81
  // root project might have been removed,
60
82
  // if it's missing there's nothing to migrate
61
83
  if (rootProject) {
62
- const rootProjectConfig = projects.get(rootProject);
63
- const jestTarget = Object.values(rootProjectConfig.targets || {}).find((t) => t?.executor === '@nx/jest:jest' || t?.executor === '@nrwl/jest:jest');
64
- const isProjectConfig = jestTarget?.options?.jestConfig === rootJestPath;
84
+ const jestTarget = Object.entries(rootProject.data?.targets ?? {}).find(([_, t]) => ((t?.executor === '@nx/jest:jest' ||
85
+ t?.executor === '@nrwl/jest:jest') &&
86
+ t?.options?.jestConfig === rootJestPath) ||
87
+ (t?.executor === 'nx:run-commands' && t?.options?.command === 'jest'));
88
+ if (!jestTarget) {
89
+ return;
90
+ }
91
+ const [jestTargetName, jestTargetConfigInGraph] = jestTarget;
65
92
  // if root project doesn't have jest target, there's nothing to migrate
66
- if (isProjectConfig) {
67
- const jestProjectConfig = `jest.config.${rootProjectConfig.projectType === 'application' ? 'app' : 'lib'}.${options.js ? 'js' : 'ts'}`;
68
- tree.rename(rootJestPath, jestProjectConfig);
69
- jestTarget.options.jestConfig = jestProjectConfig;
70
- (0, devkit_1.updateProjectConfiguration)(tree, rootProject, rootProjectConfig);
93
+ const rootProjectConfig = (0, devkit_1.readProjectConfiguration)(tree, rootProject.name);
94
+ if (rootProjectConfig.targets['test']?.executor === 'nx:run-commands'
95
+ ? rootProjectConfig.targets['test']?.command !== 'jest'
96
+ : rootProjectConfig.targets['test']?.options?.jestConfig !==
97
+ rootJestPath) {
98
+ // Jest target has already been updated
99
+ return;
71
100
  }
101
+ const jestProjectConfig = `jest.config.${rootProjectConfig.projectType === 'application' ? 'app' : 'lib'}.${options.js ? 'js' : 'ts'}`;
102
+ tree.rename(rootJestPath, jestProjectConfig);
103
+ const nxJson = (0, devkit_1.readNxJson)(tree);
104
+ const targetDefaults = (0, project_configuration_utils_1.readTargetDefaultsForTarget)(jestTargetName, nxJson.targetDefaults, jestTargetConfigInGraph.executor);
105
+ const target = (rootProjectConfig.targets[jestTargetName] ??=
106
+ jestTargetConfigInGraph.executor === 'nx:run-commands'
107
+ ? { command: `jest --config ${jestProjectConfig}` }
108
+ : {
109
+ executor: jestTargetConfigInGraph.executor,
110
+ options: {},
111
+ });
112
+ if (target.executor === '@nx/jest:jest') {
113
+ target.options.jestConfig = jestProjectConfig;
114
+ }
115
+ if (targetDefaults?.cache === undefined) {
116
+ target.cache = jestTargetConfigInGraph.cache;
117
+ }
118
+ if (targetDefaults?.inputs === undefined) {
119
+ target.inputs = jestTargetConfigInGraph.inputs;
120
+ }
121
+ if (targetDefaults?.outputs === undefined) {
122
+ target.outputs = jestTargetConfigInGraph.outputs;
123
+ }
124
+ if (targetDefaults?.dependsOn === undefined) {
125
+ target.dependsOn = jestTargetConfigInGraph.dependsOn;
126
+ }
127
+ (0, devkit_1.updateProjectConfiguration)(tree, rootProject.name, rootProjectConfig);
72
128
  // generate new global config as it was move to project config or is missing
73
129
  generateGlobalConfig(tree, options.js);
74
130
  }
@@ -94,18 +150,20 @@ function updateProductionFileSet(tree) {
94
150
  }
95
151
  (0, devkit_1.updateNxJson)(tree, nxJson);
96
152
  }
97
- function addJestTargetDefaults(tree) {
153
+ function addJestTargetDefaults(tree, hasPlugin) {
98
154
  const nxJson = (0, devkit_1.readNxJson)(tree);
99
- const productionFileSet = nxJson.namedInputs?.production;
100
155
  nxJson.targetDefaults ??= {};
101
156
  nxJson.targetDefaults['@nx/jest:jest'] ??= {};
102
- nxJson.targetDefaults['@nx/jest:jest'].cache ??= true;
103
- // Test targets depend on all their project's sources + production sources of dependencies
104
- nxJson.targetDefaults['@nx/jest:jest'].inputs ??= [
105
- 'default',
106
- productionFileSet ? '^production' : '^default',
107
- '{workspaceRoot}/jest.preset.js',
108
- ];
157
+ if (!hasPlugin) {
158
+ const productionFileSet = nxJson.namedInputs?.production;
159
+ nxJson.targetDefaults['@nx/jest:jest'].cache ??= true;
160
+ // Test targets depend on all their project's sources + production sources of dependencies
161
+ nxJson.targetDefaults['@nx/jest:jest'].inputs ??= [
162
+ 'default',
163
+ productionFileSet ? '^production' : '^default',
164
+ '{workspaceRoot}/jest.preset.js',
165
+ ];
166
+ }
109
167
  nxJson.targetDefaults['@nx/jest:jest'].options ??= {
110
168
  passWithNoTests: true,
111
169
  };
@@ -167,7 +225,7 @@ async function jestInitGenerator(tree, schema) {
167
225
  ...schema,
168
226
  skipFormat: true,
169
227
  }));
170
- createJestConfig(tree, options);
228
+ await createJestConfig(tree, options);
171
229
  if (!options.skipPackageJson) {
172
230
  (0, devkit_1.removeDependenciesFromPackageJson)(tree, ['@nx/jest'], []);
173
231
  const installTask = updateDependencies(tree, options);
@@ -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,123 @@
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/plugins/package-json-workspaces");
13
+ const globs_1 = require("nx/src/utils/globs");
14
+ const minimatch = 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 = minimatch(path, packageManagerWorkspacesGlob);
44
+ if (!isPackageJsonProject) {
45
+ return {};
46
+ }
47
+ }
48
+ options = normalizeOptions(options);
49
+ const hash = (0, calculate_hash_for_create_nodes_1.calculateHashForCreateNodes)(projectRoot, options, context);
50
+ const targets = targetsCache[hash] ??
51
+ (await buildJestTargets(configFilePath, projectRoot, options, context));
52
+ calculatedTargets[hash] = targets;
53
+ return {
54
+ projects: {
55
+ [projectRoot]: {
56
+ root: projectRoot,
57
+ targets: targets,
58
+ },
59
+ },
60
+ };
61
+ },
62
+ ];
63
+ async function buildJestTargets(configFilePath, projectRoot, options, context) {
64
+ const config = await (0, jest_config_1.readConfig)({
65
+ _: [],
66
+ $0: undefined,
67
+ }, (0, path_1.resolve)(context.workspaceRoot, configFilePath), true, null, undefined, true);
68
+ const targetDefaults = (0, project_configuration_utils_1.readTargetDefaultsForTarget)(options.targetName, context.nxJsonConfiguration.targetDefaults, 'nx:run-commands');
69
+ const namedInputs = (0, get_named_inputs_1.getNamedInputs)(projectRoot, context);
70
+ const targets = {};
71
+ const target = (targets[options.targetName] = {
72
+ command: 'jest',
73
+ options: {
74
+ cwd: projectRoot,
75
+ },
76
+ });
77
+ if (!targetDefaults?.cache) {
78
+ target.cache = true;
79
+ }
80
+ if (!targetDefaults?.inputs) {
81
+ target.inputs = getInputs(namedInputs);
82
+ }
83
+ if (!targetDefaults?.outputs) {
84
+ target.outputs = getOutputs(projectRoot, config, context);
85
+ }
86
+ return targets;
87
+ }
88
+ function getInputs(namedInputs) {
89
+ return [
90
+ ...('production' in namedInputs
91
+ ? ['default', '^production']
92
+ : ['default', '^default']),
93
+ {
94
+ externalDependencies: ['jest'],
95
+ },
96
+ ];
97
+ }
98
+ function getOutputs(projectRoot, { globalConfig }, context) {
99
+ function getOutput(path) {
100
+ const relativePath = (0, path_1.relative)((0, path_1.join)(context.workspaceRoot, projectRoot), path);
101
+ if (relativePath.startsWith('..')) {
102
+ return (0, path_1.join)('{workspaceRoot}', (0, path_1.join)(projectRoot, relativePath));
103
+ }
104
+ else {
105
+ return (0, path_1.join)('{projectRoot}', relativePath);
106
+ }
107
+ }
108
+ const outputs = [];
109
+ for (const outputOption of [
110
+ globalConfig.coverageDirectory,
111
+ globalConfig.outputFile,
112
+ ]) {
113
+ if (outputOption) {
114
+ outputs.push(getOutput(outputOption));
115
+ }
116
+ }
117
+ return outputs;
118
+ }
119
+ function normalizeOptions(options) {
120
+ options ??= {};
121
+ options.targetName ??= 'test';
122
+ return options;
123
+ }