Why You Should Not Use Classes in React Testing Library
You might be tempted to query elements by their class name in React Testing Library to test their presence. However, this approach is strongly discouraged.
import React from 'react'
import { render } from '@testing-library/react'
import { Component } from '@components'
// π΄ Don't
describe('Selectors', () => {
it('should query the element by its className', () => {
const { container } = render(<Component />)
const domElement = container.getElementsByClassName('container')[0]
expect(domElement).toBeInTheDocument()
})
})
Instead of using class names for querying elements, use selectors provided by React Testing Library, such as getByTestId
, getByText
, or getByRole
. React Testing Library does not have a built-in way to select elements by class names for a reason.
// β
Do
describe('Selectors', () => {
it('should query the element by its className', () => {
render(<Component />)
expect(screen.getByTestId('element')).toBeInTheDocument() // Using data-testid attribute
expect(screen.getByText('content')).toBeInTheDocument() // Using text content
expect(screen.getByRole('button')).toBeInTheDocument() // Using the node type
// Use getAllBy for multiple elements
expect(screen.getAllByTestId('element')).toHaveLength(3)
expect(screen.getAllByText('content')).toHaveLength(3)
expect(screen.getAllByRole('button')).toHaveLength(3)
})
})
For using getByTestId
, you first want to define a data-testid
property on your element.
Class names are an implementation detail that can make your unit test suite less resilient. If the class name changes but the functionality remain the same, your tests will need to be updated, otherwise, they will fail.
If you are using Tailwind, your queries also won't be descriptive in your test cases, meaning it's hard to tell what is the purpose of the queried element.
describe('Selectors', () => {
it('should query the element by its className', () => {
const { container } = render(<Component />)
// β What is the purpose of this element? What are we querying exactly?
const domElement = container.getElementsByClassName('md:max-w-screen-xl')[0]
expect(domElement).toBeInTheDocument()
})
})
If you specifically need to test the existence of class names on an element, you can do so by using a toHaveClass
assertion. However, you should avoid querying elements by their class names or ids.
describe('Selectors', () => {
it('should query the element by its className', () => {
render(<Component />)
expect(screen.getByTestId('element')).toHaveClass('open')
expect(screen.getByTestId('element')).not.toHaveClass('closed')
})
})
If you are interested in more unit test best practices to get the best out of your test suite, make sure you have a look at the article below.
Rocket Launch Your Career
Speed up your learning progress with our mentorship program. Join as a mentee to unlock the full potential of Webtips and get a personalized learning experience by experts to master the following frontend technologies: