fix(testing): handle existing jest preset file correctly (#23437)
<!-- Please make sure you have read the submission guidelines before posting an PR --> <!-- https://github.com/nrwl/nx/blob/master/CONTRIBUTING.md#-submitting-a-pr --> <!-- Please make sure that your commit message follows our format --> <!-- Example: `fix(nx): must begin with lowercase` --> ## Current Behavior <!-- This is the behavior we have today --> ## Expected Behavior <!-- This is the behavior we should expect with the changes in this PR --> ## Related Issue(s) <!-- Please link the issue being fixed so it gets closed when this is merged. --> Fixes #20449
This commit is contained in:
parent
937019b172
commit
217a349adc
5
packages/jest/preset.ts
Normal file
5
packages/jest/preset.ts
Normal file
@ -0,0 +1,5 @@
|
||||
import { nxPreset } from './preset/jest-preset';
|
||||
|
||||
export { nxPreset };
|
||||
|
||||
export default nxPreset;
|
||||
@ -262,19 +262,33 @@ describe('jestProject', () => {
|
||||
expect(tree.exists('libs/lib1/jest.config.js')).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should always use jest.preset.js with --js', async () => {
|
||||
tree.write('jest.preset.ts', '');
|
||||
it('should generate a jest.preset.js when it does not exist', async () => {
|
||||
await configurationGenerator(tree, {
|
||||
...defaultOptions,
|
||||
project: 'lib1',
|
||||
js: true,
|
||||
} as JestProjectSchema);
|
||||
expect(tree.exists('libs/lib1/jest.config.js')).toBeTruthy();
|
||||
expect(tree.exists('jest.preset.js')).toBeTruthy();
|
||||
expect(tree.read('libs/lib1/jest.config.js', 'utf-8')).toContain(
|
||||
"preset: '../../jest.preset.js',"
|
||||
);
|
||||
});
|
||||
|
||||
it('should not override existing jest preset file and should point to it in jest.config files', async () => {
|
||||
tree.write('jest.preset.mjs', 'export default {}');
|
||||
await configurationGenerator(tree, {
|
||||
...defaultOptions,
|
||||
project: 'lib1',
|
||||
js: true,
|
||||
} as JestProjectSchema);
|
||||
expect(tree.exists('libs/lib1/jest.config.js')).toBeTruthy();
|
||||
expect(tree.exists('jest.preset.mjs')).toBeTruthy();
|
||||
expect(tree.read('libs/lib1/jest.config.js', 'utf-8')).toContain(
|
||||
"preset: '../../jest.preset.mjs',"
|
||||
);
|
||||
});
|
||||
|
||||
it('should use module.exports with --js flag', async () => {
|
||||
await configurationGenerator(tree, {
|
||||
...defaultOptions,
|
||||
|
||||
@ -17,7 +17,7 @@ import {
|
||||
} from '@nx/devkit';
|
||||
import { initGenerator as jsInitGenerator } from '@nx/js';
|
||||
import { JestPluginOptions } from '../../plugins/plugin';
|
||||
import { isPresetCjs } from '../../utils/config/is-preset-cjs';
|
||||
import { getPresetExt } from '../../utils/config/config-file';
|
||||
|
||||
const schemaDefaults = {
|
||||
setupFile: 'none',
|
||||
@ -90,7 +90,7 @@ export async function configurationGeneratorInternal(
|
||||
tasks.push(ensureDependencies(tree, options));
|
||||
}
|
||||
|
||||
const presetExt = isPresetCjs(tree) ? 'cjs' : 'js';
|
||||
const presetExt = getPresetExt(tree);
|
||||
|
||||
await createJestConfig(tree, options, presetExt);
|
||||
checkForTestTarget(tree, options);
|
||||
|
||||
@ -11,7 +11,7 @@ projects: await getJestProjectsAsync()
|
||||
exports[`createJestConfig should generate files 2`] = `
|
||||
"const nxPreset = require('@nx/jest/preset').default;
|
||||
|
||||
module.exports = { ...nxPreset }"
|
||||
module.exports = { ...nxPreset };"
|
||||
`;
|
||||
|
||||
exports[`createJestConfig should generate files with --js flag 1`] = `
|
||||
@ -25,5 +25,5 @@ projects: await getJestProjectsAsync()
|
||||
exports[`createJestConfig should generate files with --js flag 2`] = `
|
||||
"const nxPreset = require('@nx/jest/preset').default;
|
||||
|
||||
module.exports = { ...nxPreset }"
|
||||
module.exports = { ...nxPreset };"
|
||||
`;
|
||||
|
||||
@ -5,12 +5,13 @@ import {
|
||||
Tree,
|
||||
} from '@nx/devkit';
|
||||
import { join } from 'path';
|
||||
import type { JestPresetExtension } from '../../../utils/config/config-file';
|
||||
import { NormalizedJestProjectSchema } from '../schema';
|
||||
|
||||
export function createFiles(
|
||||
tree: Tree,
|
||||
options: NormalizedJestProjectSchema,
|
||||
presetExt: 'cjs' | 'js'
|
||||
presetExt: JestPresetExtension
|
||||
) {
|
||||
const projectConfig = readProjectConfiguration(tree, options.project);
|
||||
|
||||
|
||||
@ -8,23 +8,34 @@ import {
|
||||
type Tree,
|
||||
} from '@nx/devkit';
|
||||
import { readTargetDefaultsForTarget } from 'nx/src/project-graph/utils/project-configuration-utils';
|
||||
import { findRootJestConfig } from '../../../utils/config/find-root-jest-files';
|
||||
import {
|
||||
findRootJestConfig,
|
||||
type JestPresetExtension,
|
||||
} from '../../../utils/config/config-file';
|
||||
import type { NormalizedJestProjectSchema } from '../schema';
|
||||
|
||||
export async function createJestConfig(
|
||||
tree: Tree,
|
||||
options: Partial<NormalizedJestProjectSchema>,
|
||||
presetExt: 'cjs' | 'js'
|
||||
presetExt: JestPresetExtension
|
||||
) {
|
||||
if (!tree.exists(`jest.preset.${presetExt}`)) {
|
||||
// preset is always js file.
|
||||
if (presetExt === 'mjs') {
|
||||
tree.write(
|
||||
`jest.preset.${presetExt}`,
|
||||
`
|
||||
const nxPreset = require('@nx/jest/preset').default;
|
||||
`import { nxPreset } from '@nx/jest/preset.js';
|
||||
|
||||
module.exports = { ...nxPreset }`
|
||||
export default { ...nxPreset };`
|
||||
);
|
||||
} else {
|
||||
// js or cjs
|
||||
tree.write(
|
||||
`jest.preset.${presetExt}`,
|
||||
`const nxPreset = require('@nx/jest/preset').default;
|
||||
|
||||
module.exports = { ...nxPreset };`
|
||||
);
|
||||
}
|
||||
}
|
||||
if (options.rootProject) {
|
||||
// we don't want any config to be made because the `configurationGenerator` will do it.
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import { findRootJestConfig } from '../../../utils/config/find-root-jest-files';
|
||||
import { NormalizedJestProjectSchema } from '../schema';
|
||||
import { readProjectConfiguration, type Tree } from '@nx/devkit';
|
||||
import { findRootJestConfig } from '../../../utils/config/config-file';
|
||||
import { addPropertyToJestConfig } from '../../../utils/config/update-config';
|
||||
import { readProjectConfiguration, Tree } from '@nx/devkit';
|
||||
import type { NormalizedJestProjectSchema } from '../schema';
|
||||
|
||||
function isUsingUtilityFunction(host: Tree) {
|
||||
const rootConfig = findRootJestConfig(host);
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
import {
|
||||
addDependenciesToPackageJson,
|
||||
createProjectGraphAsync,
|
||||
formatFiles,
|
||||
readNxJson,
|
||||
removeDependenciesFromPackageJson,
|
||||
@ -7,15 +8,17 @@ import {
|
||||
updateNxJson,
|
||||
type GeneratorCallback,
|
||||
type Tree,
|
||||
createProjectGraphAsync,
|
||||
} from '@nx/devkit';
|
||||
import { createNodes } from '../../plugins/plugin';
|
||||
import { jestVersion, nxVersion } from '../../utils/versions';
|
||||
import { isPresetCjs } from '../../utils/config/is-preset-cjs';
|
||||
import type { JestInitSchema } from './schema';
|
||||
import { addPlugin } from '@nx/devkit/src/utils/add-plugin';
|
||||
import { createNodes } from '../../plugins/plugin';
|
||||
import {
|
||||
getPresetExt,
|
||||
type JestPresetExtension,
|
||||
} from '../../utils/config/config-file';
|
||||
import { jestVersion, nxVersion } from '../../utils/versions';
|
||||
import type { JestInitSchema } from './schema';
|
||||
|
||||
function updateProductionFileSet(tree: Tree, presetExt: 'cjs' | 'js') {
|
||||
function updateProductionFileSet(tree: Tree) {
|
||||
const nxJson = readNxJson(tree);
|
||||
|
||||
const productionFileSet = nxJson.namedInputs?.production;
|
||||
@ -40,7 +43,7 @@ function updateProductionFileSet(tree: Tree, presetExt: 'cjs' | 'js') {
|
||||
updateNxJson(tree, nxJson);
|
||||
}
|
||||
|
||||
function addJestTargetDefaults(tree: Tree, presetEnv: 'cjs' | 'js') {
|
||||
function addJestTargetDefaults(tree: Tree, presetExt: JestPresetExtension) {
|
||||
const nxJson = readNxJson(tree);
|
||||
|
||||
nxJson.targetDefaults ??= {};
|
||||
@ -53,7 +56,7 @@ function addJestTargetDefaults(tree: Tree, presetEnv: 'cjs' | 'js') {
|
||||
nxJson.targetDefaults['@nx/jest:jest'].inputs ??= [
|
||||
'default',
|
||||
productionFileSet ? '^production' : '^default',
|
||||
`{workspaceRoot}/jest.preset.${presetEnv}`,
|
||||
`{workspaceRoot}/jest.preset.${presetExt}`,
|
||||
];
|
||||
|
||||
nxJson.targetDefaults['@nx/jest:jest'].options ??= {
|
||||
@ -96,10 +99,10 @@ export async function jestInitGeneratorInternal(
|
||||
nxJson.useInferencePlugins !== false;
|
||||
options.addPlugin ??= addPluginDefault;
|
||||
|
||||
const presetExt = isPresetCjs(tree) ? 'cjs' : 'js';
|
||||
const presetExt = getPresetExt(tree);
|
||||
|
||||
if (!tree.exists('jest.preset.js') && !tree.exists('jest.preset.cjs')) {
|
||||
updateProductionFileSet(tree, presetExt);
|
||||
if (!tree.exists(`jest.preset.${presetExt}`)) {
|
||||
updateProductionFileSet(tree);
|
||||
if (options.addPlugin) {
|
||||
await addPlugin(
|
||||
tree,
|
||||
|
||||
49
packages/jest/src/utils/config/config-file.ts
Normal file
49
packages/jest/src/utils/config/config-file.ts
Normal file
@ -0,0 +1,49 @@
|
||||
import { readJson, type Tree } from '@nx/devkit';
|
||||
|
||||
export const jestConfigExtensions = [
|
||||
'js',
|
||||
'ts',
|
||||
'mjs',
|
||||
'cjs',
|
||||
'mts',
|
||||
'cts',
|
||||
] as const;
|
||||
export type JestConfigExtension = typeof jestConfigExtensions[number];
|
||||
|
||||
export const jestPresetExtensions = ['js', 'cjs', 'mjs'] as const;
|
||||
export type JestPresetExtension = typeof jestPresetExtensions[number];
|
||||
|
||||
export function getPresetExt(tree: Tree): JestPresetExtension {
|
||||
const ext = jestPresetExtensions.find((ext) =>
|
||||
tree.exists(`jest.preset.${ext}`)
|
||||
);
|
||||
|
||||
if (ext) {
|
||||
return ext;
|
||||
}
|
||||
|
||||
const rootPkgJson = readJson(tree, 'package.json');
|
||||
if (rootPkgJson.type && rootPkgJson.type === 'module') {
|
||||
// use cjs if package.json type is module
|
||||
return 'cjs';
|
||||
}
|
||||
|
||||
// default to js
|
||||
return 'js';
|
||||
}
|
||||
|
||||
export function findRootJestConfig(tree: Tree): string | null {
|
||||
const ext = jestConfigExtensions.find((ext) =>
|
||||
tree.exists(`jest.config.${ext}`)
|
||||
);
|
||||
|
||||
return ext ? `jest.config.${ext}` : null;
|
||||
}
|
||||
|
||||
export function findRootJestPreset(tree: Tree): string | null {
|
||||
const ext = jestPresetExtensions.find((ext) =>
|
||||
tree.exists(`jest.preset.${ext}`)
|
||||
);
|
||||
|
||||
return ext ? `jest.preset.${ext}` : null;
|
||||
}
|
||||
@ -1,25 +0,0 @@
|
||||
import { Tree } from '@nx/devkit';
|
||||
|
||||
export function findRootJestConfig(tree: Tree): string | null {
|
||||
if (tree.exists('jest.config.js')) {
|
||||
return 'jest.config.js';
|
||||
}
|
||||
|
||||
if (tree.exists('jest.config.ts')) {
|
||||
return 'jest.config.ts';
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
export function findRootJestPreset(tree: Tree): string | null {
|
||||
if (tree.exists('jest.preset.js')) {
|
||||
return 'jest.preset.js';
|
||||
}
|
||||
|
||||
if (tree.exists('jest.preset.cjs')) {
|
||||
return 'jest.preset.cjs';
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
@ -1,14 +0,0 @@
|
||||
import { type Tree, readJson } from '@nx/devkit';
|
||||
|
||||
export function isPresetCjs(tree: Tree) {
|
||||
if (tree.exists('jest.preset.cjs')) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const rootPkgJson = readJson(tree, 'package.json');
|
||||
if (rootPkgJson.type && rootPkgJson.type === 'module') {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
@ -20,7 +20,7 @@ if (swcJestConfig.swcrc === undefined) {
|
||||
|
||||
<% if(js) {%>module.exports =<% } else { %>export default<% } %> {
|
||||
displayName: '<%= project %>',
|
||||
preset: '<%= offsetFromRoot %>jest.preset.js',
|
||||
preset: '<%= offsetFromRoot %><%= jestPreset %>',
|
||||
transform: {
|
||||
'^.+\\.[tj]s$': ['@swc/jest', swcJestConfig],
|
||||
},
|
||||
|
||||
@ -603,10 +603,12 @@ function replaceJestConfig(tree: Tree, options: NormalizedSchema) {
|
||||
if (tree.exists(existingJestConfig)) {
|
||||
tree.delete(existingJestConfig);
|
||||
}
|
||||
const jestPreset = findRootJestPreset(tree) ?? 'jest.presets.js';
|
||||
|
||||
// replace with JS:SWC specific jest config
|
||||
generateFiles(tree, filesDir, options.projectRoot, {
|
||||
ext: options.js ? 'js' : 'ts',
|
||||
jestPreset,
|
||||
js: !!options.js,
|
||||
project: options.name,
|
||||
offsetFromRoot: offsetFromRoot(options.projectRoot),
|
||||
@ -1013,4 +1015,12 @@ function logNxReleaseDocsInfo() {
|
||||
});
|
||||
}
|
||||
|
||||
function findRootJestPreset(tree: Tree): string | null {
|
||||
const ext = ['js', 'cjs', 'mjs'].find((ext) =>
|
||||
tree.exists(`jest.preset.${ext}`)
|
||||
);
|
||||
|
||||
return ext ? `jest.preset.${ext}` : null;
|
||||
}
|
||||
|
||||
export default libraryGenerator;
|
||||
|
||||
@ -28,6 +28,7 @@ import {
|
||||
replaceOverridesInLintConfig,
|
||||
} from '@nx/eslint/src/generators/utils/eslint-file';
|
||||
import { logShowProjectCommand } from '@nx/devkit/src/utils/log-show-project-command';
|
||||
import { findRootJestPreset } from '@nx/jest/src/utils/config/config-file';
|
||||
|
||||
export async function e2eProjectGenerator(host: Tree, options: Schema) {
|
||||
return await e2eProjectGeneratorInternal(host, {
|
||||
@ -90,6 +91,7 @@ export async function e2eProjectGeneratorInternal(
|
||||
});
|
||||
}
|
||||
|
||||
const jestPreset = findRootJestPreset(host) ?? 'jest.preset.js';
|
||||
if (options.projectType === 'server') {
|
||||
generateFiles(
|
||||
host,
|
||||
@ -99,6 +101,7 @@ export async function e2eProjectGeneratorInternal(
|
||||
...options,
|
||||
...names(options.rootProject ? 'server' : options.project),
|
||||
offsetFromRoot: offsetFromRoot(options.e2eProjectRoot),
|
||||
jestPreset,
|
||||
tmpl: '',
|
||||
}
|
||||
);
|
||||
@ -127,6 +130,7 @@ export async function e2eProjectGeneratorInternal(
|
||||
...names(options.rootProject ? 'cli' : options.project),
|
||||
mainFile,
|
||||
offsetFromRoot: offsetFromRoot(options.e2eProjectRoot),
|
||||
jestPreset,
|
||||
tmpl: '',
|
||||
}
|
||||
);
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/* eslint-disable */
|
||||
export default {
|
||||
displayName: '<%= e2eProjectName %>',
|
||||
preset: '<%= offsetFromRoot %>/jest.preset.js',
|
||||
preset: '<%= offsetFromRoot %><%= jestPreset %>',
|
||||
setupFiles: ['<rootDir>/src/test-setup.ts'],
|
||||
testEnvironment: 'node',
|
||||
transform: {
|
||||
@ -10,5 +10,5 @@ export default {
|
||||
}],
|
||||
},
|
||||
moduleFileExtensions: ['ts', 'js', 'html'],
|
||||
coverageDirectory: '<%= offsetFromRoot %>/coverage/<%= e2eProjectName %>',
|
||||
coverageDirectory: '<%= offsetFromRoot %>coverage/<%= e2eProjectName %>',
|
||||
};
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/* eslint-disable */
|
||||
export default {
|
||||
displayName: '<%= e2eProjectName %>',
|
||||
preset: '<%= offsetFromRoot %>jest.preset.js',
|
||||
preset: '<%= offsetFromRoot %><%= jestPreset %>',
|
||||
globalSetup: '<rootDir>/src/support/global-setup.ts',
|
||||
globalTeardown: '<rootDir>/src/support/global-teardown.ts',
|
||||
setupFiles: ['<rootDir>/src/support/test-setup.ts'],
|
||||
|
||||
@ -284,7 +284,7 @@ export async function remixApplicationGeneratorInternal(
|
||||
if (options.unitTestRunner === 'jest') {
|
||||
tree.write(
|
||||
'jest.preset.js',
|
||||
`import { nxPreset } from '@nx/jest/preset/jest-preset.js';
|
||||
`import { nxPreset } from '@nx/jest/preset.js';
|
||||
export default {...nxPreset};
|
||||
`
|
||||
);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user