DEV Community

jozsefDevs
jozsefDevs

Posted on

Top 3 React Testing Library mistakes I should have spotted earlier πŸš€

There are a few mistakes that are incredibly easy to make in React Testing Library and I wish I'd watched out for these earlier. Recently I've fixed hundreds of these in a more extensive code base, so just making a remark here. Watch out for these!

1 - Await on synchronous queries

// ❌ Incorrect code ❌
await screen.getByTestId('menu') // check for existence

// ❌ Incorrect code ❌
const banner = await screen.queryByTestId('banner')
expect(banner).not.toBeInDocument() // check for non-existence
Enter fullscreen mode Exit fullscreen mode

Here the problem is that we're awaiting on methods that are synchronous by default.

// βœ… Correct code
screen.getByTestId('menu') // check for existence

// βœ… Correct code
const banner = screen.queryByTestId('banner')
expect(banner).not.toBeInDocument() // check for non-existence
Enter fullscreen mode Exit fullscreen mode

πŸ’‘ Remember, getBy..., queryBy..., getAllBy..., queryAllBy... methods are synchronous. Meaning they're only useful, if your component already rendered elements you want to find. (Probably not a good idea to use these, if your component is making a network request to get the data and just renders after.)

πŸ’‘ Check out this related eslint-plugin rule

2 - Not awaiting on asynchronous queries πŸ™€

This problem is the inverse of the previous one. πŸ™ˆ

So let's say your component is only rendered after fetching some network data. In this case, synchronous methods are not helping, because they won't wait for the data to be rendered. In these cases you'll need to use findBy.../findAllBy...

However there is a problem with the code below ⬇️

// ❌ Incorrect code ❌
screen.findByTestId('menu') // check for existence
Enter fullscreen mode Exit fullscreen mode

Yep, there is no await used here. This findBy... call gives us back a promise, because it's always async.

// βœ… Correct code
await screen.findByTestId('menu') // check for existence
Enter fullscreen mode Exit fullscreen mode

πŸ’‘ Please always await findBy..., findAllBy... queries.

πŸ’‘ Check out this related eslint-plugin rule

As an extra takeaway task, I leave this here for you to find out why this one will always get us fake results. πŸ™ˆ

// ❌ Incorrect code ❌
expect(screen.findByTestId('menu')) // -> psst.. this will always pass
Enter fullscreen mode Exit fullscreen mode

3 - Using queryBy.. to check existence

Okay, so we can easily decide when to use sync or async methods, but how about this one?

// ❌ Incorrect code ❌
expect(screen.queryByText('A title')).toBeInTheDocument();    
Enter fullscreen mode Exit fullscreen mode

As per documentation, queryBy..

returns the matching node for a query, and return null if no elements match. This is useful for asserting an element that is not present.

πŸ’‘ Please only use queryBy..., queryAllBy... queries when you want to check that an element is NOT present.

πŸ’‘ Check out this related eslint-plugin rule

// βœ… Correct code
expect(screen.queryByText('A title')).not.toBeInTheDocument()
Enter fullscreen mode Exit fullscreen mode

+1 - Use React Testing Library eslint plugins

You might have noticed already that I've included the related eslint-plugin rules for all the mentioned problems. I love automating rules because they're ensuring good code quality and consistency within the team.

🚨🚨 You must install eslint-plugin-testing-library and eslint-plugin-jest-dom if you're working heavily with RTL in your project.

If you have already a lot of tests (which you should πŸ™ˆ) eslint won't go easy on you after installing these plugins. However it worth fixing every recommendation it has πŸ’ͺ

Happy testing!

Reference: Common mistakes with React Testing Library

Top comments (0)