---
# === IDENTITY ===
id: software/devops/jest-configuration/2026
canonical_question: "Jest testing configuration reference"
aliases:
  - "How to configure Jest for TypeScript projects"
  - "jest.config.ts best practices and options"
  - "Jest 30 configuration with ts-jest and ESM"
  - "Jest setup for React and Node.js testing"
entity_type: software_reference
domain: software > devops > Jest Testing Configuration
region: global
jurisdiction: global
temporal_scope: 2024-2026

# === VERIFICATION ===
last_verified: 2026-02-28
confidence: 0.93
version: 1.0
first_published: 2026-02-28

# === TEMPORAL VALIDITY ===
temporal_validity:
  status: stable
  last_breaking_change: "Jest 30 (June 2025) — dropped Node <18, jsdom upgraded to 26, stricter TypeScript types"
  next_review: 2026-08-27
  change_sensitivity: medium

# === CONSTRAINTS ===
constraints:
  - "Jest 30 requires Node.js 18+ — versions 14, 16, 19, and 21 are no longer supported"
  - "TypeScript config files (jest.config.ts) require ts-node or esbuild-register installed — Jest does not parse TS natively"
  - "ESM support requires --experimental-vm-modules flag — not yet stable without it"
  - "jest-environment-jsdom is a separate package since Jest 28 — must be installed explicitly for DOM testing"
  - "transform configuration must match your file types — .ts/.tsx files need ts-jest or @swc/jest transformer"

# === SKIP CONDITIONS ===
skip_this_unit_if:
  - condition: "Using Vitest instead of Jest"
    use_instead: "Vitest configuration docs at vitest.dev/config"
  - condition: "Using Vite and want a Vite-native test runner"
    use_instead: "Vitest — drop-in Jest replacement for Vite projects"

# === AGENT HINTS ===
inputs_needed:
  - key: "language"
    question: "Are you testing TypeScript or JavaScript?"
    type: choice
    options: ["TypeScript", "JavaScript"]
  - key: "environment"
    question: "Are you testing browser code (React/Vue) or Node.js code?"
    type: choice
    options: ["Browser (jsdom)", "Node.js", "Both"]
  - key: "module_system"
    question: "Does your project use ESM or CommonJS?"
    type: choice
    options: ["CommonJS", "ESM (type: module)", "Mixed"]

# === DISTRIBUTION ===
canonical_source: "https://knowledgelib.io/software/devops/jest-configuration/2026"
suggested_citation: "Source: knowledgelib.io — AI Knowledge Library (verified 2026-02-28)"

# === RELATED UNITS ===
related_kos:
  depends_on:
    - id: "software/devops/typescript-tsconfig/2026"
      label: "TypeScript tsconfig Patterns Reference"
  related_to:
    - id: "software/devops/eslint-prettier-config/2026"
      label: "ESLint + Prettier Configuration Reference"
    - id: "software/devops/pre-commit-hooks/2026"
      label: "Pre-commit Hooks Setup Reference"
  solves: []
  alternative_to: []
  often_confused_with: []

# === SOURCES ===
sources:
  - id: src1
    title: "Configuring Jest — Official Docs"
    author: Jest
    url: https://jestjs.io/docs/configuration
    type: official_docs
    published: 2025-06-04
    reliability: authoritative
  - id: src2
    title: "Jest 30: Faster, Leaner, Better"
    author: Jest
    url: https://jestjs.io/blog/2025/06/04/jest-30
    type: official_docs
    published: 2025-06-04
    reliability: authoritative
  - id: src3
    title: "From v29 to v30 — Jest Migration Guide"
    author: Jest
    url: https://jestjs.io/docs/upgrading-to-jest30
    type: official_docs
    published: 2025-06-04
    reliability: authoritative
  - id: src4
    title: "ts-jest Configuration"
    author: ts-jest
    url: https://kulshekhar.github.io/ts-jest/docs/getting-started/installation
    type: official_docs
    published: 2025-01-01
    reliability: high
  - id: src5
    title: "ESM Support — ts-jest"
    author: ts-jest
    url: https://kulshekhar.github.io/ts-jest/docs/guides/esm-support
    type: official_docs
    published: 2025-01-01
    reliability: high
  - id: src6
    title: "Getting Started — Jest"
    author: Jest
    url: https://jestjs.io/docs/getting-started
    type: official_docs
    published: 2025-06-04
    reliability: authoritative
  - id: src7
    title: "Jest CLI Options"
    author: Jest
    url: https://jestjs.io/docs/cli
    type: official_docs
    published: 2025-06-04
    reliability: authoritative
---

# Jest Testing Configuration Reference

## TL;DR

