Resources
Document: querySelector() method
render
Render into a container which is appended to document.body.
For example, render a component before each test and store the result in the renderResult
variable:
describe('<Card />', () => {
let renderResult = null;
const props = {
id: '1',
title: 'test title',
};
beforeEach(() => {
renderResult = render(<Card {...props} />);
});
...
});
Logging the HTML
If you want to see the actual HTML output of your component (as it would appear in the browser), you can log the innerHTML
of the container from the renderResult
like this:
console.log(renderResult.container.innerHTML);
Output
<div class="card__info">
<a class="card__txt-link" href="/video/1">
<div class="card__top">
<div class="card__title-wrapper">
<h3 class="card__title">test title</h3>
</div>
</div>
</a>
</div>
Get an element from the render result's container.
For example, use querySelector()
to select the first matching element by CSS selector:
expect(
contentRenderResult.container.querySelector('.detail-meta__studio')
.textContent
).toBe(props.studio);
rerender
Use when you need to update props, re-render the component, and verify the updated props are rendered correctly.
For example:
it('should render watermark if "watermark" prop is set', () => {
const getWatermark = (container) =>
container.querySelector('.card__watermark');
const waterMarkUrl = '/static/images/logo-water.svg';
let watermark = getWatermark(renderResult.container);
expect(watermark).not.toBeInTheDocument();
renderResult.rerender(
<Card
{...{
...props,
watermark: {
url: waterMarkUrl,
alt: 'water',
},
}}
/>
);
watermark = getWatermark(renderResult.container);
expect(watermark).toBeInTheDocument();
expect(watermark.querySelector('img')).toHaveAttribute('src', waterMarkUrl);
});
User Actions
fireEvent
For example, simulate a click on an element and check that the onClickItem
callback function is called:
const handleItemClick = jest.fn();
it('should trigger "onClickItem" prop when item is clicked', () => {
fireEvent.click(screen.getByRole('menuitem'));
expect(handleItemClick).toHaveBeenCalledTimes(1);
});
Note: Make sure handleItemClick
is passed as the onClickItem
prop to the component being tested. Otherwise, the callback won't be triggered.
waitFor
When you need to wait for something to either pass or fail.
For example, wait for the button to appear:
UserProfile.jsx
import { useEffect, useState } from 'react';
export default function UserProfile() {
const [user, setUser] = useState(null);
useEffect(() => {
// Simulate network request
setTimeout(() => {
setUser({ name: 'Alice' });
}, 500);
}, []);
return (
<div>
{user ? <button className="logout-button">Logout</button> : <p>Loading...</p>}
</div>
);
}
UserProfile.test.jsx
it('shows logout button after user is loaded', async () => {
render(<UserProfile />);
await waitFor(() => {
expect(screen.getByText('Logout')).toBeInTheDocument();
});
});
Queries
screen
DOM Testing Library also exports a screen object which has every query that is pre-bound to document.body
For example, check that the heading renders correctly:
it('renders the title heading correctly', () => {
expect(screen.getByRole('heading', { level: 1 })).toHaveTextContent(props.title);
});
Top comments (5)
Been needing a rundown like this for a minute, honestly makes me want to write some tests today.
Thank you @nevodavid ! I just realized that I have starred the GitHub repo Novu a while ago. It's super cool :D
Super useful overview, thanks for showing real examples! Do you have a favorite lesser-known trick for debugging with RTL?
Thank you @dotallio ! So far I like to log
container.innerHTML
to see what the rendered element looks like. Additionally, sometimes I test the opposite logic to ensure that things that are expected to be rendered get rendered, and things that shouldn't be rendered don't appear in the rendered output, e.g., usingtoBeInTheDocument
andnot.toBeInTheDocument
.Here are some other nice resources:
If you have any tips, I'd really love to learn too!
Pretty cool, I always pick up something new digging through these kinds of details.