DEV Community

Jen C.
Jen C.

Posted on

5 2 3 1

Jest - Testing with React and React Testing Library: Useful APIs

Resources

react-testing-library API

Firing Events

waitFor

About Queries

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} />);
    });

...

});
Enter fullscreen mode Exit fullscreen mode

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);
Enter fullscreen mode Exit fullscreen mode

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>
Enter fullscreen mode Exit fullscreen mode

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);
Enter fullscreen mode Exit fullscreen mode

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);
  });
Enter fullscreen mode Exit fullscreen mode

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);
  });
Enter fullscreen mode Exit fullscreen mode

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>
  );
}

Enter fullscreen mode Exit fullscreen mode

UserProfile.test.jsx

it('shows logout button after user is loaded', async () => {
  render(<UserProfile />);

  await waitFor(() => {
    expect(screen.getByText('Logout')).toBeInTheDocument();
  });
});
Enter fullscreen mode Exit fullscreen mode

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);
});
Enter fullscreen mode Exit fullscreen mode

DevCycle image

OpenFeature Multi-Provider: Enabling New Feature Flagging Use-Cases

DevCycle is the first feature management platform with OpenFeature built in. We pair the reliability, scalability, and security of a managed service with freedom from vendor lock-in, helping developers ship faster with true OpenFeature-native feature flagging.

Watch Full Video 🎥

Top comments (5)

Collapse
 
nevodavid profile image
Nevo David

Been needing a rundown like this for a minute, honestly makes me want to write some tests today.

Collapse
 
jenchen profile image
Jen C. • Edited

Thank you @nevodavid ! I just realized that I have starred the GitHub repo Novu a while ago. It's super cool :D

Collapse
 
dotallio profile image
Dotallio

Super useful overview, thanks for showing real examples! Do you have a favorite lesser-known trick for debugging with RTL?

Collapse
 
jenchen profile image
Jen C.

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., using toBeInTheDocument and not.toBeInTheDocument.

Here are some other nice resources:

If you have any tips, I'd really love to learn too!

Collapse
 
nathan_tarbert profile image
Nathan Tarbert

Pretty cool, I always pick up something new digging through these kinds of details.

AWS GenAI LIVE image

How is generative AI increasing efficiency?

Join AWS GenAI LIVE! to find out how gen AI is reshaping productivity, streamlining processes, and driving innovation.

Learn more

AWS Security LIVE! From re:Inforce 2025

Tune into AWS Security LIVE! streaming live from the AWS re:Inforce expo floor in Philadelphia from 8:00 AM ET-6:00 PM ET.

Tune in to the full event

DEV is partnering to bring live events to the community. Join us or dismiss this billboard if you're not interested. ❤️