- **Bottom line**: Configure Jest in `jest.config.ts` using `ts-jest` preset for TypeScript projects; set `testEnvironment` to `"jsdom"` for React/browser code or `"node"` for backend; use `moduleNameMapper` for path aliases.
- **Key tool/command**: `npx jest --config jest.config.ts`
- **Watch out for**: Forgetting to install `ts-node` — Jest cannot read `jest.config.ts` without it, and the error message is not always clear.
- **Works with**: Jest 29.x–30.x, TypeScript 5.4+, Node.js 18+, React 18+/19.

## Constraints
<!-- Agents: read this section before recommending any action from this unit.
     These are hard constraints that must not be violated. -->

- Jest 30 requires Node.js 18+ — versions 14, 16, 19, and 21 are no longer supported
- TypeScript config files (`jest.config.ts`) require `ts-node` or `esbuild-register` installed — Jest does not parse TS natively
- ESM support requires `--experimental-vm-modules` flag — not yet stable without it
- `jest-environment-jsdom` is a separate package since Jest 28 — must be installed explicitly for DOM testing
- `transform` configuration must match your file types — `.ts`/`.tsx` files need `ts-jest` or `@swc/jest` transformer

## Quick Reference

| Option | Default | Purpose |
|---|---|---|
| `preset` | none | Base config preset (`ts-jest`, `ts-jest/presets/default-esm`) |
| `testEnvironment` | `"node"` | Test runtime (`"node"` or `"jsdom"`) |
| `roots` | `["<rootDir>"]` | Directories to search for test files |
| `testMatch` | `["**/__tests__/**/*.[jt]s?(x)", "**/?(*.)+(spec\|test).[jt]s?(x)"]` | Glob patterns for test files |
| `transform` | `{}` | File transformers (ts-jest, @swc/jest, babel-jest) |
| `moduleNameMapper` | `{}` | Path alias mapping (@ → src) |
| `setupFiles` | `[]` | Scripts run before test framework init |
| `setupFilesAfterFramework` | `[]` | Scripts run after framework init (e.g., jest-dom) |
| `collectCoverage` | `false` | Enable coverage collection |
| `coverageThreshold` | none | Minimum coverage percentages |
| `coverageDirectory` | `"coverage"` | Coverage report output dir |
| `moduleFileExtensions` | `["js","mjs","cjs","jsx","ts","tsx","json","node","mts","cts"]` | Resolved file extensions |
| `testTimeout` | `5000` | Default test timeout (ms) |
| `verbose` | `false` | Show individual test results |
| `maxWorkers` | `50%` | Parallel test workers |

## Decision Tree

```
START
├── TypeScript project?
│   ├── YES → Install ts-jest, use preset: 'ts-jest'
│   └── NO → Use babel-jest (included by default)
├── React or browser DOM testing?
│   ├── YES → testEnvironment: 'jsdom', install jest-environment-jsdom
│   └── NO → testEnvironment: 'node' (default)
├── Project uses ESM (type: module)?
│   ├── YES → Use ts-jest ESM preset + --experimental-vm-modules
│   └── NO → Standard CJS preset works
├── Need faster transforms?
│   ├── YES → Use @swc/jest instead of ts-jest (3-5x faster)
│   └── NO → ts-jest is fine for most projects
├── Using path aliases (@/ imports)?
│   ├── YES → Configure moduleNameMapper to match tsconfig paths
│   └── NO ↓
└── DEFAULT → ts-jest preset + node environment
```

## Step-by-Step Guide

### 1. Install Jest and TypeScript support

Install Jest with ts-jest for TypeScript transformation. [src4]

```bash
# Core packages
npm install --save-dev jest ts-jest @types/jest

# For React/browser testing, also install:
npm install --save-dev jest-environment-jsdom @testing-library/react @testing-library/jest-dom
```

**Verify**: `npx jest --version` → `30.x.x`

### 2. Create jest.config.ts

Generate a base config with ts-jest. [src1]

```typescript
// jest.config.ts
import type { Config } from 'jest';

const config: Config = {
  preset: 'ts-jest',
  testEnvironment: 'node',
  roots: ['<rootDir>/src'],
  testMatch: ['**/__tests__/**/*.test.ts', '**/*.spec.ts'],
  moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json'],
  verbose: true,
};

export default config;
```

**Verify**: `npx jest --showConfig | grep preset` → shows `ts-jest`

### 3. Configure path aliases

Map TypeScript `paths` to Jest's `moduleNameMapper`. [src1]

```typescript
// jest.config.ts
import type { Config } from 'jest';

const config: Config = {
  preset: 'ts-jest',
  testEnvironment: 'node',
  moduleNameMapper: {
    '^@/(.*)$': '<rootDir>/src/$1',
    '^@components/(.*)$': '<rootDir>/src/components/$1',
    '^@utils/(.*)$': '<rootDir>/src/utils/$1',
  },
};

export default config;
```

