diff --git a/packages/jest/src/generators/configuration/configuration.spec.ts b/packages/jest/src/generators/configuration/configuration.spec.ts index 4e894ac4f8c80..42e89d53c4255 100644 --- a/packages/jest/src/generators/configuration/configuration.spec.ts +++ b/packages/jest/src/generators/configuration/configuration.spec.ts @@ -5,6 +5,7 @@ import { Tree, updateProjectConfiguration, writeJson, + updateJson, } from '@nx/devkit'; import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing'; import { jestConfigObject } from '../../utils/config/functions'; @@ -386,4 +387,62 @@ describe('jestProject', () => { `); }); }); + + describe(`jest.preset.cjs`, () => { + it(`root jest.preset.cjs existing should force subsequent configs to point to it correctly`, async () => { + // ARRANGE + tree.write( + `jest.preset.cjs`, + ` + const nxPreset = require('@nx/jest/preset').default; + + module.exports = { ...nxPreset }` + ); + + // ACT + await configurationGenerator(tree, { + ...defaultOptions, + project: 'lib1', + } as JestProjectSchema); + + // ASSERT + expect(tree.read('libs/lib1/jest.config.ts', 'utf-8')) + .toMatchInlineSnapshot(` + "/* eslint-disable */ + export default { + displayName: 'lib1', + preset: '../../jest.preset.cjs', + coverageDirectory: '../../coverage/libs/lib1', + }; + " + `); + }); + + it(`root package.json type=module should create jest.preset.cjs and force subsequent configs to point to it correctly`, async () => { + // ARRANGE + updateJson(tree, 'package.json', (pkgJson) => { + pkgJson.type = 'module'; + return pkgJson; + }); + + // ACT + await configurationGenerator(tree, { + ...defaultOptions, + project: 'lib1', + } as JestProjectSchema); + + // ASSERT + expect(tree.exists('jest.preset.cjs')).toBeTruthy(); + expect(tree.read('libs/lib1/jest.config.ts', 'utf-8')) + .toMatchInlineSnapshot(` + "/* eslint-disable */ + export default { + displayName: 'lib1', + preset: '../../jest.preset.cjs', + coverageDirectory: '../../coverage/libs/lib1', + }; + " + `); + }); + }); }); diff --git a/packages/jest/src/generators/configuration/configuration.ts b/packages/jest/src/generators/configuration/configuration.ts index 48fe321e4a12f..a786f6f9ed9ba 100644 --- a/packages/jest/src/generators/configuration/configuration.ts +++ b/packages/jest/src/generators/configuration/configuration.ts @@ -17,6 +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'; const schemaDefaults = { setupFile: 'none', @@ -84,9 +85,11 @@ export async function configurationGeneratorInternal( tasks.push(ensureDependencies(tree, options)); } - await createJestConfig(tree, options); + const presetExt = isPresetCjs(tree) ? 'cjs' : 'js'; + + await createJestConfig(tree, options, presetExt); checkForTestTarget(tree, options); - createFiles(tree, options); + createFiles(tree, options, presetExt); updateTsConfig(tree, options); updateVsCodeRecommendedExtensions(tree); diff --git a/packages/jest/src/generators/configuration/files-angular/jest.config.ts__tmpl__ b/packages/jest/src/generators/configuration/files-angular/jest.config.ts__tmpl__ index 1db519aa49ac3..f3945726987bf 100644 --- a/packages/jest/src/generators/configuration/files-angular/jest.config.ts__tmpl__ +++ b/packages/jest/src/generators/configuration/files-angular/jest.config.ts__tmpl__ @@ -1,7 +1,7 @@ /* eslint-disable */ <% if(js){ %>module.exports =<% } else{ %>export default<% } %> { displayName: '<%= project %>', - preset: '<%= offsetFromRoot %>jest.preset.js', + preset: '<%= offsetFromRoot %>jest.preset.<%= presetExt %>', setupFilesAfterEnv: ['/src/test-setup.ts'],<% if(testEnvironment) { %> testEnvironment: '<%= testEnvironment %>',<% } %> coverageDirectory: '<%= offsetFromRoot %>coverage/<%= projectRoot %>', diff --git a/packages/jest/src/generators/configuration/files/jest.config.ts__tmpl__ b/packages/jest/src/generators/configuration/files/jest.config.ts__tmpl__ index bf46ea8d95518..af8daaf4cd3f2 100644 --- a/packages/jest/src/generators/configuration/files/jest.config.ts__tmpl__ +++ b/packages/jest/src/generators/configuration/files/jest.config.ts__tmpl__ @@ -1,7 +1,7 @@ /* eslint-disable */ <% if(js){ %>module.exports =<% } else{ %>export default<% } %> { displayName: '<%= project %>', - preset: '<%= offsetFromRoot %>jest.preset.js',<% if(setupFile !== 'none') { %> + preset: '<%= offsetFromRoot %>jest.preset.<%= presetExt %>',<% if(setupFile !== 'none') { %> setupFilesAfterEnv: ['/src/test-setup.ts'],<% } %><% if(testEnvironment) { %> testEnvironment: '<%= testEnvironment %>',<% } %><% if(skipSerializers){ %> transform: { diff --git a/packages/jest/src/generators/configuration/lib/create-files.ts b/packages/jest/src/generators/configuration/lib/create-files.ts index e9d4a03b3dadb..1a9a0b07aa1ab 100644 --- a/packages/jest/src/generators/configuration/lib/create-files.ts +++ b/packages/jest/src/generators/configuration/lib/create-files.ts @@ -7,7 +7,11 @@ import { import { join } from 'path'; import { NormalizedJestProjectSchema } from '../schema'; -export function createFiles(tree: Tree, options: NormalizedJestProjectSchema) { +export function createFiles( + tree: Tree, + options: NormalizedJestProjectSchema, + presetExt: 'cjs' | 'js' +) { const projectConfig = readProjectConfiguration(tree, options.project); const filesFolder = @@ -42,6 +46,7 @@ export function createFiles(tree: Tree, options: NormalizedJestProjectSchema) { rootProject: options.rootProject, projectRoot: options.rootProject ? options.project : projectConfig.root, offsetFromRoot: offsetFromRoot(projectConfig.root), + presetExt, }); if (options.setupFile === 'none') { diff --git a/packages/jest/src/generators/configuration/lib/create-jest-config.spec.ts b/packages/jest/src/generators/configuration/lib/create-jest-config.spec.ts index c52f6481024d3..3646ecdc9933a 100644 --- a/packages/jest/src/generators/configuration/lib/create-jest-config.spec.ts +++ b/packages/jest/src/generators/configuration/lib/create-jest-config.spec.ts @@ -46,7 +46,7 @@ describe('createJestConfig', () => { }); it('should generate files with --js flag', async () => { - await createJestConfig(tree, { js: true }); + await createJestConfig(tree, { js: true }, 'js'); expect(tree.exists('jest.config.js')).toBeTruthy(); expect( @@ -58,7 +58,7 @@ describe('createJestConfig', () => { }); it('should generate files ', async () => { - await createJestConfig(tree, {}); + await createJestConfig(tree, {}, 'js'); expect(tree.exists('jest.config.ts')).toBeTruthy(); expect( @@ -92,13 +92,13 @@ export default { `; tree.write('jest.config.ts', expected); - await createJestConfig(tree, {}); + await createJestConfig(tree, {}, 'js'); expect(tree.read('jest.config.ts', 'utf-8')).toEqual(expected); }); it('should make js jest files', async () => { - await createJestConfig(tree, { js: true }); + await createJestConfig(tree, { js: true }, 'js'); expect(tree.exists('jest.config.js')).toBeTruthy(); expect(tree.exists('jest.preset.js')).toBeTruthy(); @@ -106,7 +106,7 @@ export default { describe('root project', () => { it('should not add a monorepo jest.config.ts to the project', async () => { - await createJestConfig(tree, { rootProject: true }); + await createJestConfig(tree, { rootProject: true }, 'js'); expect(tree.exists('jest.config.ts')).toBeFalsy(); }); @@ -143,7 +143,7 @@ export default { ` ); - await createJestConfig(tree, { rootProject: false }); + await createJestConfig(tree, { rootProject: false }, 'js'); expect(tree.exists('jest.config.app.ts')).toBeTruthy(); expect(tree.read('jest.config.app.ts', 'utf-8')).toMatchInlineSnapshot(` @@ -210,7 +210,7 @@ module.exports = { ` ); - await createJestConfig(tree, { js: true, rootProject: false }); + await createJestConfig(tree, { js: true, rootProject: false }, 'js'); expect(tree.exists('jest.config.app.js')).toBeTruthy(); expect(tree.read('jest.config.js', 'utf-8')) diff --git a/packages/jest/src/generators/configuration/lib/create-jest-config.ts b/packages/jest/src/generators/configuration/lib/create-jest-config.ts index 0e2dc961bc298..fb19843f52f35 100644 --- a/packages/jest/src/generators/configuration/lib/create-jest-config.ts +++ b/packages/jest/src/generators/configuration/lib/create-jest-config.ts @@ -13,12 +13,13 @@ import type { NormalizedJestProjectSchema } from '../schema'; export async function createJestConfig( tree: Tree, - options: Partial + options: Partial, + presetExt: 'cjs' | 'js' ) { - if (!tree.exists('jest.preset.js')) { + if (!tree.exists(`jest.preset.${presetExt}`)) { // preset is always js file. tree.write( - `jest.preset.js`, + `jest.preset.${presetExt}`, ` const nxPreset = require('@nx/jest/preset').default; diff --git a/packages/jest/src/generators/init/init.ts b/packages/jest/src/generators/init/init.ts index 740155750a86e..48d77f8e8fa5d 100644 --- a/packages/jest/src/generators/init/init.ts +++ b/packages/jest/src/generators/init/init.ts @@ -11,6 +11,7 @@ import { import { updatePackageScripts } from '@nx/devkit/src/utils/update-package-scripts'; import { createNodes } from '../../plugins/plugin'; import { jestVersion, nxVersion } from '../../utils/versions'; +import { isPresetCjs } from '../../utils/config/is-preset-cjs'; import type { JestInitSchema } from './schema'; function addPlugin(tree: Tree) { @@ -34,7 +35,7 @@ function addPlugin(tree: Tree) { updateNxJson(tree, nxJson); } -function updateProductionFileSet(tree: Tree) { +function updateProductionFileSet(tree: Tree, presetExt: 'cjs' | 'js') { const nxJson = readNxJson(tree); const productionFileSet = nxJson.namedInputs?.production; @@ -59,7 +60,7 @@ function updateProductionFileSet(tree: Tree) { updateNxJson(tree, nxJson); } -function addJestTargetDefaults(tree: Tree) { +function addJestTargetDefaults(tree: Tree, presetEnv: 'cjs' | 'js') { const nxJson = readNxJson(tree); nxJson.targetDefaults ??= {}; @@ -72,7 +73,7 @@ function addJestTargetDefaults(tree: Tree) { nxJson.targetDefaults['@nx/jest:jest'].inputs ??= [ 'default', productionFileSet ? '^production' : '^default', - '{workspaceRoot}/jest.preset.js', + `{workspaceRoot}/jest.preset.${presetEnv}`, ]; nxJson.targetDefaults['@nx/jest:jest'].options ??= { @@ -111,12 +112,14 @@ export async function jestInitGeneratorInternal( ): Promise { options.addPlugin ??= process.env.NX_ADD_PLUGINS !== 'false'; - if (!tree.exists('jest.preset.js')) { - updateProductionFileSet(tree); + const presetExt = isPresetCjs(tree) ? 'cjs' : 'js'; + + if (!tree.exists('jest.preset.js') && !tree.exists('jest.preset.cjs')) { + updateProductionFileSet(tree, presetExt); if (options.addPlugin) { addPlugin(tree); } else { - addJestTargetDefaults(tree); + addJestTargetDefaults(tree, presetExt); } } diff --git a/packages/jest/src/utils/config/find-root-jest-files.ts b/packages/jest/src/utils/config/find-root-jest-files.ts index 72a97a18e0d86..5b88608451982 100644 --- a/packages/jest/src/utils/config/find-root-jest-files.ts +++ b/packages/jest/src/utils/config/find-root-jest-files.ts @@ -17,5 +17,9 @@ export function findRootJestPreset(tree: Tree): string | null { return 'jest.preset.js'; } + if (tree.exists('jest.preset.cjs')) { + return 'jest.preset.cjs'; + } + return null; } diff --git a/packages/jest/src/utils/config/is-preset-cjs.ts b/packages/jest/src/utils/config/is-preset-cjs.ts new file mode 100644 index 0000000000000..c1ba4752bf1e2 --- /dev/null +++ b/packages/jest/src/utils/config/is-preset-cjs.ts @@ -0,0 +1,14 @@ +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; +}