React testing library: Common mistakes you should know to avoid these pitfalls

React Testing Library is certainly created with a view to testing the patterns between each scenario in every eCommerce business ever. This can be a controversial subject, largely due to the multitude of ways one can go about writing a test. There are no clear rules, instead, you are the one in charge of deciding what’s worth testing and how you’re going to do it. As time has gone on, some small changes to the API are made as a result.

However, the changes always come along with mistakes. Despite all the efforts that have been conducted in order to minimize these pitfalls, we still see blog posts and tests written following these suboptimal patterns. So now, we – ArrowHiTech would like to introduce to you guys some common mistakes of the React testing library. After that, you can be able to avoid the pitfalls without hesitation. Let’s go!

Mistake #1. Using wrapper when shows the variable name for the return value from render

 // ❌
 const wrapper = render(<Example prop="1" />)
 wrapper.rerender(<Example prop="2" />)
 // ✅
 const {rerender} = render(<Example prop="1" />)
 rerender(<Example prop="2" />) 

So, the name wrapper is old cruft from enzyme and we don’t need that here. Also, the return value from render is not “wrapping” anything. It’s certainly a collection of utilities that you should actually not often need anyway.

Mistake #2. Adding aria-, role, and other accessibility attributes incorrectly in React testing library

 // ❌
 render(<button role="button">Click me</button>)
 // ✅
 render(<button>Click me</button>) 

Slapping accessibility attributes willy nilly is not only unnecessary (as in the case above), but it can also confuse screen readers and their users. The accessibility of React testing library attributes should really only be used when semantic HTML doesn’t satisfy your use case (like if you’re building a non-native UI that you want to make accessible as an autocomplete).

Mistake #3. Not using @testing-library/user-event for React testing library

 // ❌
 fireEvent.change(input, {target: {value: 'hello world'}})
 // ✅
 userEvent.type(input, 'hello world') 

@testing-library/user-event is obviously a package that’s built on top of fireEvent. It also provides several methods that resemble user interactions more closely. So in the example above, fireEvent.change will simply trigger a single change event on the input. However the type call will trigger keyDown, keyPress, and keyUp events for each character as well. As a result, it’s much closer to the user’s actual interactions. 

Mistake #4. Using query* variants for anything except checking for non-existence

 // ❌
 expect(screen.queryByRole('alert')).toBeInTheDocument()
 // ✅
 expect(screen.getByRole('alert')).toBeInTheDocument()
 expect(screen.queryByRole('alert')).not.toBeInTheDocument() 

To clarify, the only reason the query* variant of the queries is exposed is for you to have a function you can call. This, as a result, does not throw an error if no element is found to match the query. Also, the only reason this is useful for the React testing library is to verify that an element is not rendered to the page.

Mistake #5. Performing side-effects of React testing library in waitFor

 // ❌
 await waitFor(() => {
   fireEvent.keyDown(input, {key: 'ArrowDown'})
   expect(screen.getAllByRole('listitem')).toHaveLength(3)
 })
 // ✅
 fireEvent.keyDown(input, {key: 'ArrowDown'})
 await waitFor(() => {
   expect(screen.getAllByRole('listitem')).toHaveLength(3)
 }) 

waitFor is certainly intended for things that have a non-deterministic amount of time between the action you performed and the assertion passing. Because of this, the callback can be called (or checked for errors) a non-deterministic number of times and frequency. So this means that your side-effect could run multiple times on your React testing library. This also means that you can’t use snapshot assertions within waitFor.

Mistake #6. Wrapping things when using act unnecessarily

 // ❌
 act(() => {
   render(<Example />)
 })
 const input = screen.getByRole('textbox', {name: /choose a fruit/i})
 act(() => {
   fireEvent.keyDown(input, {key: 'ArrowDown'})
 })
 // ✅
 render(<Example />)
 const input = screen.getByRole('textbox', {name: /choose a fruit/i})
 fireEvent.keyDown(input, {key: 'ArrowDown'}) 

A lot of people wrapping things like this because they see these “act” warnings all the time and are just trying anything they can to get them to go away. However, what they don’t know is that render and fireEvent are already wrapped in the act. So those are doing nothing useful. Most of the time, if you’re seeing an act warning, then it’s not just something to be silenced. However, it’s actually telling you that something unexpected is happening in your React testing library.

Mistake #7. Using the wrong query when using React testing library

 // ❌
 // assuming you've got this DOM to work with:
 // <label>Username</label><input data-testid="username" />
 screen.getByTestId('username')
 // ✅
 // change the DOM to be accessible by associating the label and setting the type
 // <label for="username">Username</label><input id="username" type="text" />
 screen.getByRole('textbox', {name: /username/i}) 

You obviously should attempt to use it in the order you should attempt to use them. If your goal is aligned with tests that give you confidence that your app will work, then you’ll want to query the DOM as closely to the way your end-users do so as possible. The queries help you do this, but not all queries are created equally on the React testing library.

Mistake #8. Using get* variants as assertions

 // ❌
 screen.getByRole('alert', {name: /error/i})
 // ✅
 expect(screen.getByRole('alert', {name: /error/i})).toBeInTheDocument() 

This one’s not really a big deal actually, however, we should mention this. If get* queries are unsuccessful in finding the element, obviously they’ll throw a really helpful error message. That shows you the full DOM structure which will help you during debugging. Because of this, the assertion could never possibly fail. The queries of the React testing library will throw before the assertion has a chance to.

Final words

That should be it! To conclude, here are some of the most common mistakes that you should know about the React testing library that you need to avoid. Throughout this article, we hope that you guys can possibly know about these common mistakes so that you can avoid them without hesitation. As a result, you will be more successful at shipping your software with confidence.

Are you looking for the best React development services for your business? So let’s check it out awesome services at ArrowHiTech Website. Our experience experts will help you to gain the successful project. Besides that, if you have any questions, let’s leave them into this CONTACT FORM. We will reply you as soon as possible.

>>> Read more:

React native calendar: Simple steps to create this component

React Native development environment: Useful tips to set it up in Windows

Tags

Share