Why You Should Not Use Classes in React Testing Library

Ferenc Almasi β€’ 2022 September 16 β€’ Read time 3 min read
  • twitter
  • facebook

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.

Copied to clipboard! Playground
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()
    })
})
Don't use class name for querying elements in React Testing Library

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.

Copied to clipboard! Playground
// βœ… 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.

Copied to clipboard! Playground
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.

Copied to clipboard! Playground
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')
    })
})
Testing for the presence or absence of class names

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.

11 Jest Best Practices to Get the Most Out of Your Tests
  • twitter
  • facebook
Did you find this page helpful?
πŸ“š More Webtips
Mentoring

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:

Courses

Recommended

This site uses cookies We use cookies to understand visitors and create a better experience for you. By clicking on "Accept", you accept its use. To find out more, please see our privacy policy.