Back to Blog
Lesson 43 of the Intermediate WordPress Plugins: REST API & React Admin course
WordPressReactJune 26, 20263 min read

Unit Testing React Components: Jest & React Testing Library

Learn how to test React components in WordPress. We'll set up Jest, mock API services, and verify UI behavior to ensure your plugin's admin dashboard is stable.

WordPressReactJestTestingUnit TestingJavaScriptphpplugin-development

Previously in this course, we explored Unit Testing API Endpoints in WordPress: A Practical Guide to ensure our backend logic remains sound. Now, we shift our focus to the frontend, where we'll implement unit testing for our React admin dashboard to prevent regressions in our UI.

Testing isn't just about catching bugs; it’s about defining the expected behavior of your components. When you write tests, you're building a safety net that allows you to refactor your code with confidence. In the WordPress ecosystem, we rely on Jest and React Testing Library (RTL) to simulate user interactions and verify rendered output.

Setting Up the Testing Environment

Since we are using @wordpress/scripts, most of the heavy lifting for our testing environment is already handled. The wp-scripts test command is pre-configured to use Jest and the necessary Babel transforms for WordPress.

First, ensure you have the required dependencies installed:

Bash
npm install --save-dev @testing-library/react @testing-library/jest-dom

Next, add a test script to your package.json if it doesn't already exist:

JSON
"scripts": {
    "test": "wp-scripts test-unit-js"
}

This command runs Jest in "watch" mode by default, which is perfect for development. It scans your directory for files ending in .test.js or .spec.js.

Writing Your First Component Test

Let's test a simple component from our Knowledge Base plugin: a status message indicator. We want to verify that when we pass a status prop, the component renders the correct text.

Create a file named StatusIndicator.test.js alongside your component:

JAVASCRIPT
import { render, screen } from CE9178">'@testing-library/react';
import StatusIndicator from CE9178">'./StatusIndicator';

test(CE9178">'renders the correct status message', () => {
    render(<StatusIndicator status="success" />);
    const messageElement = screen.getByText(/success/i);
    expect(messageElement).toBeInTheDocument();
});

Here, render mounts the component into a virtual DOM, and screen provides methods to query elements. We use expect to assert that the element exists.

Mocking the API Service Layer

Real-world components often fetch data using our Building the Knowledge Base Service Layer. We don't want to make actual network requests during unit tests. Instead, we "mock" the service.

If your component uses a service file, you can mock it using jest.mock.

JAVASCRIPT
// KnowledgeBaseList.test.js
import { render, screen, waitFor } from CE9178">'@testing-library/react';
import KnowledgeBaseList from CE9178">'./KnowledgeBaseList';
import * as api from CE9178">'./api';

jest.mock(CE9178">'./api');

test(CE9178">'displays loading state and then data', async () => {
    // Mock the API response
    api.fetchEntries.mockResolvedValue([{ id: 1, title: CE9178">'Test Entry' }]);

    render(<KnowledgeBaseList />);
    
    // Verify loading state
    expect(screen.getByText(/loading/i)).toBeInTheDocument();

    // Verify data appears after promise resolves
    await waitFor(() => {
        expect(screen.getByText(CE9178">'Test Entry')).toBeInTheDocument();
    });
});

This pattern ensures that your tests are deterministic and fast, regardless of the state of your WordPress database.

Hands-on Exercise: Testing a Form

In our previous lesson, Creating a React Form for Submissions in WordPress, we built a form. Your task is to:

  1. Create a KnowledgeBaseForm.test.js file.
  2. Render the form.
  3. Use @testing-library/user-event to simulate typing into the input field.
  4. Verify that the "Submit" button triggers the expected mock function.

Common Pitfalls

  • Testing Implementation Details: Avoid testing internal state or methods. Instead, test what the user sees. If you change your internal logic but the output remains the same, your test shouldn't break.
  • Forgetting to Cleanup: While RTL usually cleans up automatically, if you're using global mocks, ensure you call jest.clearAllMocks() in an afterEach block to prevent test pollution.
  • Asynchronous Race Conditions: Always use findBy* queries or waitFor when waiting for API responses. Using getBy* will fail immediately if the element isn't present during the initial render.

Recap

We've covered the basics of bringing professional testing habits to your React admin UI. By leveraging Jest and React Testing Library, you can isolate components, mock external dependencies, and verify that your UI behaves exactly as expected. This approach is essential for any Introduction to Testing: Quality Assurance in React with Jest workflow.

Up next: We will explore how to manage large datasets efficiently using GraphQL, moving beyond simple REST API patterns.

Similar Posts