Skip to content

feat: node_modules preset config#5302

Draft
Noyabronok wants to merge 2 commits into
kulshekhar:mainfrom
Noyabronok:feat/node-modules-mjs
Draft

feat: node_modules preset config#5302
Noyabronok wants to merge 2 commits into
kulshekhar:mainfrom
Noyabronok:feat/node-modules-mjs

Conversation

@Noyabronok

@Noyabronok Noyabronok commented May 9, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds a nodeModulesTransformOptions second parameter to the CJS preset functions (createDefaultPreset, createDefaultLegacyPreset, createJsWithTsPreset, createJsWithTsLegacyPreset). When provided, the preset automatically sets transformIgnorePatterns to allow the specified packages to be transpiled.

New options:

  • packageNames — packages that should not be ignored by Jest's transform (e.g. ESM-only packages)
  • mjsPackages — when true, also adds a transform entry and pattern for .mjs files in node_modules

Example:

const presetConfig = createDefaultPreset(
  {},
  {
    packageNames: ['some-package'],
    mjsPackages: true,
  },
)

The resulting config will include:

  • transformIgnorePatterns: ['/node_modules/(?!(some-esm-package/|.*\\.mjs$))']
  • An additional transform entry for node_modules/.+\.mjs$

Summary by CodeRabbit

  • New Features

    • Presets gain configurable ESM handling for .mjs packages in node_modules and allow specifying package names to transform.
  • Type Updates

    • Preset types extended to expose the new node-modules transform options in configs.
  • Deprecations

    • Removed the deprecated preset entry point; migrate to the updated preset factories.
  • Tests

    • Added snapshot coverage for the new preset option combinations.

Review Change Stack

@coderabbitai

coderabbitai Bot commented May 9, 2026

Copy link
Copy Markdown
📝 Walkthrough

Walkthrough

This PR adds configurable transformation support for .mjs files in node_modules. It introduces new types and a utility to build transform-ignore regexes, refactors preset factories to accept node-modules transform options, extends preset types, re-exports the utility, and makes transpilation ESM-aware.

Changes

MJS Node Modules Transform Support

Layer / File(s) Summary
Data Contracts
src/constants.ts, src/types.ts
Introduces MJS_NODE_MODULES_TRANSFORM_PATTERN constant and NodeModulesTransformOptions type to define configuration shape for .mjs transformation.
Transform Pattern Utility
src/utils/node-modules-transform-pattern.ts, src/utils/index.ts
Implements nodeModulesTransformPattern() utility to build a /node_modules/(?!...) negative-lookahead regex from packageNames and optional mjsPackages; adds escapeRegex helper and re-exports from utils.
Preset Factory Refactoring
src/presets/create-jest-preset.ts
Adds withNodeModulesTransform() helper that injects transformIgnorePatterns and optional MJS transform entries; refactors four preset factories to accept nodeModulesTransformOptions and removes deprecated createJestPreset().
ESM Transpilation Handling
src/legacy/ts-jest-transformer.ts
Adjusts node_modules JS transpilation to compute useESM from supportsStaticESM and transformerConfig.useESM, set ts.ModuleKind accordingly, and rewrite .mjs.js filename when not using ESM for ts.transpileModule.
Test Coverage
src/presets/create-jest-preset.spec.ts
Adds snapshot tests for preset factories covering mjsPackages, packageNames, and combined options across default and legacy presets.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Suggested reviewers

  • kulshekhar

🐰 The preset now knows to dance with .mjs files,
Transformation patterns hop through node_modules with style,
ESM compiler options prance along with care,
Four preset factories now share the helper's grace,
Snapshot tests tuck the changes safe and square.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 12.50% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title 'feat: node_modules preset config' is partially related to the changeset. It refers to a real aspect of the change (node_modules and preset configuration), but is vague and overly broad for the specific main change, which is adding support for MJS packages and configurable transforms in presets.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@Noyabronok Noyabronok marked this pull request as ready for review May 9, 2026 20:15
@Noyabronok Noyabronok requested a review from kulshekhar as a code owner May 9, 2026 20:15

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/presets/create-jest-preset.spec.ts (1)

101-108: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Baseline “legacy preset” test is invoking the non-legacy factory.

Inside describe('createDefaultLegacyPreset'), the first test currently snapshots createDefaultPreset(...), so it does not validate the intended baseline.

Suggested fix
     describe('createDefaultLegacyPreset', () => {
       it('should return preset config', () => {
         expect(
-          createDefaultPreset({
+          createDefaultLegacyPreset({
             tsconfig: 'tsconfig.spec.json',
           }),
         ).toMatchSnapshot()
       })
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/presets/create-jest-preset.spec.ts` around lines 101 - 108, The test
under describe('createDefaultLegacyPreset') is calling createDefaultPreset
instead of the legacy factory; update the test to invoke
createDefaultLegacyPreset with the same argument shape (e.g., { tsconfig:
'tsconfig.spec.json' }) so the snapshot covers the legacy preset path; ensure
the expect(...) wraps createDefaultLegacyPreset(...) and leave the rest of the
assertion (toMatchSnapshot) unchanged.
🧹 Nitpick comments (1)
src/presets/create-jest-preset.spec.ts (1)

110-112: ⚡ Quick win

Add packageNames coverage for the other updated CJS preset factories.

This PR adds the second parameter to multiple CJS creators, but only createDefaultPreset is snapshot-tested with packageNames. Adding the same case(s) for createDefaultLegacyPreset, createJsWithTsPreset, and createJsWithTsLegacyPreset would close a regression gap.

Also applies to: 125-129, 142-146

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/presets/create-jest-preset.spec.ts` around lines 110 - 112, Add snapshot
tests that pass the new second-argument option { packageNames: true } to the
other CJS preset factories so they get the same coverage as createDefaultPreset;
specifically add test cases calling createDefaultLegacyPreset(..., {
packageNames: true }), createJsWithTsPreset(..., { packageNames: true }), and
createJsWithTsLegacyPreset(..., { packageNames: true }) (mirroring the existing
test pattern used for createDefaultPreset) and assert they toMatchSnapshot().
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/utils/node-modules-transform-pattern.ts`:
- Around line 21-23: The code currently interpolates raw packageNames into a
regex via packageNames.join('|') (used in the exclusions.push calls), which
allows regex metacharacters in package names to change the pattern; fix by
escaping regex metacharacters in each package name before joining (e.g., replace
'.' and other metacharacters via an escapeRegExp helper and use
packageNames.map(escapeRegExp).join('|')) for both places where exclusions.push
builds `(${...})/` so the generated regex matches literal package names only.

---

Outside diff comments:
In `@src/presets/create-jest-preset.spec.ts`:
- Around line 101-108: The test under describe('createDefaultLegacyPreset') is
calling createDefaultPreset instead of the legacy factory; update the test to
invoke createDefaultLegacyPreset with the same argument shape (e.g., { tsconfig:
'tsconfig.spec.json' }) so the snapshot covers the legacy preset path; ensure
the expect(...) wraps createDefaultLegacyPreset(...) and leave the rest of the
assertion (toMatchSnapshot) unchanged.

---

Nitpick comments:
In `@src/presets/create-jest-preset.spec.ts`:
- Around line 110-112: Add snapshot tests that pass the new second-argument
option { packageNames: true } to the other CJS preset factories so they get the
same coverage as createDefaultPreset; specifically add test cases calling
createDefaultLegacyPreset(..., { packageNames: true }),
createJsWithTsPreset(..., { packageNames: true }), and
createJsWithTsLegacyPreset(..., { packageNames: true }) (mirroring the existing
test pattern used for createDefaultPreset) and assert they toMatchSnapshot().
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 55f1b524-2bb1-4518-9400-910889eba11a

📥 Commits

Reviewing files that changed from the base of the PR and between 1155e39 and 8c95667.

⛔ Files ignored due to path filters (1)
  • src/presets/__snapshots__/create-jest-preset.spec.ts.snap is excluded by !**/*.snap
📒 Files selected for processing (7)
  • src/constants.ts
  • src/legacy/ts-jest-transformer.ts
  • src/presets/create-jest-preset.spec.ts
  • src/presets/create-jest-preset.ts
  • src/types.ts
  • src/utils/index.ts
  • src/utils/node-modules-transform-pattern.ts

Comment thread src/utils/node-modules-transform-pattern.ts
@Noyabronok

Noyabronok commented May 9, 2026

Copy link
Copy Markdown
Contributor Author

@ahnpnl
Here is the 2nd pr with the mjs changes using the new pattern we discussed in #5291

  • As you asked, I've applied this pattern to multiple presets.
  • Unfortunately, we still need a nodeModulesTransformPattern function because multiple ignore patterns for node_modules won't work due to the negative lookahead nature of the regex. I think it's fine though, since all the packages can be specified through this function, like:
const presetConfig = createJsWithTsPreset({}, { mjsPackages: true, packageNames: ['until-async'] })

const config: JestConfigWithTsJest = {
  ...presetConfig,

I would also ask if you like the nodemodules configuration as a 2nd parameter to the preset, or if you think it'd be better to add it as named option to the existing xTransformOptions types, which would make the calls look something like:

createJsWithTsPreset({ nodeModules: { mjsPackages: true, packageNames: ['until-async'] }})

Please let me know if you like this and if there are any other changes you'd like to see. I left out website documentation from the PR for now, will document once we agree on the final approach.

@ahnpnl ahnpnl left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The PR looks pretty clean. Some suggestions:

  • We should have 2 smaller PRs: one to change in ts-jest-transformer.ts and one is changing in preset. Smaller PRs increase the readability and less time to review

  • Each PR should have unit tests, e2e tests and docs updates. This PR only contains unit tests for create-jest-preset.ts but missing unit tests for ts-jest-transformer.ts and node-modules-transform-pattern.ts as well as missing docs updates

Or do you intent to make this PR only change for ts-jest-transformer and let #5291 takes care of preset update?

@Noyabronok

Noyabronok commented May 10, 2026

Copy link
Copy Markdown
Contributor Author

@ahnpnl

We should have 2 smaller PRs: one to change in ts-jest-transformer.ts and one is changing in preset. Smaller PRs increase the readability and less time to review

Created #5304 for transformer-only changes. If you could please review it.

do you intent to make this PR only change for ts-jest-transformer and let #5291 takes care of preset update?

I think what we should do right now is focus on #5304 and #5291 and leave this one in draft to do the preset config until they're both merged. How does that sound?

@Noyabronok Noyabronok changed the title feat: mjs packages support feat: node_modules preset config May 10, 2026
@Noyabronok Noyabronok marked this pull request as draft May 10, 2026 13:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants