Testing Components with React Testing Library in React JS

React Testing Library (RTL) is a popular testing library for React applications. It focuses on testing components from the perspective of the user by emphasizing interactions and rendered output rather than internal implementation details.

Why Use React Testing Library?

  • Provides utilities to test components the way users interact with them.
  • Encourages testing accessibility and user flows.
  • Integrates seamlessly with Jest for assertions and mocking.

Setting Up React Testing Library

If you're using Create React App (CRA), React Testing Library is already set up. For a custom setup, install it using:

  npm install @testing-library/react @testing-library/jest-dom
      

Example 1: Testing Static Component Rendering

The example below tests if a component renders correctly:

  
  // Welcome.js
  import React from 'react';

  function Welcome({ user }) {
      return 

Welcome, {user || 'Guest'}!

; } export default Welcome;
  
  // Welcome.test.js
  import { render, screen } from '@testing-library/react';
  import Welcome from './Welcome';

  test('renders welcome message for a guest', () => {
      render();
      expect(screen.getByText('Welcome, Guest!')).toBeInTheDocument();
  });

  test('renders welcome message for a user', () => {
      render();
      expect(screen.getByText('Welcome, John!')).toBeInTheDocument();
  });
  
      

Example 2: Testing User Interactions

The following example tests a component with user interaction:

  
  // Counter.js
  import React, { useState } from 'react';

  function Counter() {
      const [count, setCount] = useState(0);

      return (
          

Count: {count}

); } export default Counter;
  
  // Counter.test.js
  import { render, screen, fireEvent } from '@testing-library/react';
  import Counter from './Counter';

  test('increments the count when the button is clicked', () => {
      render();
      const button = screen.getByText('Increment');
      fireEvent.click(button);
      expect(screen.getByText('Count: 1')).toBeInTheDocument();
  });
  
      

Example 3: Testing Form Submissions

The example below tests form submission with a mocked function:

  
  // LoginForm.js
  import React, { useState } from 'react';

  function LoginForm({ onSubmit }) {
      const [username, setUsername] = useState('');

      const handleSubmit = (e) => {
          e.preventDefault();
          onSubmit(username);
      };

      return (
          
setUsername(e.target.value)} />
); } export default LoginForm;
  
  // LoginForm.test.js
  import { render, screen, fireEvent } from '@testing-library/react';
  import LoginForm from './LoginForm';

  test('submits the form with the correct username', () => {
      const mockSubmit = jest.fn();
      render();
      
      const input = screen.getByPlaceholderText('Enter username');
      const button = screen.getByText('Login');
      
      fireEvent.change(input, { target: { value: 'testuser' } });
      fireEvent.click(button);
      
      expect(mockSubmit).toHaveBeenCalledWith('testuser');
  });
  
      

Example 4: Testing Asynchronous Behavior

RTL provides utilities for testing asynchronous code. Here’s an example:

  
  // FetchData.js
  import React, { useEffect, useState } from 'react';

  function FetchData() {
      const [data, setData] = useState(null);

      useEffect(() => {
          fetch('https://jsonplaceholder.typicode.com/posts/1')
              .then((response) => response.json())
              .then((data) => setData(data));
      }, []);

      return (
          
{data ?

{data.title}

:

Loading...

}
); } export default FetchData;
  
  // FetchData.test.js
  import { render, screen, waitFor } from '@testing-library/react';
  import FetchData from './FetchData';

  global.fetch = jest.fn(() =>
      Promise.resolve({
          json: () => Promise.resolve({ title: 'Test Post' }),
      })
  );

  test('renders fetched data after loading', async () => {
      render();
      expect(screen.getByText('Loading...')).toBeInTheDocument();
      await waitFor(() => expect(screen.getByText('Test Post')).toBeInTheDocument());
  });
  
      

Best Practices for Testing with React Testing Library

  • Focus on testing user behavior and outcomes.
  • Use accessible queries like getByText, getByRole, or getByLabelText.
  • Mock API calls and external dependencies to isolate components.
  • Write meaningful test descriptions to explain test intent.

React Testing Library encourages best practices by focusing on user experience and interactions. By using the examples and guidelines provided, you can effectively test components in your React applications.





Advertisement