Published on

Testing Your React App

Authors
  • Name
    Twitter

In this blog post, we'll explore how to write tests for your React application using popular testing libraries such as Jest and React Testing Library.

Setting Up Your React Project

Before we dive into writing tests, let's set up a basic React project. Here is the structure of our project:

├── node_modules
├── public
│   ├── index.html
├── src
│   ├── components
│   │   ├── App.js
│   │   ├── App.test.js
│   ├── index.js
├── package.json
└── yarn.lock

Installing Testing Libraries

We will use Jest for running our tests and React Testing Library for testing our components. Let's install these libraries:

yarn add --dev jest @testing-library/react @testing-library/jest-dom

Writing Your First Test

Let's start by creating a simple component in src/components/App.js.

import React from 'react'

const App = () => {
  return (
    <div>
      <h1>Hello, World!</h1>
    </div>
  )
}

export default App

Now, let's write a test for the App component in src/components/App.test.js.

import React from 'react'
import { render, screen } from '@testing-library/react'
import '@testing-library/jest-dom/extend-expect'
import App from './App'

test('renders Hello, World!', () => {
  render(<App />)
  const headingElement = screen.getByText(/Hello, World!/i)
  expect(headingElement).toBeInTheDocument()
})

Running Your Tests

To run your tests, you can use the yarn test command:

yarn test

If everything is set up correctly, you should see an output indicating that the test passed.

PASS  src/components/App.test.js
  ✓ renders Hello, World! (xms)

Testing User Interactions

React Testing Library makes it easy to test user interactions. Let's add a button to our App component and test its functionality.

Update src/components/App.js:

import React, { useState } from 'react'

const App = () => {
  const [count, setCount] = useState(0)

  return (
    <div>
      <h1>Hello, World!</h1>
      <p>Count: {count}</p>
      <button onClick={() => setCount(count + 1)}>Increment</button>
    </div>
  )
}

export default App

Update src/components/App.test.js:

import React from 'react'
import { render, screen, fireEvent } from '@testing-library/react'
import '@testing-library/jest-dom/extend-expect'
import App from './App'

test('renders Hello, World!', () => {
  render(<App />)
  const headingElement = screen.getByText(/Hello, World!/i)
  expect(headingElement).toBeInTheDocument()
})

test('increments count when button is clicked', () => {
  render(<App />)
  const buttonElement = screen.getByText(/Increment/i)
  fireEvent.click(buttonElement)
  const countElement = screen.getByText(/Count: 1/i)
  expect(countElement).toBeInTheDocument()
})

Testing Asynchronous Code

Sometimes, you need to test components that handle asynchronous operations. React Testing Library provides utilities for this as well. Let's add an asynchronous operation to our App component.

Update src/components/App.js:

import React, { useState } from 'react'

const App = () => {
  const [count, setCount] = useState(0)
  const [data, setData] = useState(null)

  const fetchData = async () => {
    const response = await fetch('https://jsonplaceholder.typicode.com/todos/1')
    const result = await response.json()
    setData(result)
  }

  return (
    <div>
      <h1>Hello, World!</h1>
      <p>Count: {count}</p>
      <button onClick={() => setCount(count + 1)}>Increment</button>
      <button onClick={fetchData}>Fetch Data</button>
      {data && <p>{data.title}</p>}
    </div>
  )
}

export default App

Update src/components/App.test.js:

import React from 'react'
import { render, screen, fireEvent, waitFor } from '@testing-library/react'
import '@testing-library/jest-dom/extend-expect'
import App from './App'

test('renders Hello, World!', () => {
  render(<App />)
  const headingElement = screen.getByText(/Hello, World!/i)
  expect(headingElement).toBeInTheDocument()
})

test('increments count when button is clicked', () => {
  render(<App />)
  const buttonElement = screen.getByText(/Increment/i)
  fireEvent.click(buttonElement)
  const countElement = screen.getByText(/Count: 1/i)
  expect(countElement).toBeInTheDocument()
})

test('fetches and displays data', async () => {
  render(<App />)
  const buttonElement = screen.getByText(/Fetch Data/i)
  fireEvent.click(buttonElement)
  const dataElement = await waitFor(() => screen.getByText(/delectus aut autem/i))
  expect(dataElement).toBeInTheDocument()
})

Conclusion

Testing is a crucial part of developing robust React applications. By writing tests for your components, you can ensure that your application behaves as expected and catches bugs early in the development process. We covered the basics of writing and running tests in React using Jest and React Testing Library, including testing user interactions and asynchronous operations. Happy testing!