Logo

dev-resources.site

for different kinds of informations.

Getting Started with Redux in React Testing Library: A Guide to Custom Render Functions.

Published at
3/4/2024
Categories
javascript
react
testdev
programming
Author
jagodabieniek
Author
13 person written this
jagodabieniek
open
Getting Started with Redux in React Testing Library: A Guide to Custom Render Functions.

Introduction

Often in our projects we need to manage the state. For this purpose, we can use Redux however in 2024 there is a Redux toolkit , which simplifies the use of Redux itself. In this tutorial, I want to focus on how to start testing an application that uses the Redux toolkit.

Custom render function.

In testing React components, It is often used external libraries, not only redux-toolkit, but also react-router-dom or styled-components . In these cases, it is usefull to create custom render function.

Let's take as example boardSlice.ts (example from my project):

Image description

Import the necessary modules and components from React, Redux Toolkit, React Testing Library, and your application.

import { ReactElement, ReactNode } from 'react';
import { render, RenderOptions } from '@testing-library/react';
import { configureStore } from '@reduxjs/toolkit';
import { Provider } from 'react-redux';
import { boardSlice } from './store/slices';
Enter fullscreen mode Exit fullscreen mode

Define the CustomRenderOptions interface witch extends the RenderOptions from @testing-library/react, excluding the wrapper property. It adds optional preloadedState and store properties. This allows you to pass an initial state for the Redux store or a custom store when calling customRender.

interface CustomRenderOptions extends Omit<RenderOptions, 'wrapper'> {
  preloadedState?: Record<string, unknown>;
  store?: ReturnType<typeof configureStore>;
}
Enter fullscreen mode Exit fullscreen mode

Create the customRender function takes a React element and an options object as arguments. The options object defaults to an empty object if not provided.
Create the Redux store: If a store is not provided in the options, a new store is created using the configureStore function from Redux Toolkit. The store uses the boardSlice.reducer as its reducer and the preloadedState as its initial state.

const customRender = (
  ui: ReactElement,
  {
    preloadedState = {},
    store = configureStore({
      reducer: { board: boardSlice.reducer },
      preloadedState,
    }),
    ...options
  }: CustomRenderOptions = {}
) => {
  // ...
};
Enter fullscreen mode Exit fullscreen mode

Create the Wrapper component, wraps its children in a Redux Provider. The Provider makes the Redux store available to the components.

const Wrapper = ({ children }: { children: ReactNode }) => (
  <Provider store={store}>{children}</Provider>
);
Enter fullscreen mode Exit fullscreen mode

Call the render function finally, the function calls the render function from React Testing Library, passing the ui and the Wrapper as the wrapper option.

return render(ui, { wrapper: Wrapper, ...options });
Enter fullscreen mode Exit fullscreen mode

Export the customRender function, then exported as render, so it can be used in place of the render function from @testing-library/react.

export { customRender as render };
Enter fullscreen mode Exit fullscreen mode

Finally we receive :

import { ReactElement, ReactNode } from 'react';
import { render, RenderOptions } from '@testing-library/react';
import { MemoryRouter } from 'react-router-dom';
import { configureStore } from '@reduxjs/toolkit';
import { Provider } from 'react-redux';
import { boardSlice } from './store/slices';
interface CustomRenderOptions extends Omit<RenderOptions, 'wrapper'> {
  preloadedState?: Record<string, unknown>;
  store?: ReturnType<typeof configureStore>;
}

const customRender = (
  ui: ReactElement,
  {
    preloadedState = {},
    store = configureStore({
      reducer: { board: boardSlice.reducer },
      preloadedState,
    }),
    ...options
  }: CustomRenderOptions = {}
) => {
  const Wrapper = ({ children }: { children: ReactNode }) => (
   // Here you can other providers
    <Provider store={store}>
      {children}
    </Provider>
  );

  return render(ui, { wrapper: Wrapper, ...options });
};

export * from '@testing-library/react';
export { customRender as render };

Enter fullscreen mode Exit fullscreen mode

Sumarry

In this tutorial, we've explored how to create a custom render function for testing React components that interact with a Redux store, using Redux Toolkit. This custom render function simplifies the testing process by automatically wrapping the component under test in the necessary context providers, such as Redux's Provider and React Router's MemoryRouter.

We started by importing the necessary modules and defining a CustomRenderOptions interface to extend the RenderOptions from @testing-library/react. This interface allows us to optionally pass an initial state or a custom store to the customRender function.

Next, we created the customRender function, which takes a React element and an options object as arguments. Inside this function, we created a Redux store (if not provided in the options) and a Wrapper component that wraps its children in a Redux Provider.

Finally, we called the render function from @testing-library/react, passing the ui and the Wrapper as the wrapper option, and exported the customRender function as render.

This custom render function is a powerful tool that can simplify your test setup, reduce repetition in your tests, and make your tests more robust and flexible when working with libraries like Redux Toolkit.
With this configuration, your application is now equipped to handle Redux Toolkit in unit tests. In subsequent sections, we will delve into the specifics of what to test and how to conduct these tests within the Redux Toolkit context.

testdev Article's
30 articles in total
Favicon
Your Roadmap to Mastering k6 for Performance Testing
Favicon
What is testing ?
Favicon
Empowering IT Development: Optimized Storage Solutions for Testing and Training Excellence
Favicon
ERC-4337 Shared Mempool Mainnet Launch, Biconomy Acquires Klaster, Eclipse Bridges Ethereum & Solana, and Mekong Testnet Launch
Favicon
AWS Bedrock Knowledge - Base Testing Script
Favicon
JetThoughts Soars Among Top Web Development Companies in the USA for 2024 by Techreviewer.co
Favicon
Software Testing Glossary: One-Stop Guide for 100+ Testing Terms
Favicon
Role And Responsibilities Of A Test Lead In Software Testing
Favicon
Advanced Topics in E2E Testing Introduction
Favicon
Mastering Test Automation: Best Practices for Seamless Software Testing
Favicon
How I would begin a career in software QA
Favicon
Top 12 Software Testing Communities for Developers and Testers [2024]
Favicon
10 Key Strategies to Effectively Manage Developer-QA Ratio Challenges in Startups
Favicon
Playwright's LocatorHandler: Simplifying Web Testing and overlay handling
Favicon
Unveiling the Art of Exploratory Testing: Techniques for Intuitive Software Quality Assurance
Favicon
Getting Started with Redux in React Testing Library: A Guide to Custom Render Functions.
Favicon
Tests, Tests Everywhere
Favicon
Test Post
Favicon
The Test List in Test-Driven Development (TDD)
Favicon
Exploring WebdriverIO
Favicon
Increasing focus on QAOps
Favicon
How to Test Banking Applications: Complete Guide To Testing In The Banking Domain
Favicon
What is Optical fiber
Favicon
Firebase Testing
Favicon
Software Development Engineer in Test / Quality Assurance
Favicon
You don’t really need external testers
Favicon
My "Postman 30 day challenge for developers" expression
Favicon
Is NodeJS Test Runner β€œDev-Ready”?
Favicon
tes
Favicon
Domain-Specific Languages for Automated Testing Development

Featured ones: