Custom Jest matchers for testing React components with Enzyme
—
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Pending
The risk profile of this skill
Jest 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