jest-dom
Custom Jest matchers for asserting on the state of the DOM in your tests.
Repository Health
Technical Analysis
jest-dom is a companion library for Testing Library that adds a set of custom matchers to Jest (and Jest-compatible runners like Vitest) specifically for asserting on DOM nodes. Instead of manually inspecting element.textContent, element.getAttribute(...), or element.classList, you get declarative matchers such as toBeInTheDocument(), toHaveTextContent(), toHaveAttribute(), and toHaveClass() that read like the behavior they verify.
The library is deliberately narrow in scope: it does not render components or query the DOM itself (that’s the job of @testing-library/dom and its framework wrappers) — it only extends expect with matchers that operate on whatever DOM node your test already has a handle to. This keeps it usable across React, Vue, Angular, or plain DOM testing setups, and across both Jest and Vitest via a dedicated /vitest entry point.
Each matcher also produces test-failure output tailored to DOM assertions — printing the actual vs. expected text content, attribute value, or class list with contextual formatting — rather than Jest’s generic object-diff output, which is often unreadable for DOM nodes.
What You Get
- Presence & visibility matchers -
toBeInTheDocument(),toBeVisible(), andtoBeEmptyDOMElement()for asserting whether and how an element renders. - Form-state matchers -
toBeDisabled(),toBeEnabled(),toBeRequired(),toBeInvalid()/toBeValid(),toBeChecked(), andtoHaveValue()/toHaveDisplayValue()for form and input assertions. - Content & attribute matchers -
toHaveTextContent(),toHaveAttribute(),toHaveClass(),toHaveStyle(), andtoContainHTML()for verifying rendered output. - Accessibility matchers -
toHaveAccessibleName(),toHaveAccessibleDescription(),toHaveRole(), andtoHaveErrorMessage()for asserting on the accessibility tree. - Dedicated entry points - separate
/jest-globalsand/vitestimports so the matchers register correctly whether you use Jest’s globalexpector an explicit one. - DOM-aware failure output - custom error formatting that prints readable diffs of text content, attributes, and class lists instead of Jest’s default object serialization.
Common Use Cases
- Asserting rendered React/Vue/Angular output - after rendering a component with
@testing-library/react(or another framework adapter), asserting the resulting DOM node’s text, attributes, or visibility. - Form validation tests - checking that inputs are marked
required,invalid,disabled, or hold a specific value after user interaction. - Accessibility regression tests - asserting accessible names, roles, and ARIA error messages stay correct as markup changes.
- Migrating off enzyme or manual DOM assertions - replacing hand-rolled
element.getAttribute(...)checks with declarative, self-describing matchers. - Cross-runner test suites - projects that run the same DOM assertions under both Jest and Vitest via the shared matcher set.
Under The Hood
Architecture
jest-dom is structured as one small ES module per matcher (src/to-have-text-content.js, src/to-have-attribute.js, src/to-be-disabled.js, etc.), each exporting a single matcher function with the standard Jest matcher signature (received, ...args) => {pass, message}. src/matchers.js re-exports every matcher plus a generated set of toContainAnyBy*/toContainOneBy* query matchers, and src/index.js simply calls expect.extend(extensions) — the default side-effecting entry point most consumers import once in a test-setup file. Separate src/jest-globals.js and src/vitest.js entry points exist purely to register matchers against a runner-specific expect instead of relying on a Jest global, letting the same matcher implementations work unmodified across runners. Shared plumbing — type-checking, CSS parsing, message formatting — lives centrally in src/utils.js so every matcher throws and formats failures consistently.
Tech Stack
The package is plain JavaScript (with a TypeScript-authored types/ tree for consumers) built with Rollup into CommonJS and ESM bundles, exposed through conditional exports map entries for require/import and per-entry-point type declarations. Runtime dependencies are intentionally minimal and focused: @adobe/css-tools for parsing CSS in toHaveStyle, aria-query for role/ARIA lookups, dom-accessibility-api for computing accessible names/descriptions per the WAI-ARIA spec, picocolors for terminal-safe diff coloring, and redent/css.escape for output formatting and selector escaping. @testing-library/dom and vitest are peer dependencies rather than bundled ones, keeping the library agnostic about which runner or query layer a consumer uses.
Code Quality
The project has extensive test coverage: nearly every matcher in src/ has a same-named file under src/__tests__/, run through a dual Jest project config (tests/jest.config.dom and tests/jest.config.node) that exercises the matchers against both a real jsdom environment and a plain Node context. Error paths are explicit and typed via dedicated GenericTypeError, HtmlElementTypeError, NodeTypeError, and InvalidCSSError classes in utils.js rather than being swallowed, and every matcher validates its input node before proceeding. Linting and formatting are enforced through kcd-scripts (an opinionated ESLint/Prettier wrapper), and CI runs via GitHub Actions on each push, giving the project consistent, enforced conventions across a very large number of independently-authored matcher files.
API Design
The library’s entire public surface is designed to read as natural-language test assertions — expect(element).toBeInTheDocument() versus manually checking document.body.contains(element) — and it deliberately mirrors Jest’s built-in matcher conventions (supporting .not, custom failure messages via this.utils.matcherHint) so it feels native rather than bolted on. Getting started requires a single import in a test-setup file with no configuration, and the conditional exports map means TypeScript users, Jest-globals users, and Vitest users each get a dedicated, correctly-typed entry point without extra setup steps.
Used by 166 apps in this directory
LiteLLM
AI Development · Developer Tools
Open source AI gateway and Python SDK that gives you one OpenAI-compatible interface to call 100+ LLM providers, with built-in routing, cost tracking, guardrails, and virtual keys.
LobeHub
AI Assistants · Automation · Productivity
Your Chief Agent Operator — build, schedule, and collaborate with an entire AI team in one self-hostable workspace.
Lokus
Knowledge Management · Note Taking
Local-first note-taking with graph view, canvas & AI plugins—your Markdown files, zero telemetry, blazing-fast Rust performance.
Magic
AI Agents · Automation · Low Code Platforms
Magic is an enterprise-grade open-source AI agent platform combining a generalist AI agent, workflow engine, IM, and collaborative office system for running an AI-powered digital workforce.
marimo
Data Engineering · Developer Tools
A reactive Python notebook that eliminates hidden state, runs reproducibly, and deploys as a web app or script — stored as pure Python, built for the AI era.
Mastra Code
AI Code Assistants
"A coding agent that never compacts" — a terminal-based AI coding agent built on the Mastra framework, with Observational Memory instead of context compaction, multi-model support, and OAuth login for Claude Max or ChatGPT Plus.
Mathesar
Databases
Spreadsheet-like interface for your PostgreSQL database — self-hosted, no SQL required, native Postgres access control.
Mattermost
Collaboration · Devops · Team Chat
Open core, self-hosted team collaboration with chat, AI agents, voice calling, and deep DevOps integrations — all under your control.
Medplum
Authentication · Databases · Developer Tools
An open-source, FHIR-native healthcare platform that gives developers a compliant backend, authentication, a React component library, and serverless bots to build clinical applications in weeks instead of years.