Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Best practice for testing for data-testid in a nested component with React Testing Library?

I'm trying to write a test to check if my app is rendering correctly. On the initial page Ive added a data-testid of "start". So my top level test checks that the initial component has been rendered.

import React from "react";
import { render } from "react-testing-library";
import App from "../App";

test("App - Check the choose form is rendered", () => {
  const wrapper = render(<App />);
  const start = wrapper.getByTestId("start");
  // console.log(start)
  // start.debug();
});

If I console.log(start) the I can see all the properties of the node. However if I try and debug() then it errors saying it's not a function.

My test above does seem to work. If I change the getByTestId from start to anything else then it does error. But I'm not using the expect function so am I violating best practices?

like image 725
Evanss Avatar asked Oct 17 '25 22:10

Evanss


1 Answers

There are two parts to this question -

Why console.log(start) works and why not start.debug()?

getByTestId returns an HTMLElement. When you use console.log(start), the HTMLElement details are logged. But an HTMLElement does not have debug function. Instead, react-testing-library provides you with a debug function when you use render to render a component. So instead of using start.debug(), you should use wrapper.debug().

Because you don't have an expect function, is it a good practice to write such tests ?

I am not sure about what could be a great answer to this, but I will tell the way I use it. There are two variants for getting an element using data-testid - getByTestId and queryByTestId. The difference is that getByTestId throws error if an element with the test id is not found whereas queryByTestId returns null in such case. This means that getByTestId in itself is an assertion for presence of element. So having another expect which checks if the element was found or not will be redundant in case you are using getByTestId. I would rather use queryByTestId if I am to assert the presence/absence of an element. Example below -

test("App - Check the "Submit" button is rendered", () => {
 const { queryByTestId } = render(<App />)
 expect(queryByTestId('submit')).toBeTruthy()
});

I would use getByTestId in such tests where I know that the element is present and we have expects for the element's properties (not on the element's presence/absence). Example below -

test("App - Check the "Submit" button is disabled by default", () => {
 const { getByTestId } = render(<App />)
 expect(getByTestId('submit')).toHaveClass('disabled')
});

In the above test, if getByTestId is not able to find the submit button, it fails by throwing an error, and does not execute the toHaveClass. Here we don't need to test for presence/absence of the element, as this test is concerned only with the "disabled" state of the button.

like image 120
Manish Avatar answered Oct 19 '25 17:10

Manish