Get by HTML element with React Testing Library?

Solution 1:

I'm not sure what wrapper is in this case. But to answer your two questions: yes it's possible to get by HTML element and no, it's not advisable.

This is how you would do it:

// Possible but not advisable
const { container } = render(<MyComponent />)
// `container` is just a DOM node
const button = container.querySelector('button')

Since you get back a DOM node you can use all the normal DOM APIs such as querySelector.

Now, why is this not advisable. A big selling point of react-testing-library is that you test your components as a user does. This means not relying on implementation details. For instance, you don't have direct access to a component's state.

Writing tests this way is a bit harder but allows you to write more robust tests.

In your case, I would argue that the underlying HTML is an implementation detail. What happens if you change your HTML structure so that the h1 is now an h2 or a div? The test will break. If instead, you look at these elements by text the tag becomes irrelevant.

In some cases, the normal query helpers are not enough. For those events you can use a data-testid and use getByTestId.

Solution 2:

Depending on the type of element you're querying for, you might also find the byRole API to be useful:

https://testing-library.com/docs/queries/byrole/

For example, the level was particularly useful for me to test that default <h1> elem was correctly being overridden:

it('correctly renders override header level', () => {
  const { getByRole } = render(<Heading overrideHeadingLevel="h6" />)

  expect(getByRole('heading', { level: 6 })).toBeInTheDocument()
})