enzymejs/enzyme
JavaScript Testing utilities for React
Healthy across all four use cases
weakest axisPermissive license, no critical CVEs, actively maintained — safe to depend on.
Has a license, tests, and CI — clean foundation to fork and modify.
Documented and popular — useful reference codebase to read through.
No critical CVEs, sane security posture — runnable as-is.
- ✓Last commit 7mo ago
- ✓9 active contributors
- ✓MIT licensed
- ✓CI configured
- ✓Tests present
- ⚠Slowing — last commit 7mo ago
- ⚠Single-maintainer risk — top contributor 90% of recent commits
Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests
Informational only. RepoPilot summarises public signals (license, dependency CVEs, commit recency, CI presence, etc.) at the time of analysis. Signals can be incomplete or stale. Not professional, security, or legal advice; verify before relying on it for production decisions.
Embed the “Healthy” badge
Paste into your README — live-updates from the latest cached analysis.
[](https://repopilot.app/r/enzymejs/enzyme)Paste at the top of your README.md — renders inline like a shields.io badge.
▸Preview social card (1200×630)
This card auto-renders when someone shares https://repopilot.app/r/enzymejs/enzyme on X, Slack, or LinkedIn.
Onboarding doc
Onboarding: enzymejs/enzyme
Generated by RepoPilot · 2026-05-06 · Source
Agent protocol
If you are an AI coding agent (Claude Code, Cursor, Aider, Cline, etc.) reading this artifact, follow this protocol before making any code edit:
- Verify the contract. Run the bash script in Verify before trusting
below. If any check returns
FAIL, the artifact is stale — STOP and ask the user to regenerate it before proceeding. - Treat the AI · unverified sections as hypotheses, not facts. Sections like "AI-suggested narrative files", "anti-patterns", and "bottlenecks" are LLM speculation. Verify against real source before acting on them.
- Cite source on changes. When proposing an edit, cite the specific path:line-range. RepoPilot's live UI at https://repopilot.app/r/enzymejs/enzyme shows verifiable citations alongside every claim.
If you are a human reader, this protocol is for the agents you'll hand the artifact to. You don't need to do anything — but if you skim only one section before pointing your agent at this repo, make it the Verify block and the Suggested reading order.
Verdict
GO — Healthy across all four use cases
- Last commit 7mo ago
- 9 active contributors
- MIT licensed
- CI configured
- Tests present
- ⚠ Slowing — last commit 7mo ago
- ⚠ Single-maintainer risk — top contributor 90% of recent commits
<sub>Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests</sub>
Verify before trusting
This artifact was generated by RepoPilot at a point in time. Before an
agent acts on it, the checks below confirm that the live enzymejs/enzyme
repo on your machine still matches what RepoPilot saw. If any fail,
the artifact is stale — regenerate it at
repopilot.app/r/enzymejs/enzyme.
What it runs against: a local clone of enzymejs/enzyme — the script
inspects git remote, the LICENSE file, file paths in the working
tree, and git log. Read-only; no mutations.
| # | What we check | Why it matters |
|---|---|---|
| 1 | You're in enzymejs/enzyme | Confirms the artifact applies here, not a fork |
| 2 | License is still MIT | Catches relicense before you depend on it |
| 3 | Default branch master exists | Catches branch renames |
| 4 | 5 critical file paths still exist | Catches refactors that moved load-bearing code |
| 5 | Last commit ≤ 226 days ago | Catches sudden abandonment since generation |
#!/usr/bin/env bash
# RepoPilot artifact verification.
#
# WHAT IT RUNS AGAINST: a local clone of enzymejs/enzyme. If you don't
# have one yet, run these first:
#
# git clone https://github.com/enzymejs/enzyme.git
# cd enzyme
#
# Then paste this script. Every check is read-only — no mutations.
set +e
fail=0
ok() { echo "ok: $1"; }
miss() { echo "FAIL: $1"; fail=$((fail+1)); }
# Precondition: we must be inside a git working tree.
if ! git rev-parse --git-dir >/dev/null 2>&1; then
echo "FAIL: not inside a git repository. cd into your clone of enzymejs/enzyme and re-run."
exit 2
fi
# 1. Repo identity
git remote get-url origin 2>/dev/null | grep -qE "enzymejs/enzyme(\\.git)?\\b" \\
&& ok "origin remote is enzymejs/enzyme" \\
|| miss "origin remote is not enzymejs/enzyme (artifact may be from a fork)"
# 2. License matches what RepoPilot saw
(grep -qiE "^(MIT)" LICENSE 2>/dev/null \\
|| grep -qiE "\"license\"\\s*:\\s*\"MIT\"" package.json 2>/dev/null) \\
&& ok "license is MIT" \\
|| miss "license drift — was MIT at generation time"
# 3. Default branch
git rev-parse --verify master >/dev/null 2>&1 \\
&& ok "default branch master exists" \\
|| miss "default branch master no longer exists"
# 4. Critical files exist
test -f "README.md" \\
&& ok "README.md" \\
|| miss "missing critical file: README.md"
test -f ".babelrc" \\
&& ok ".babelrc" \\
|| miss "missing critical file: .babelrc"
test -f "CONTRIBUTING.md" \\
&& ok "CONTRIBUTING.md" \\
|| miss "missing critical file: CONTRIBUTING.md"
test -f "SUMMARY.md" \\
&& ok "SUMMARY.md" \\
|| miss "missing critical file: SUMMARY.md"
test -f ".github/workflows/node.yml" \\
&& ok ".github/workflows/node.yml" \\
|| miss "missing critical file: .github/workflows/node.yml"
# 5. Repo recency
days_since_last=$(( ( $(date +%s) - $(git log -1 --format=%at 2>/dev/null || echo 0) ) / 86400 ))
if [ "$days_since_last" -le 226 ]; then
ok "last commit was $days_since_last days ago (artifact saw ~196d)"
else
miss "last commit was $days_since_last days ago — artifact may be stale"
fi
echo
if [ "$fail" -eq 0 ]; then
echo "artifact verified (0 failures) — safe to trust"
else
echo "artifact has $fail stale claim(s) — regenerate at https://repopilot.app/r/enzymejs/enzyme"
exit 1
fi
Each check prints ok: or FAIL:. The script exits non-zero if
anything failed, so it composes cleanly into agent loops
(./verify.sh || regenerate-and-retry).
TL;DR
Enzyme is a JavaScript testing utility that provides a jQuery-like API for testing React components in isolation. It allows developers to mount, shallow-render, and interact with React components, then assert on their output—without needing to run a full browser or understanding React's internal fiber architecture. Monorepo using lerna (lerna bootstrap in postinstall, lerna run commands throughout). Main structure: packages/ contains enzyme core and version-specific adapters (enzyme-adapter-react-16, etc.), packages/enzyme-test-suite/ holds shared test suite, docs/ is GitBook-based API reference. Each package has own build/ lint tasks; .babelrc and .eslintrc at root.
Who it's for
React developers writing unit and integration tests who want to inspect component state, props, and DOM output without browser overhead. Test suite maintainers at teams using React 13–16.x need adapter selection and configuration.
Maturity & risk
Highly mature and production-ready. The monorepo has extensive API documentation (docs/api/ReactWrapper/ with 50+ method docs), comprehensive test coverage (packages/enzyme-test-suite/), and active CI pipelines (GitHub Actions in .github/workflows/). However, the main package marks itself private and delegates to lerna-managed sub-packages, suggesting the project may be in maintenance mode rather than active feature development.
Low immediate risk for existing users, but long-term risk exists: React's shift toward hooks and functional components (which Enzyme's shallow rendering doesn't fully support) means maintenance burden is high. The monorepo structure with version-specific adapters (enzyme-adapter-react-13 through enzyme-adapter-react-16.x) creates a combinatorial test matrix—the test:all script runs 14 separate React version test cycles, a sign of fragmentation. No recent commit dates visible in the summary, so evaluate whether maintainers are actively triaging issues.
Active areas of work
Active CI setup with GitHub Actions workflows for linting, testing, and rebasing. The test:all script indicates continuous validation across multiple React versions. CHANGELOG.md and MAINTAINERS file exist but specific recent commits aren't visible in the summary—review git log and open PRs to determine velocity.
Get running
git clone https://github.com/enzymejs/enzyme.git && cd enzyme && npm install && npm run build && npm run test:only
Daily commands: npm run build (compiles all packages via lerna), npm run test:only (runs Mocha on packages/enzyme-test-suite/build), npm run test:watch (re-runs on file change), npm run lint (lints all packages), npm run build:watch (rebuilds on change).
Map of the codebase
README.md— Defines Enzyme's purpose as React testing utility, migration guides, and project scope—essential for understanding what this library does.babelrc— Babel configuration for transpiling JSX and ES6+ across all packages in this monorepo—foundational for the build pipelineCONTRIBUTING.md— Documents contribution standards, monorepo structure with lerna, and development workflow specific to this projectSUMMARY.md— Provides high-level overview of the library's API surface and architecture—quick reference for navigating the codebase.github/workflows/node.yml— CI/CD pipeline configuration that validates all packages and runs tests—critical for understanding release and quality gatesbook.json— GitBook configuration that builds the official documentation site—defines the doc architecture and navigation structure
Components & responsibilities
- enzyme (core package) (JavaScript, Babel, React internals) — Exports mount(), shallow(), render() functions and wrapper classes; orchestrates adapter selection based on React version; manages wrapper state and querying API
- Failure mode: If core package has bugs, all tests fail; if adapter version mismatch, cryptic 'Invalid hook call' or 'render is not a function' errors
- enzyme-adapter-react-X (per-version adapters) (React internals, ReactDOM, React Test Renderer) — Bridges enzyme API to React X's internal renderer, lifecycle hooks, and state management; implements mount(), shallow(), dive() for specific React version
- Failure mode: If adapter is wrong version or missing, wrapper methods throw TypeError; component lifecycle hooks not called correctly
- CI — undefined
How to make changes
Add a new ReactWrapper method
- Create method implementation in the appropriate package under packages/enzyme/src (
packages/enzyme/src/ReactWrapper.js (hypothetical—not in file list but inferred from structure)) - Write unit tests in packages/enzyme/test (
packages/enzyme/test/ReactWrapper-spec.js (inferred test location)) - Document the new method with examples (
docs/api/ReactWrapper/newMethodName.md) - Update SUMMARY.md to include the new method in the API reference table of contents (
SUMMARY.md) - Run linter and tests via npm run lint and npm test before submitting PR (
.eslintrc)
Add support for a new React version
- Update adapter package compatibility matrix in packages/enzyme-adapter-react-X/package.json (
packages/enzyme-adapter-react-*/package.json (version-specific adapter)) - Add React version to CI test matrix in GitHub Actions (
.github/workflows/node.yml) - Document migration steps if breaking changes exist (
CHANGELOG.md) - Update README compatibility table and migration guide (
README.md)
Publish a new Enzyme release
- Update version numbers across packages using lerna (
package.json (root version field)) - Run preversion checks: linting, testing, type validation (
.eslintrc and package.json (check script)) - Document changes in changelog with version and date (
CHANGELOG.md) - Publish packages to npm via npm publish (handled by postversion script) (
.npmrc) - Rebuild and deploy documentation site (
book.json and docs/)
Why these technologies
- Lerna (monorepo manager) — Enables separate packages for enzyme-core and per-version React adapters while sharing build/test infrastructure and unified versioning
- Babel + JSX transpilation — Converts modern React JSX and ES6+ to ES5-compatible code for broad Node.js version and browser compatibility
- Jest/Mocha test framework (inferred) — Standard testing approach for React libraries; integrated with nyc for code coverage reporting
- ESLint + Markdown linting — Enforces consistent code style and documentation quality across 470+ files in the monorepo
- GitHub Actions CI/CD — Automated testing on every PR and push; validates compatibility across Node versions before release to npm
- GitBook for documentation — Generates searchable, versioned API reference site from Markdown files; auto-deploys on release
Trade-offs already made
-
Separate adapter packages for each React version (enzyme-adapter-react-16, react-17, etc.)
- Why: React's internal APIs change significantly between major versions; a single adapter would require version detection and conditional logic
- Consequence: Developers must install matching adapter for their React version; adds 3–5 dependencies per user but ensures reliability
-
Shallow rendering as primary testing mode alongside full mount
- Why: Enables fast, isolated component unit tests without jsdom/JSDOM overhead; mirrors popular Vue/Angular testing patterns
- Consequence: Tests may miss integration bugs; developers must consciously choose between shallow and mount based on test goal
-
jQuery-like API (find, closest, filter, simulate) for React components
- Why: Lowers learning curve for developers familiar with jQuery DOM manipulation and jQuery Test Utilities
- Consequence: API is somewhat at odds with React's functional, props-driven paradigm; can mask anti-patterns like over-testing implementation details
-
Unified monorepo with lerna bootstrap for local development
- Why: Allows testing adapters against enzyme-core in-repo before publishing; single npm release cycle
- Consequence: Complex setup for contributors (npm link, lerna bootstrap); higher cognitive load for first-time setup
Non-goals (don't propose these)
- Does not provide snapshot testing (complementary tool responsibility)
- Does not bundle a test runner (Jest/Mocha must be configured separately)
- Does not replace E2E testing frameworks (Cypress, Selenium); focuses on unit/integration tests
- Does not handle React Native testing (web-only library)
- Does not provide component mocking (user responsibility via Jest.mock or similar)
- Not a real-time collaborative testing tool
Traps & gotchas
- The npm postinstall script runs 'lerna bootstrap' unless on Travis CI—this auto-links packages; if you use npm link manually, you may get conflicts. 2. test:all cycles through React 13, 14, 15.x, and 16.x versions by running install-relevant-react.sh before each test phase—if you modify tests, you must run the full test:all or you'll miss version-specific regressions. 3. Shallow rendering differs significantly across React versions (especially 0.13 vs. 16); adapters abstract this, but your test may pass on one version and fail on another. 4. The pretest script runs lint before build, so a lint failure blocks test:only; fix linting issues first (npm run lint --fix). 5. No explicit npm ci lock-file strategy visible; npm postinstall assumes a mutable node_modules (clean-node-modules exists), so CI environments must handle this explicitly.
Architecture
Concepts to learn
- Shallow rendering — Enzyme's core strength—it renders a component one level deep, not its children, letting you test a component in isolation. Adapter-specific (React 13–15 vs. 16+ use different internals). Understanding its limitations with hooks and fragments is critical.
- React Adapter Pattern — Enzyme abstracts React version differences through adapters (enzyme-adapter-react-16 vs. enzyme-adapter-react-15). Each adapter implements a common interface to mount/render components. Contributing to Enzyme means understanding how adapters bridge version gaps.
- React Fiber — React 16+ uses Fiber architecture internally. Enzyme's adapter for React 16 must introspect Fiber nodes to shallow-render and provide instance access. Pre-Fiber versions (13–15) use a different internal tree structure, which is why adapters exist.
- jQuery-like Selector API — Enzyme borrows jQuery's method chaining (find, filter, map, forEach) and selector syntax. This makes component traversal intuitive for DOM-test-familiar devs but can mask React-specific concerns (e.g., .find() doesn't understand context or HOCs directly).
- Enzyme Adapter Protocol — Each adapter must implement a common interface (methods like createShallowRenderer, createMountRenderer, elementToNode). Understanding this protocol is required to extend Enzyme for new React versions or alternative UI libraries (preact, inferno).
- Monorepo & Lerna Dependency Management — Enzyme uses lerna to manage multiple interdependent packages (enzyme core, adapters, test suite) from a single repo. Understanding lerna publish, bootstrap, and run is essential for contributing and releasing.
- React Reconciliation & Virtual DOM Diffing — Enzyme's simulate() method triggers React's reconciliation algorithm. Understanding how React diffs and updates components is necessary to write correct tests (e.g., why simulate doesn't always flush updates, or why shallow rendering doesn't invoke lifecycle methods).
Related repos
facebook/react— Enzyme is a test utility for React; understanding React's component lifecycle, reconciliation, and fiber architecture is essential to Enzyme's designairbnb/airbnb-prop-types— Enzyme is maintained by Airbnb; this repo shows how Airbnb enforces prop validation in component tests, a common use case for Enzymelodash/lodash— Enzyme's selector and traversal API is inspired by jQuery; lodash provides similar functional composition patterns used in Enzyme's assertion helperstesting-library/react-testing-library— Modern alternative to Enzyme; React Testing Library focuses on user behavior rather than implementation details, and many Enzyme users migrate here for React 16.8+enzymejs/enzyme-adapter-react-16— Official companion repo; the adapter package lives here and must be installed alongside enzyme core to support React 16
PR ideas
To work on one of these in Claude Code or Cursor, paste:
Implement the "<title>" PR idea from CLAUDE.md, working through the checklist as the task list.
Add missing ReactWrapper API documentation files
The docs/api/ReactWrapper directory has 50+ method documentation files listed, but several core methods referenced in the codebase appear to be missing .md files. Specifically, methods like shallow(), simulateError(), setState(), setProps(), unmount(), and update() are commonly used in React testing but have no corresponding documentation files. This creates gaps in the API reference that new contributors and users rely on.
- [ ] Review src/ implementation files to identify all public ReactWrapper methods
- [ ] Compare against existing docs/api/ReactWrapper/*.md files to find gaps
- [ ] Create missing .md documentation files following the existing format (e.g., docs/api/ReactWrapper/shallow.md, docs/api/ReactWrapper/setState.md)
- [ ] Include method signature, description, usage examples, and return type for each new file
- [ ] Update docs/api/README.md to include links to newly documented methods
Add GitHub Action workflow for testing against multiple Node versions
The repo has .github/workflows/node.yml and node-pretest.yml, but based on the test:all script that tests against React 13-16.8, there's no dedicated workflow testing against multiple Node.js versions (12, 14, 16, 18, etc.). This is critical for a testing utility library that must maintain compatibility across Node versions used by different projects.
- [ ] Create .github/workflows/node-versions.yml with a matrix strategy for Node 12, 14, 16, 18
- [ ] Configure each Node version to run: npm run build && npm run test:only
- [ ] Add separate workflow steps for linting and code coverage reporting
- [ ] Ensure the workflow runs on push to master and pull requests
- [ ] Update README.md with a badge showing Node version compatibility status
Add integration tests for adapter compatibility across React versions
The repo supports multiple React versions (13-16.8+) via packages/, but there's no explicit integration test suite validating that each adapter (enzyme-adapter-react-*) works correctly with its target React version. The existing test:all script runs the same tests against different React installs, but dedicated adapter integration tests would catch adapter-specific regressions early.
- [ ] Create packages/enzyme-test-suite/build/adapter-integration/ directory for adapter-specific tests
- [ ] Add test files for each major adapter: adapter-react-16.spec.js, adapter-react-17.spec.js, adapter-react-18.spec.js
- [ ] Test adapter instantiation, mounting/rendering, and core lifecycle methods for each React version
- [ ] Create a new npm script: 'test:adapters' that runs only these integration tests
- [ ] Document the adapter testing approach in CONTRIBUTING.md with specific instructions for maintainers
Good first issues
- Add missing TypeScript .d.ts stubs: enzyme/src/ has no TypeScript definitions; creating packages/enzyme/types/index.d.ts and exporting mount, shallow, render, and ReactWrapper would help TS users. Skeleton already exists in some adapters; extend to core.
- Expand API documentation for edge cases: docs/api/ReactWrapper/ documents 50+ methods but lacks examples for common pitfalls (e.g., how .find() behaves with fragments, how simulate() handles async state updates in 16+). Pick 5 methods and add 'Common Mistakes' sections.
- Add integration test for React 16.8+ hooks: packages/enzyme-test-suite/test/ has no tests for useState/useEffect hook interaction with shallow rendering. Create test/hooks.spec.js with at least 10 test cases (hook state updates, effect cleanup, custom hooks). This documents Enzyme's limitations with hooks.
Top contributors
- @ljharb — 90 commits
- @deining — 2 commits
- @mul53 — 2 commits
- @BboyAkers — 1 commits
- @martin-pettersson — 1 commits
Recent commits
61e1b47— [tests] [dev deps] pinpsldue to breaking change in a minor version (ljharb)fbc174e— [deps] pin@babel/nodedue to a breaking change in a minor (ljharb)ec4f378— [enzyme-shallow-equal] [deps] updateobject-is(ljharb)e2b69f5— [enzyme-adapter-utils] [deps] updatefunction.prototype.name,object.fromentries(ljharb)53bc4bb— [enzyme-adapter-react-helper] [deps] updateobject.getownpropertydescriptors(ljharb)e314ea9— [tests] [deps] updatehas-symbols(ljharb)a50596a— [enzyme-adapter-react-16,enzyme-adapter-utils,enzyme-shallow-equal] [deps] updatehasown(ljharb)05fa5a6— [enzyme-adapter-*] [deps] updateobject.assign,object.values(ljharb)b220c31— [enzyme] [deps] updatearray.prototype.flat,function.prototype.name,hasown,is-boolean-object, `is-number-obje (ljharb)ea7e662— [*] [dev deps] updateeslint-plugin-import,eslint-plugin-jsx-a11y,eslint-plugin-react(ljharb)
Security observations
The enzyme repository has a moderate security posture. The primary concern is the incomplete visibility of dependencies in the provided package.json, which prevents a full vulnerability assessment. Secondary concerns include the postinstall script's use of 'npm link' and the lack of a security policy. The codebase is a testing library for React, which inherently reduces injection risks compared to backend services, but users should be cautioned about XSS when testing with untrusted input. The monorepo structure (using lerna) requires careful management of cross-package dependencies and version alignment.
- High · Incomplete package.json - Missing Security Metadata —
package.json. The package.json file appears to be truncated in the provided content. Critical fields like 'dependencies', 'devDependencies', and 'engines' are not visible. This prevents a comprehensive security audit of third-party dependencies for known vulnerabilities (CVEs). Fix: Provide the complete package.json file. Ensure all dependencies are pinned to specific versions or ranges. Regularly run 'npm audit' and 'npm audit fix' to identify and remediate known vulnerabilities. - Medium · Postinstall Script Security Risk —
package.json - postinstall script. The postinstall script contains a conditional check for TRAVIS environment variable and executes 'npm link npm' and 'lerna bootstrap'. The 'npm link' command modifies the npm installation globally and could pose security risks in CI/CD environments or when dependencies are malicious. Fix: Avoid using 'npm link' in production or CI/CD postinstall scripts. Use 'npm ci' instead of 'npm install' in CI/CD pipelines. Review the necessity of linking npm itself, as this is unusual and potentially dangerous. - Medium · Multiple React Version Testing Without Dependency Pinning Visibility —
package.json - test:all and react scripts. The test:all script tests against multiple React versions (13-16.8), but the mechanism for switching React versions (install-relevant-react.sh) is not visible. This could introduce supply chain risks if version selection is not carefully controlled. Fix: Verify that install-relevant-react.sh uses pinned version specifications and validates checksums. Ensure React version installation is audited for security before running tests. - Low · Missing Security Policy File —
Repository root. No SECURITY.md or security policy file is visible in the repository structure. This makes it difficult for security researchers to report vulnerabilities responsibly. Fix: Create a SECURITY.md file with instructions for responsible vulnerability disclosure. Consider adding a .github/SECURITY.md template. - Low · Incomplete Documentation on Security Practices —
docs/ directory. The provided file structure shows documentation and guides, but no visible security hardening guide or best practices documentation for users of the library regarding safe usage with user input. Fix: Add documentation warning about XSS risks when using enzyme with untrusted data, particularly regarding simulation and DOM manipulation features.
LLM-derived; treat as a starting point, not a security audit.
Where to read next
- Open issues — current backlog
- Recent PRs — what's actively shipping
- Source on GitHub
Generated by RepoPilot. Verdict based on maintenance signals — see the live page for receipts. Re-run on a new commit to refresh.