Why You Should Not Use Classes in React Testing Library

Ferenc Almasi • 2022 September 16 • 📖 3 min read

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

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) 
    })
})
Copied to clipboard!

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.

Looking to improve your skills? Check out our interactive course to master JavaScript from start to finish.
JavaScript Course

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()
    })
})
Copied to clipboard!

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

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
JavaScript Course Dashboard

Tired of looking for tutorials?

You are not alone. Webtips has more than 400 tutorials which would take roughly 75 hours to read.

Check out our interactive course to master JavaScript in 5 hours.

Learn More

📚 Get access to exclusive content

Want to get access to exclusive content? Support webtips with the price of a coffee to get access to tips, checklists, cheatsheets, and much more. ☕

Get access Support us
Read more on
🎉 Thank you for subscribing to our newsletter. x