Skip to content

fix(testing): convert executor-based jest.config.ts and preserve type-only imports#35286

Merged
FrozenPandaz merged 1 commit intomasterfrom
gh-34593
Apr 27, 2026
Merged

fix(testing): convert executor-based jest.config.ts and preserve type-only imports#35286
FrozenPandaz merged 1 commit intomasterfrom
gh-34593

Conversation

@leosvelperez
Copy link
Copy Markdown
Member

Current Behavior

nx migrate --run-migrations crashes on workspaces that use the @nx/jest:jest executor (via targetDefaults) instead of @nx/jest/plugin:

NX   Failed to run replace-removed-matcher-aliases-v22-3 from @nx/jest. This workspace is NOT up to date!

NX   Jest: Failed to parse the TypeScript config file .../libs/.../jest.config.ts

  ReferenceError: __dirname is not defined in ES module scope

The convert-jest-config-to-cjs migration (update-22-2-0) is gated on @nx/jest/plugin being registered in nx.json, so executor-based workspaces skip it entirely. Their jest.config.ts files (often a mix of ESM syntax and CJS globals like __dirname) never get converted. The later replace-removed-matcher-aliases-v22-3 migration then calls jest-config.readConfig on every jest.config.ts, which on Node 22+/24+ with native type-stripping reparses the file as ESM and crashes.

Separately, the conversion logic also didn't handle import type declarations — it rewrote them to const { X } = require('mod'), which unnecessarily pulls the module at runtime and drops type references the IDE/tsc relied on. For types-only specifiers, it could even crash at runtime.

Expected Behavior

convert-jest-config-to-cjs runs for every jest.config.ts whose project is CommonJS (plugin registration is no longer required), so executor-based setups are covered. The type: module guard still skips ESM projects.

Type-only imports are preserved:

  • import type { Config } from 'jest' — left untouched (Node's type-stripping erases it, so it doesn't force ESM parsing at runtime).
  • import { type Foo, bar } from 'mod' — split into import type { Foo } from 'mod' plus const { bar } = require('mod').
  • Renames (import { type Foo as JestFoo, run } from 'mod') preserved.

Related Issue(s)

Fixes #34593

…-only imports

Runs convert-jest-config-to-cjs for every jest.config.ts with a CJS-compatible package.json type, not just plugin-registered ones, so executor-based workspaces stop crashing on native type-stripping loaders (readConfig). Keeps `import type` declarations and splits inline `type` specifiers into a type-only import plus a require so editor/tsc type safety is retained.
@leosvelperez leosvelperez requested a review from a team as a code owner April 14, 2026 11:08
@leosvelperez leosvelperez requested a review from JamesHenry April 14, 2026 11:08
@netlify
Copy link
Copy Markdown

netlify Bot commented Apr 14, 2026

Deploy Preview for nx-dev ready!

Name Link
🔨 Latest commit 599bbb4
🔍 Latest deploy log https://app.netlify.com/projects/nx-dev/deploys/69de20285d18390008a0029f
😎 Deploy Preview https://deploy-preview-35286--nx-dev.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@netlify
Copy link
Copy Markdown

netlify Bot commented Apr 14, 2026

Deploy Preview for nx-docs ready!

Name Link
🔨 Latest commit 599bbb4
🔍 Latest deploy log https://app.netlify.com/projects/nx-docs/deploys/69de2028f8d84200082a7cb9
😎 Deploy Preview https://deploy-preview-35286--nx-docs.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@nx-cloud
Copy link
Copy Markdown
Contributor

nx-cloud Bot commented Apr 14, 2026

View your CI Pipeline Execution ↗ for commit 599bbb4

Command Status Duration Result
nx affected --targets=lint,test,build,e2e,e2e-c... ✅ Succeeded 54m 16s View ↗
nx run-many -t check-imports check-lock-files c... ✅ Succeeded 5s View ↗
nx-cloud record -- pnpm nx conformance:check ✅ Succeeded 7s View ↗
nx build workspace-plugin ✅ Succeeded <1s View ↗
nx-cloud record -- nx format:check ✅ Succeeded 2s View ↗
nx-cloud record -- nx sync:check ✅ Succeeded <1s View ↗

☁️ Nx Cloud last updated this comment at 2026-04-14 12:06:37 UTC

@leosvelperez leosvelperez self-assigned this Apr 14, 2026
@FrozenPandaz FrozenPandaz merged commit b1ba26c into master Apr 27, 2026
23 checks passed
@FrozenPandaz FrozenPandaz deleted the gh-34593 branch April 27, 2026 04:53
ShwethaSundar pushed a commit to ShwethaSundar/nx that referenced this pull request Apr 27, 2026
…-only imports (nrwl#35286)

## Current Behavior

`nx migrate --run-migrations` crashes on workspaces that use the
`@nx/jest:jest` executor (via `targetDefaults`) instead of
`@nx/jest/plugin`:

```
NX   Failed to run replace-removed-matcher-aliases-v22-3 from @nx/jest. This workspace is NOT up to date!

NX   Jest: Failed to parse the TypeScript config file .../libs/.../jest.config.ts

  ReferenceError: __dirname is not defined in ES module scope
```

The `convert-jest-config-to-cjs` migration (update-22-2-0) is gated on
`@nx/jest/plugin` being registered in `nx.json`, so executor-based
workspaces skip it entirely. Their `jest.config.ts` files (often a mix
of ESM syntax and CJS globals like `__dirname`) never get converted. The
later `replace-removed-matcher-aliases-v22-3` migration then calls
`jest-config.readConfig` on every `jest.config.ts`, which on Node
22+/24+ with native type-stripping reparses the file as ESM and crashes.

Separately, the conversion logic also didn't handle `import type`
declarations — it rewrote them to `const { X } = require('mod')`, which
unnecessarily pulls the module at runtime and drops type references the
IDE/tsc relied on. For types-only specifiers, it could even crash at
runtime.

## Expected Behavior

`convert-jest-config-to-cjs` runs for every `jest.config.ts` whose
project is CommonJS (plugin registration is no longer required), so
executor-based setups are covered. The `type: module` guard still skips
ESM projects.

Type-only imports are preserved:

- `import type { Config } from 'jest'` — left untouched (Node's
type-stripping erases it, so it doesn't force ESM parsing at runtime).
- `import { type Foo, bar } from 'mod'` — split into `import type { Foo
} from 'mod'` plus `const { bar } = require('mod')`.
- Renames (`import { type Foo as JestFoo, run } from 'mod'`) preserved.

## Related Issue(s)

Fixes nrwl#34593
FrozenPandaz pushed a commit that referenced this pull request Apr 28, 2026
…-only imports (#35286)

## Current Behavior

`nx migrate --run-migrations` crashes on workspaces that use the
`@nx/jest:jest` executor (via `targetDefaults`) instead of
`@nx/jest/plugin`:

```
NX   Failed to run replace-removed-matcher-aliases-v22-3 from @nx/jest. This workspace is NOT up to date!

NX   Jest: Failed to parse the TypeScript config file .../libs/.../jest.config.ts

  ReferenceError: __dirname is not defined in ES module scope
```

The `convert-jest-config-to-cjs` migration (update-22-2-0) is gated on
`@nx/jest/plugin` being registered in `nx.json`, so executor-based
workspaces skip it entirely. Their `jest.config.ts` files (often a mix
of ESM syntax and CJS globals like `__dirname`) never get converted. The
later `replace-removed-matcher-aliases-v22-3` migration then calls
`jest-config.readConfig` on every `jest.config.ts`, which on Node
22+/24+ with native type-stripping reparses the file as ESM and crashes.

Separately, the conversion logic also didn't handle `import type`
declarations — it rewrote them to `const { X } = require('mod')`, which
unnecessarily pulls the module at runtime and drops type references the
IDE/tsc relied on. For types-only specifiers, it could even crash at
runtime.

## Expected Behavior

`convert-jest-config-to-cjs` runs for every `jest.config.ts` whose
project is CommonJS (plugin registration is no longer required), so
executor-based setups are covered. The `type: module` guard still skips
ESM projects.

Type-only imports are preserved:

- `import type { Config } from 'jest'` — left untouched (Node's
type-stripping erases it, so it doesn't force ESM parsing at runtime).
- `import { type Foo, bar } from 'mod'` — split into `import type { Foo
} from 'mod'` plus `const { bar } = require('mod')`.
- Renames (`import { type Foo as JestFoo, run } from 'mod'`) preserved.

## Related Issue(s)

Fixes #34593
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 3, 2026

This pull request has already been merged/closed. If you experience issues related to these changes, please open a new issue referencing this pull request.

@github-actions github-actions Bot locked as resolved and limited conversation to collaborators May 3, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fix(jest): replace-removed-matcher-aliases migration crashes when convert-jest-config-to-cjs skips non-plugin workspaces

2 participants