224 lines
6.7 KiB
Markdown
224 lines
6.7 KiB
Markdown
|
|
## Jest
|
||
|
|
|
||
|
|
Jest-specific guidance for `nx import`. For the basic "Jest Preset Missing" fix (create `jest.preset.js`, install deps), see `SKILL.md`. This file covers deeper Jest integration issues.
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
### How `@nx/jest` Works
|
||
|
|
|
||
|
|
`@nx/jest/plugin` scans for `jest.config.{ts,js,cjs,mjs,cts,mts}` and creates a `test` target for each project.
|
||
|
|
|
||
|
|
**Plugin options:**
|
||
|
|
|
||
|
|
```json
|
||
|
|
{
|
||
|
|
"plugin": "@nx/jest/plugin",
|
||
|
|
"options": {
|
||
|
|
"targetName": "test"
|
||
|
|
}
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
`npx nx add @nx/jest` does two things:
|
||
|
|
|
||
|
|
1. **Registers `@nx/jest/plugin` in `nx.json`** — without this, no `test` targets are inferred
|
||
|
|
2. Updates `namedInputs.production` to exclude test files
|
||
|
|
|
||
|
|
**Gotcha**: `nx add @nx/jest` does NOT create `jest.preset.js` — that file is only generated when you run a generator (e.g. `@nx/jest:configuration`). For imports, you must create it manually (see "Jest Preset" section below).
|
||
|
|
|
||
|
|
**Other gotcha**: If you create `jest.preset.js` manually but skip `npx nx add @nx/jest`, the plugin won't be registered and `nx run PROJECT:test` will fail with "Cannot find target 'test'". You need both.
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
### Jest Preset
|
||
|
|
|
||
|
|
The preset provides shared Jest configuration (test patterns, ts-jest transform, resolver, jsdom environment).
|
||
|
|
|
||
|
|
**Root `jest.preset.js`:**
|
||
|
|
|
||
|
|
```js
|
||
|
|
const nxPreset = require('@nx/jest/preset').default;
|
||
|
|
module.exports = { ...nxPreset };
|
||
|
|
```
|
||
|
|
|
||
|
|
**Project `jest.config.ts`:**
|
||
|
|
|
||
|
|
```ts
|
||
|
|
export default {
|
||
|
|
displayName: 'my-lib',
|
||
|
|
preset: '../../jest.preset.js',
|
||
|
|
// project-specific overrides
|
||
|
|
};
|
||
|
|
```
|
||
|
|
|
||
|
|
The `preset` path is relative from the project root to the workspace root. Subdirectory imports preserve the original relative path (e.g. `../../jest.preset.js`), which resolves correctly if the import destination matches the source directory depth.
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
### Testing Dependencies
|
||
|
|
|
||
|
|
#### Core (always needed)
|
||
|
|
|
||
|
|
```
|
||
|
|
pnpm add -wD jest ts-jest @types/jest @nx/jest
|
||
|
|
```
|
||
|
|
|
||
|
|
#### Environment-specific
|
||
|
|
|
||
|
|
- **DOM testing** (React, Vue, browser libs): `jest-environment-jsdom`
|
||
|
|
- **Node testing** (APIs, CLIs): no extra deps (Jest defaults to `node` env, but Nx preset defaults to `jsdom`)
|
||
|
|
|
||
|
|
#### React testing
|
||
|
|
|
||
|
|
```
|
||
|
|
pnpm add -wD @testing-library/react @testing-library/jest-dom
|
||
|
|
```
|
||
|
|
|
||
|
|
#### React with Babel (non-ts-jest transform)
|
||
|
|
|
||
|
|
Some React projects use Babel instead of ts-jest for JSX transformation:
|
||
|
|
|
||
|
|
```
|
||
|
|
pnpm add -wD babel-jest @babel/core @babel/preset-env @babel/preset-react @babel/preset-typescript
|
||
|
|
```
|
||
|
|
|
||
|
|
**When**: Project `jest.config` has `transform` using `babel-jest` instead of `ts-jest`. Common in older Nx workspaces and CRA migrations.
|
||
|
|
|
||
|
|
#### Vue testing
|
||
|
|
|
||
|
|
```
|
||
|
|
pnpm add -wD @vue/test-utils
|
||
|
|
```
|
||
|
|
|
||
|
|
Vue projects typically use Vitest (not Jest) — see VITE.md.
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
### `tsconfig.spec.json`
|
||
|
|
|
||
|
|
Jest projects need a `tsconfig.spec.json` that includes test files:
|
||
|
|
|
||
|
|
```json
|
||
|
|
{
|
||
|
|
"extends": "./tsconfig.json",
|
||
|
|
"compilerOptions": {
|
||
|
|
"outDir": "../../dist/out-tsc",
|
||
|
|
"module": "commonjs",
|
||
|
|
"types": ["jest", "node"]
|
||
|
|
},
|
||
|
|
"include": ["jest.config.ts", "src/**/*.test.ts", "src/**/*.spec.ts", "src/**/*.d.ts"]
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
**Common issues after import:**
|
||
|
|
|
||
|
|
- Missing `"types": ["jest", "node"]` — causes `describe`/`it`/`expect` to be unrecognized
|
||
|
|
- Missing `"module": "commonjs"` — Jest doesn't support ESM by default (ts-jest transpiles to CJS)
|
||
|
|
- `include` array missing test patterns — TypeScript won't check test files
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
### Jest vs Vitest Coexistence
|
||
|
|
|
||
|
|
Workspaces can have both:
|
||
|
|
|
||
|
|
- **Jest**: Next.js apps, older React libs, Node libraries
|
||
|
|
- **Vitest**: Vite-based React/Vue apps and libs
|
||
|
|
|
||
|
|
Both `@nx/jest/plugin` and `@nx/vite/plugin` (which infers Vitest targets) coexist without conflicts — they detect different config files (`jest.config.*` vs `vite.config.*`).
|
||
|
|
|
||
|
|
**Target naming**: Both default to `test`. If a project somehow has both config files, rename one:
|
||
|
|
|
||
|
|
```json
|
||
|
|
{
|
||
|
|
"plugin": "@nx/jest/plugin",
|
||
|
|
"options": { "targetName": "jest-test" }
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
### `@testing-library/jest-dom` — Jest vs Vitest
|
||
|
|
|
||
|
|
Projects migrating from Jest to Vitest (or workspaces with both) need different imports:
|
||
|
|
|
||
|
|
**Jest** (in `test-setup.ts`):
|
||
|
|
|
||
|
|
```ts
|
||
|
|
import '@testing-library/jest-dom';
|
||
|
|
```
|
||
|
|
|
||
|
|
**Vitest** (in `test-setup.ts`):
|
||
|
|
|
||
|
|
```ts
|
||
|
|
import '@testing-library/jest-dom/vitest';
|
||
|
|
```
|
||
|
|
|
||
|
|
If the source used Jest but the dest workspace uses Vitest for that project type, update the import path. Also add `@testing-library/jest-dom` to tsconfig `types` array.
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
### Non-Nx Source: Test Script Rewriting
|
||
|
|
|
||
|
|
Nx rewrites `package.json` scripts during init. Test scripts get broken:
|
||
|
|
|
||
|
|
- `"test": "jest"` → `"test": "nx test"` (circular if no executor configured)
|
||
|
|
- `"test": "vitest run"` → `"test": "nx test run"` (broken — `run` becomes an argument)
|
||
|
|
|
||
|
|
**Fix**: Remove all rewritten test scripts. `@nx/jest/plugin` and `@nx/vite/plugin` infer test targets from config files.
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
### CI Atomization
|
||
|
|
|
||
|
|
`@nx/jest/plugin` supports splitting tests per-file for CI parallelism:
|
||
|
|
|
||
|
|
```json
|
||
|
|
{
|
||
|
|
"plugin": "@nx/jest/plugin",
|
||
|
|
"options": {
|
||
|
|
"targetName": "test",
|
||
|
|
"ciTargetName": "test-ci"
|
||
|
|
}
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
This creates `test-ci--src/lib/foo.spec.ts` targets for each test file, enabling Nx Cloud distribution. Not relevant during import, but useful for post-import CI setup.
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
### Common Post-Import Issues
|
||
|
|
|
||
|
|
1. **"Cannot find target 'test'"**: `@nx/jest/plugin` not registered in `nx.json`. Run `npx nx add @nx/jest` or manually add the plugin entry.
|
||
|
|
|
||
|
|
2. **"Cannot find module 'jest-preset'"**: `jest.preset.js` missing at workspace root. Create it (see SKILL.md).
|
||
|
|
|
||
|
|
3. **"Cannot find type definition file for 'jest'"**: Missing `@types/jest` or `tsconfig.spec.json` doesn't have `"types": ["jest", "node"]`.
|
||
|
|
|
||
|
|
4. **Tests fail with "Cannot use import statement outside a module"**: `ts-jest` not installed or not configured as transform. Check `jest.config.ts` transform section.
|
||
|
|
|
||
|
|
5. **Snapshot path mismatches**: After import, `__snapshots__` directories may have paths baked in. Run tests once with `--updateSnapshot` to regenerate.
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Fix Order
|
||
|
|
|
||
|
|
### Subdirectory Import (Nx Source)
|
||
|
|
|
||
|
|
1. `npx nx add @nx/jest` — registers plugin in `nx.json` (does NOT create `jest.preset.js`)
|
||
|
|
2. Create `jest.preset.js` manually (see "Jest Preset" section above)
|
||
|
|
3. Install deps: `pnpm add -wD jest jest-environment-jsdom ts-jest @types/jest`
|
||
|
|
4. Install framework test deps: `@testing-library/react @testing-library/jest-dom` (React), `@vue/test-utils` (Vue)
|
||
|
|
5. Verify `tsconfig.spec.json` has `"types": ["jest", "node"]`
|
||
|
|
6. `nx run-many -t test`
|
||
|
|
|
||
|
|
### Whole-Repo Import (Non-Nx Source)
|
||
|
|
|
||
|
|
1. Remove rewritten test scripts from `package.json`
|
||
|
|
2. `npx nx add @nx/jest` — registers plugin (does NOT create preset)
|
||
|
|
3. Create `jest.preset.js` manually
|
||
|
|
4. Install deps (same as above)
|
||
|
|
5. Verify/fix `jest.config.*` — ensure `preset` path points to root `jest.preset.js`
|
||
|
|
6. Verify/fix `tsconfig.spec.json` — add `types`, `module`, `include` if missing
|
||
|
|
7. `nx run-many -t test`
|