Custom Jest matchers for testing React components with Enzyme
npx @tessl/cli install tessl/npm-jest-enzyme@7.1.0Jest Enzyme provides custom Jest matchers for testing React components with Enzyme. It extends Jest's assertion capabilities with enzyme-specific matchers, making React component testing more intuitive and readable by providing domain-specific assertions that understand Enzyme wrapper objects.
npm install jest-enzymeThe package functions as a Jest setupFilesAfterEnv script and extends Jest's expect function automatically:
// package.json
"jest": {
"setupFilesAfterEnv": ["./node_modules/jest-enzyme/lib/index.js"]
}For TypeScript support:
// src/setupTests.ts
import 'jest-enzyme';import React from 'react';
import { mount } from 'enzyme';
function MyComponent({ checked, disabled, className }) {
return (
<div className={className}>
<input type="checkbox" defaultChecked={checked} disabled={disabled} />
<span>Hello World</span>
</div>
);
}
const wrapper = mount(<MyComponent checked={true} className="test-class" />);
// Use jest-enzyme matchers
expect(wrapper.find('input')).toBeChecked();
expect(wrapper.find('input')).not.toBeDisabled();
expect(wrapper).toHaveClassName('test-class');
expect(wrapper.find('span')).toHaveText('Hello World');Jest Enzyme is built around several key components:
Matchers for testing element state conditions like checked, disabled, and existence.
// Assert that input element is checked
expect(wrapper).toBeChecked(): void;
// Assert that element is disabled
expect(wrapper).toBeDisabled(): void;
// Assert that component renders null or false
expect(wrapper).toBeEmptyRender(): void;
// Assert that element exists in the wrapper
expect(wrapper).toExist(): void;Usage Examples:
const wrapper = mount(
<div>
<input id="checked" defaultChecked />
<input id="disabled" disabled />
<input id="normal" />
</div>
);
expect(wrapper.find('#checked')).toBeChecked();
expect(wrapper.find('#disabled')).toBeDisabled();
expect(wrapper.find('#normal')).toExist();
expect(wrapper.find('#nonexistent')).not.toExist();Matchers for testing element content including text, HTML, and CSS classes.
// Assert element has specific CSS class
expect(wrapper).toHaveClassName(className: string): void;
// Assert component has specific display name
expect(wrapper).toHaveDisplayName(tagName: string): void;
// Assert element has specific HTML content
expect(wrapper).toHaveHTML(html: string): void;
// Assert element has specific tag name (deprecated - use toHaveDisplayName)
expect(wrapper).toHaveTagName(tagName: string): void;
// Assert element has specific text content (exact match)
expect(wrapper).toHaveText(text: string): void;
// Assert element includes specific text (partial match)
expect(wrapper).toIncludeText(text: string): void;
// Assert form element has specific value
expect(wrapper).toHaveValue(value: any): void;Usage Examples:
const wrapper = mount(
<div className="container active">
<span id="greeting">Hello World</span>
<input type="text" defaultValue="test input" />
</div>
);
expect(wrapper).toHaveClassName('container');
expect(wrapper).toHaveClassName('active');
expect(wrapper.find('#greeting')).toHaveText('Hello World');
expect(wrapper.find('#greeting')).toIncludeText('Hello');
expect(wrapper.find('input')).toHaveValue('test input');
expect(wrapper.find('#greeting')).toHaveHTML('<span id="greeting">Hello World</span>');Matchers for testing component props, state, styles, and refs.
// Assert element has specific prop with optional value check
expect(wrapper).toHaveProp(propKey: object|string, propValue?: any): void;
// Assert element has specific ref
expect(wrapper).toHaveRef(refName: string): void;
// Assert component has specific state with optional value check
expect(wrapper).toHaveState(stateKey: object|string, stateValue?: any): void;
// Assert element has specific CSS style property
expect(wrapper).toHaveStyle(styleKey: object|string, styleValue?: any): void;Usage Examples:
function TestComponent({ title, count }) {
const [active, setActive] = React.useState(true);
return <div ref="container" style={{ color: 'red' }} title={title} />;
}
const wrapper = mount(<TestComponent title="Test" count={5} />);
expect(wrapper).toHaveProp('title', 'Test');
expect(wrapper).toHaveProp('count');
expect(wrapper).toHaveProp({ title: 'Test', count: 5 });
expect(wrapper).toHaveState('active', true);
expect(wrapper).toHaveState({ active: true });
expect(wrapper).toHaveStyle('color', 'red');
expect(wrapper).toHaveStyle({ color: 'red' });
expect(wrapper).toHaveRef('container');Matchers for testing element presence and React element matching.
// Assert wrapper contains at least one element matching selector
expect(wrapper).toContainMatchingElement(selector: string): void;
// Assert wrapper contains exactly n elements matching selector
expect(wrapper).toContainMatchingElements(n: number, selector: string): void;
// Assert wrapper contains exactly one element matching selector
expect(wrapper).toContainExactlyOneMatchingElement(selector: string): void;
// Assert wrapper contains specific React element
expect(wrapper).toContainReact(component: React.ReactElement<any>): void;
// Assert wrapper matches specific React element structure
expect(wrapper).toMatchElement(
element: React.ReactElement<any>,
options?: ToMatchElementOptions
): void;
// Assert element matches CSS selector
expect(wrapper).toMatchSelector(selector: string): void;Usage Examples:
function User({ id, name }) {
return <span className={`user-${id}`}>{name}</span>;
}
const wrapper = mount(
<div>
<User id={1} name="Alice" />
<User id={2} name="Bob" />
<span className="info">Info text</span>
</div>
);
expect(wrapper).toContainMatchingElement('.user-1');
expect(wrapper).toContainMatchingElements(2, 'User');
expect(wrapper).toContainExactlyOneMatchingElement('.info');
expect(wrapper).toContainReact(<User id={1} name="Alice" />);
expect(wrapper.find('User').first()).toMatchElement(<User />);
expect(wrapper.find('.user-1')).toMatchSelector('.user-1');declare namespace jest {
interface ToMatchElementOptions {
ignoreProps?: boolean;
}
interface Matchers<R, T> {
// Element State Matchers
toBeChecked(): void;
toBeDisabled(): void;
toBeEmptyRender(): void;
toExist(): void;
// Element Content Matchers
toHaveClassName(className: string): void;
toHaveDisplayName(tagName: string): void;
toHaveHTML(html: string): void;
toHaveTagName(tagName: string): void;
toHaveText(text: string): void;
toIncludeText(text: string): void;
toHaveValue(value: any): void;
// Element Properties Matchers
toHaveProp(propKey: object|string, propValue?: any): void;
toHaveRef(refName: string): void;
toHaveState(stateKey: object|string, stateValue?: any): void;
toHaveStyle(styleKey: object|string, styleValue?: any): void;
// Element Matching Matchers
toContainMatchingElement(selector: string): void;
toContainMatchingElements(n: number, selector: string): void;
toContainExactlyOneMatchingElement(selector: string): void;
toContainReact(component: React.ReactElement<any>): void;
toMatchElement(
element: React.ReactElement<any>,
options?: ToMatchElementOptions
): void;
toMatchSelector(selector: string): void;
}
}Jest Enzyme provides multiple setup options to integrate with your testing environment:
The recommended approach uses the dedicated Jest environment that automatically configures enzyme globals and jest-enzyme matchers:
// package.json
"jest": {
"testEnvironment": "enzyme",
"testEnvironmentOptions": {
"enzymeAdapter": "react16"
}
}For projects that prefer to configure setup files manually:
// package.json
"jest": {
"setupFilesAfterEnv": ["./node_modules/jest-enzyme/lib/index.js"]
}For Create React App projects, add the import to your test setup file:
// src/setupTests.js
import 'jest-enzyme';For TypeScript projects, create a setup file and configure Jest to use it:
// src/setupTests.ts
import 'jest-enzyme';// package.json
"jest": {
"setupFilesAfterEnv": ["./src/setupTests.ts"]
}Different matchers support different Enzyme rendering methods:
| Matcher | render | mount | shallow |
|---|---|---|---|
| toBeChecked | no | yes | yes |
| toBeDisabled | no | yes | yes |
| toBeEmptyRender | no | yes | yes |
| toExist | no | yes | yes |
| toContainMatchingElement | no | yes | yes |
| toContainMatchingElements | no | yes | yes |
| toContainExactlyOneMatchingElement | no | yes | yes |
| toContainReact | no | yes | yes |
| toHaveClassName | no | yes | yes |
| toHaveDisplayName | no | yes | yes |
| toHaveHTML | no | yes | yes |
| toHaveProp | no | yes | yes |
| toHaveRef | no | yes | yes |
| toHaveState | no | yes | yes |
| toHaveStyle | no | yes | yes |
| toHaveTagName | no | yes | yes |
| toHaveText | no | yes | yes |
| toIncludeText | no | yes | yes |
| toHaveValue | no | yes | yes |
| toMatchElement | no | yes | yes |
| toMatchSelector | no | yes | yes |
All matchers provide:
.not usage