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.
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:
Bashnpm 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:
JAVASCRIPTimport { 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:
- Create a
KnowledgeBaseForm.test.jsfile. - Render the form.
- Use
@testing-library/user-eventto simulate typing into the input field. - 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 anafterEachblock to prevent test pollution. - Asynchronous Race Conditions: Always use
findBy*queries orwaitForwhen waiting for API responses. UsinggetBy*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.
Work with me

Custom WordPress Plugin Development
Custom WordPress & WooCommerce plugins built to standard — by the developer behind a plugin with 5,000+ active installs and a SaaS with 10,000+ users.

Headless WordPress + Next.js Frontend Development
Keep WordPress for content, get a lightning-fast Next.js frontend. The best of both worlds — familiar editing, modern speed.