How to Test Forwarding Refs in React
Testing components that use React’s forwardRef API
ensures that parent components can successfully access underlying DOM
nodes. This article provides a practical, straight-to-the-point guide on
how to test forwarded refs using Jest and React Testing Library,
demonstrating how to verify that a ref is correctly attached and
functional.
The Strategy for Testing Refs
To test a forwarding ref, you need to: 1. Create a ref object inside
your test using React.createRef(). 2. Pass that ref to the
component being tested. 3. Render the component. 4. Assert that
ref.current is not null and points to the correct HTML DOM
element.
Step-by-Step Code Example
Suppose you have a custom input component that forwards its ref to
the native <input> element:
// CustomInput.jsx
import React from 'react';
const CustomInput = React.forwardRef((props, ref) => {
return <input ref={ref} type="text" {...props} />;
});
CustomInput.displayName = 'CustomInput';
export default CustomInput;Here is how you write the test using Jest and React Testing Library:
// CustomInput.test.jsx
import React from 'react';
import { render } from '@testing-library/react';
import CustomInput from './CustomInput';
test('successfully forwards ref to the input element', () => {
// 1. Create a ref
const ref = React.createRef();
// 2. Render the component with the ref
render(<CustomInput ref={ref} placeholder="Enter text" />);
// 3. Assert the ref is attached to the correct DOM node
expect(ref.current).not.toBeNull();
expect(ref.current.tagName).toBe('INPUT');
expect(ref.current.placeholder).toBe('Enter text');
});Testing Ref Functionality
In addition to verifying that the ref points to the correct DOM node, you should test that the ref functions as expected, such as triggering focus.
test('allows focusing the element via the forwarded ref', () => {
const ref = React.createRef();
render(<CustomInput ref={ref} />);
// Trigger focus programmatically via the ref
ref.current.focus();
// Assert that the element is currently focused in the document
expect(document.activeElement).toBe(ref.current);
});