I'm using the getByTestId
function in React Testing Library:
const button = wrapper.getByTestId("button");
expect(heading.textContent).toBe("something");
Is it possible / advisable to search for HTML elements instead? So something like this:
const button = wrapper.getByHTML("button");
const heading = wrapper.getByHTML("h1");
I found a way to do this. import App from './App'; import { render, queryByAttribute } from 'react-testing-library'; const getById = queryByAttribute. bind(null, 'id'); const dom = render(<App />); const table = getById(dom. container, 'directory-table');
To find elements by className in React testing library: Render a component and destructure the container object from the result. Use the getElementsByClassName() method on the container to find elements by class name.
When writing snapshot tests for a React component, you first need to have code in a working state. Then, generate a snapshot of its expected output given certain data. The snapshot tests are committed alongside the component. Jest, a testing framework, will compare the snapshot to the rendered output for the test.
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
.
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()
})
another possible solution
consider rendering your component.
render(<ReactComponent />);
const button = screen.getByText((content, element) => element.tagName.toLowerCase() === 'button');
and if you have multiple buttons use getAllByText
and refer to the target element you need to pick.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With