**Verify**: Test file with `import { fn } from '@/utils/helper'` → resolves correctly

### 4. Set up React testing (jsdom)

Configure for React component testing with Testing Library. [src6]

```typescript
// jest.config.ts — React project
import type { Config } from 'jest';

const config: Config = {
  preset: 'ts-jest',
  testEnvironment: 'jsdom',
  setupFilesAfterFramework: ['<rootDir>/src/setupTests.ts'],
  moduleNameMapper: {
    '\\.(css|less|scss)$': 'identity-obj-proxy',
    '\\.(jpg|jpeg|png|svg)$': '<rootDir>/__mocks__/fileMock.ts',
  },
  transform: {
    '^.+\\.tsx?$': 'ts-jest',
  },
};

export default config;
```

```typescript
// src/setupTests.ts
import '@testing-library/jest-dom';
```

**Verify**: `npx jest --testEnvironment jsdom` → tests run in simulated browser

### 5. Configure coverage thresholds

Enforce minimum code coverage in CI. [src1]

```typescript
// jest.config.ts — with coverage
import type { Config } from 'jest';

const config: Config = {
  preset: 'ts-jest',
  testEnvironment: 'node',
  collectCoverage: true,
  coverageDirectory: 'coverage',
  coverageReporters: ['text', 'lcov', 'json-summary'],
  coverageThreshold: {
    global: {
      branches: 80,
      functions: 80,
      lines: 80,
      statements: 80,
    },
  },
  collectCoverageFrom: [
    'src/**/*.{ts,tsx}',
    '!src/**/*.d.ts',
    '!src/**/index.ts',
    '!src/**/__tests__/**',
  ],
};

export default config;
```

**Verify**: `npx jest --coverage` → coverage table printed with thresholds enforced

### 6. Configure ESM support (experimental)

For projects with `"type": "module"` in package.json. [src5]

```typescript
// jest.config.ts — ESM mode
import type { Config } from 'jest';
import { createDefaultEsmPreset } from 'ts-jest';

const presetConfig = createDefaultEsmPreset();

const config: Config = {
  ...presetConfig,
  testEnvironment: 'node',
  moduleNameMapper: {
    '^(\\.{1,2}/.*)\\.js$': '$1',  // Strip .js extension for TS
  },
};

export default config;
```

```json
// package.json — required for ESM Jest
{
  "scripts": {
    "test": "NODE_OPTIONS='--experimental-vm-modules' npx jest"
  }
}
```

**Verify**: `npm test` → ESM imports resolve correctly

## Code Examples

### Complete Jest config for Node.js + TypeScript backend

```typescript
// jest.config.ts — Express/Fastify backend
import type { Config } from 'jest';

const config: Config = {
  preset: 'ts-jest',
  testEnvironment: 'node',
  roots: ['<rootDir>/src'],
  testMatch: ['**/__tests__/**/*.test.ts', '**/*.spec.ts'],
  moduleNameMapper: {
    '^@/(.*)$': '<rootDir>/src/$1',
  },
  collectCoverage: true,
  coverageDirectory: 'coverage',
  coverageThreshold: {
    global: { branches: 80, functions: 80, lines: 80, statements: 80 },
  },
  collectCoverageFrom: ['src/**/*.ts', '!src/**/*.d.ts', '!src/index.ts'],
  testTimeout: 10000,
  verbose: true,
  // Clear mocks between tests
  clearMocks: true,
  restoreMocks: true,
};

export default config;
```

### Jest config with @swc/jest (faster transforms)

```typescript
// jest.config.ts — using SWC for 3-5x faster transforms
import type { Config } from 'jest';

const config: Config = {
  testEnvironment: 'node',
  roots: ['<rootDir>/src'],
  transform: {
    '^.+\\.(t|j)sx?$': ['@swc/jest', {
      jsc: {
        parser: {
          syntax: 'typescript',
          tsx: true,
          decorators: true,
        },
        transform: {
          react: { runtime: 'automatic' },
        },
      },
    }],
  },
  moduleNameMapper: {
    '^@/(.*)$': '<rootDir>/src/$1',
  },
};

export default config;
```

### Monorepo Jest config (project-based)

> Full script: [monorepo-jest-config-project-based.ts](scripts/monorepo-jest-config-project-based.ts) (27 lines)

```typescript
// jest.config.ts — monorepo root with multiple projects
import type { Config } from 'jest';
const config: Config = {
  projects: [
    {
# ... (see full script)
```

## Anti-Patterns

### Wrong: Using ts-jest for JavaScript files

```typescript
// ❌ BAD — ts-jest cannot transform plain .js files by default
const config: Config = {
  preset: 'ts-jest',
  testMatch: ['**/*.test.js'],  // These won't be transformed
};
```

### Correct: Use ts-jest only for TypeScript, babel-jest for JS

```typescript
// ✅ GOOD — separate transforms for different file types
const config: Config = {
  transform: {
    '^.+\\.tsx?$': 'ts-jest',
    '^.+\\.jsx?$': 'babel-jest',
  },
};
```

### Wrong: Not installing jest-environment-jsdom separately

```typescript
// ❌ BAD — jsdom is NOT bundled with Jest since v28
const config: Config = {
  testEnvironment: 'jsdom',  // Error: Cannot find module 'jest-environment-jsdom'
};
```

### Correct: Install jsdom environment as separate package

```bash
# ✅ GOOD — install separately
npm install --save-dev jest-environment-jsdom
```

### Wrong: Forgetting to handle CSS/image imports

```typescript
// ❌ BAD — Jest crashes on CSS imports
// Component: import './styles.css';
// Error: SyntaxError: Unexpected token '.'
const config: Config = {
  preset: 'ts-jest',
  testEnvironment: 'jsdom',
  // No moduleNameMapper for CSS!
};
```

### Correct: Map static assets to mocks

```typescript
// ✅ GOOD — mock CSS and image imports
const config: Config = {
  preset: 'ts-jest',
  testEnvironment: 'jsdom',
  moduleNameMapper: {
    '\\.(css|less|scss|sass)$': 'identity-obj-proxy',
    '\\.(jpg|jpeg|png|gif|svg)$': '<rootDir>/__mocks__/fileMock.ts',
  },
};
```

## Common Pitfalls

- **jest.config.ts not loading**: Missing `ts-node` package. Fix: `npm install --save-dev ts-node`. [src1]
- **Tests pass locally, fail in CI**: Different Node.js versions. Fix: pin Node version in CI with `node-version: '20'` in GitHub Actions. [src3]
- **Slow test runs**: ts-jest type-checks every file. Fix: set `isolatedModules: true` in ts-jest config, or switch to `@swc/jest`. [src4]
- **moduleNameMapper regex wrong**: Path alias not matching. Fix: always escape dots in regex, use `^@/(.*)$` not `@/(.*)`. [src1]
- **Jest 30 TypeScript type errors**: `toHaveBeenCalledWith` stricter types. Fix: use `expect(fn).toHaveBeenCalledWith(expect.any(Number))` for flexible matching. [src3]
- **Coverage not counting all files**: Only tested files are included. Fix: add `collectCoverageFrom: ['src/**/*.ts']` to include untested files. [src1]
- **Cannot use import statement**: Jest defaults to CJS. Fix: use `ts-jest` preset or add `transform` for `.ts` files. [src4]

## Diagnostic Commands

```bash
# Show resolved Jest configuration
npx jest --showConfig

# Run tests matching a pattern
npx jest --testPathPattern="auth"

# Run a single test file
npx jest src/__tests__/auth.test.ts

# Run tests in watch mode
npx jest --watch

# Run tests with coverage
npx jest --coverage

# List all tests without running them
npx jest --listTests

# Debug Jest config issues
npx jest --debug

# Run with verbose output
npx jest --verbose
```

## Version History & Compatibility

| Version | Status | Breaking Changes | Migration Notes |
|---|---|---|---|
| Jest 30 | Current | Node <18 dropped, jsdom 26, stricter TS types, bundled internals | Check `toHaveBeenCalledWith` type matching; install jest-environment-jsdom@30 |
| Jest 29 | Maintenance | — | Last version supporting Node 16 |
| Jest 28 | EOL | jsdom extracted to separate package | `npm i jest-environment-jsdom` |
| Jest 27 | EOL | — | Upgrade to 29+ for security patches |

## When to Use / When Not to Use

| Use When | Don't Use When | Use Instead |
|---|---|---|
| Established codebase already on Jest | New Vite project (Vitest is native) | Vitest |
| Need snapshot testing | Deno project | Deno.test |
| React Testing Library (excellent Jest integration) | Bun project | bun:test |
| CI pipeline with Jest-specific tooling | Need browser-native testing | Playwright or Cypress |

## Important Caveats

- Jest 30 bundles all internal modules — unofficial deep imports into Jest packages will break on upgrade
- `@swc/jest` is 3-5x faster than `ts-jest` but does not type-check during transforms — run `tsc --noEmit` separately
- ESM support in Jest is still experimental and requires `--experimental-vm-modules` flag
- `jest.config.ts` parsing on Node 24+ with CJS may have issues — prefer `.mjs` or `.js` config if problems arise

## Related Units

- [TypeScript tsconfig Patterns Reference](/software/devops/typescript-tsconfig/2026)
- [ESLint + Prettier Configuration Reference](/software/devops/eslint-prettier-config/2026)
- [Pre-commit Hooks Setup Reference](/software/devops/pre-commit-hooks/2026)
