Testing React Components with Jest: A Simple Guide 🚀

Pavan Kumar
3 min readSep 23, 2024

--

Why Test Your Code? 🤔

Before we jump into the technical stuff, let’s answer the big question:

Why test your code? Testing ensures your app doesn’t crash or behave unexpectedly. It helps catch bugs early and keeps your users happy. 😊

Imagine building a house without checking if the walls are stable. 🏠 Testing is like making sure every brick in your app is solid!

Meet Our Component: Email Signup ✉️

Here’s the deal: we have a React component called EmailSignup. It lets users enter their email and, when they hit “Submit”, the app does its magic. ✨ But how do we make sure this magic works? We test it!

What Are We Testing? 📝

For our EmailSignup component, we’ll test:

  1. The initial state: Does it show the correct text when the page loads?
  2. If the email from the URL shows up in the input field.
  3. If it properly handles a loading state (when the form is submitting).
  4. If it shows an error message when something goes wrong.
  5. If it sends the right information when the user submits the form

Tools We’ll Use 🛠️

  • Jest: A testing framework that lets us write and run tests.
  • React Testing Library: A set of helpers that lets us interact with React components like a user would.

We’ll also mock some hooks like useRouter (for simulating URL queries) and useDispatch (for simulating Redux actions).

The Test Code 🖥️

Let’s take a look at our test cases! 🚀 Don’t worry if you’re not a coding expert — I’ll explain each step along the way.

import React from 'react';
import { render, screen, fireEvent } from '@testing-library/react';
import '@testing-library/jest-dom';
import EmailSignup from './EmailSignup';
import { useRouter } from 'next/router';
import { useDispatch } from 'react-redux';
import useDevice from './useDevice';

// Mocking hooks
jest.mock('next/router', () => ({
useRouter: jest.fn(),
}));
jest.mock('react-redux', () => ({
useDispatch: jest.fn(),
}));
jest.mock('./useDevice', () => jest.fn());

describe('EmailSignup Component', () => {
let mockRouter, mockDispatch, mockDevice;

beforeEach(() => {
mockRouter = { query: {} }; // Fake router data
mockDispatch = jest.fn(); // Fake dispatch function
mockDevice = 'desktop'; // Fake device context

useRouter.mockReturnValue(mockRouter);
useDispatch.mockReturnValue(mockDispatch);
useDevice.mockReturnValue(mockDevice);
});

test('renders with initial state', () => {
render(<EmailSignup />); // Render the component

expect(screen.getByPlaceholderText(/enter your email/i)).toBeInTheDocument();
expect(screen.getByText(/Please check your email/i)).toBeInTheDocument();
});

test('uses email from router query if available', () => {
mockRouter.query = { email: 'test@example.com' };
render(<EmailSignup />);

const emailInput = screen.getByPlaceholderText(/enter your email/i);
expect(emailInput.value).toBe('test@example.com');
});

test('handles loading state', () => {
render(<EmailSignup />);
const submitButton = screen.getByRole('button', { name: /submit/i });

fireEvent.click(submitButton); // Simulate a click on the submit button

expect(screen.getByRole('button')).toBeDisabled(); // Check if the button is disabled
});

test('dispatches action on successful submit', () => {
mockRouter.query = { email: 'test@example.com' };
render(<EmailSignup />);

fireEvent.click(screen.getByRole('button', { name: /submit/i }));

expect(mockDispatch).toHaveBeenCalledTimes(1); // Ensure dispatch was called
expect(mockDispatch).toHaveBeenCalledWith({
type: 'SIGNUP',
payload: { email: 'test@example.com' },
});
});
});

Breaking Down the Tests 🛠️

Let’s break down what’s happening:

  1. Mocking: We use Jest’s jest.mock() to fake useRouter, useDispatch, and useDevice. This lets us control what data these hooks return so we can test different scenarios.
  2. Rendering the Component: We use render(<EmailSignup />) to render the component, so we can interact with it
  3. Testing Initial State: The first test checks if the component loads correctly with a default email input and a message prompting the user to check their email.
  4. Testing URL Query: If an email is passed via the URL (mocked with useRouter), the second test ensures it shows up in the input field.
  5. Loading State: When the form is submitted, the loading state should disable the submit button. We simulate this using fireEvent.click().
  6. Dispatching Actions: Finally, we test if the correct action is dispatched with the right email when the form is submitted.

What Did We Achieve? 🎯

By writing these simple tests, we made sure:

  • Our form behaves as expected when the page loads.
  • The email from the URL appears in the form field.
  • The loading state and error messages work properly.
  • The form sends the right data when submitted.

In short: Our tests make sure our component works as expected, and any bugs 🐛 caught now are bugs not seen by your users. 🎉

--

--

Pavan Kumar
Pavan Kumar

Written by Pavan Kumar

8+ years of Testing experience in automation using Selenium (Java). Expertise in API and Performance testing . Interested in Full Stack Development

No responses yet