jest-dom

Custom Jest matchers for asserting on the state of the DOM in your tests.

Library
npm
v7.0.1
4,603 stars
MIT License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum. How we score it →
59 /100 Fair
Development Activity 24
Maintenance 48
Community 64
Maturity 60
Momentum 40

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation. How we score it →
80 /100 Excellent
Architecture 82
Code Quality 88
Innovation 60
Learning Curve 90

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(), and toBeEmptyDOMElement() for asserting whether and how an element renders.
  • Form-state matchers - toBeDisabled(), toBeEnabled(), toBeRequired(), toBeInvalid()/toBeValid(), toBeChecked(), and toHaveValue()/toHaveDisplayValue() for form and input assertions.
  • Content & attribute matchers - toHaveTextContent(), toHaveAttribute(), toHaveClass(), toHaveStyle(), and toContainHTML() for verifying rendered output.
  • Accessibility matchers - toHaveAccessibleName(), toHaveAccessibleDescription(), toHaveRole(), and toHaveErrorMessage() for asserting on the accessibility tree.
  • Dedicated entry points - separate /jest-globals and /vitest imports so the matchers register correctly whether you use Jest’s global expect or 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

TypeScript
99%
Apache 2.0

Colanode

Collaboration · Knowledge Management · Team Chat

5,170

Local-first, self-hosted workspace that combines real-time chat, Notion-style pages, and structured databases — all synced via CRDTs so you work offline without losing a keystroke.

View details
46
Repo Health
73
Technical
67
Dependency
Built with
TypeScript 99%
Updated 7 months ago
TypeScript
84%
Apache 2.0

Continue

AI Code Assistants · AI Development · Automation

36,303

Open-source coding agent for VS Code, JetBrains, and CLI with support for 30+ LLM providers.

View details
66
Repo Health
88
Technical
62
Dependency
Built with
TypeScript 84%
Updated 1 weeks ago
TypeScript
45%
Other

Convex Backend

Databases · Developer Tools

12,754

Open-source reactive database that lets developers build live-updating apps with pure TypeScript, strong consistency, and real-time subscriptions—no separate API layer required.

View details
88
Repo Health
82
Technical
65
Dependency
Built with
TypeScript 45%
Rust 43%
Updated 6 days ago
Go
49%
Other

Cosmos-Server

Authentication · Security

6,183

All-in-one self-hosted home server with SmartShield anti-DDoS, Nebula mesh VPN, automatic HTTPS, and a 250-app marketplace — all secured behind a unified auth layer.

View details
82
Repo Health
59
Technical
65
Dependency
Built with
Go 49%
JavaScript 48%
Updated 1 weeks ago
TypeScript
93%
AGPL 3.0

CourseLit

Blogging · Ecommerce

1,284

Open-source, self-hosted LMS for selling online courses, digital downloads, and building communities on your own branded website.

View details
63
Repo Health
74
Technical
67
Dependency
Built with
TypeScript 93%
Updated 1 weeks ago
TypeScript
97%
MIT

DenchClaw

AI Agents · CRM

1,660

An AI-native CRM you self-host on your own machine, built on the OpenClaw agent framework, with a DuckDB backend and pre-built agent skills for managing contacts, deals, reports, and 500+ outreach integrations from natural-language chat.

View details
47
Repo Health
73
Technical
71
Dependency
Built with
TypeScript 97%
Updated 4 months ago
Python
56%
Other

Dify

AI Development · Design Tools · Developer Tools

159,396

Visual LLM workflow platform with RAG pipelines, agent capabilities, and model management for building production AI applications.

View details
92
Repo Health
85
Technical
67
Dependency
Built with
Python 56%
TypeScript 42%
Updated 6 days ago
TypeScript
95%
AGPL 3.0

Docmost

CMS · Collaboration · Note Taking

22,079

Self-hosted collaborative wiki and knowledge base with real-time editing, diagrams, AI assistance, and enterprise access controls — a modern alternative to Confluence and Notion.

View details
89
Repo Health
70
Technical
66
Dependency
Built with
TypeScript 95%
Updated 6 days ago
Python
47%
MIT

Docs

CMS · File Storage

16,942

Open-source collaborative knowledge platform with real-time editing, AI writing tools, and full self-hosting control — built by the French and German governments.

View details
88
Repo Health
81
Technical
68
Dependency
Built with
Python 47%
TypeScript 46%
Updated 1 weeks ago

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers