How to render with router as well as with Redux for react-testing-library?

Viewed 403

this is my testing-library-utils.js:

import React from "react";
import { render as rtlRender } from "@testing-library/react";
import { Provider } from "react-redux";
import { createStore, applyMiddleware } from "redux";
import { composeWithDevTools } from "redux-devtools-extension";
import thunk from "redux-thunk";
import reducer from "../reducers/rootReducer";

import { createMemoryHistory } from "history";
import { Router } from "react-router-dom";

const middleware = [thunk];

const history = createMemoryHistory();

function render(
  ui,
  {
    initialState,
    store = createStore(
      reducer,
      initialState,
      composeWithDevTools(applyMiddleware(...middleware))
    ),
    ...renderOptions
  } = {}
) {
  function Wrapper({ children }) {
    return (
      <Provider store={store}>
        <Router history={history}>{children}</Router>
      </Provider>
    );
  }
  return rtlRender(ui, { wrapper: Wrapper, ...renderOptions });
}

// re-export everything
export * from "@testing-library/react";
// override render method
export { render };

When i click on a <Link/>(using userEvent), it does not navigate to the desired page. I think its the way i am using <Router/> in my testing-library-utils.js.

How should I render with react-redux as well as react-router for testing using react-testing-library?

1 Answers

Here is how to do it in TypeScript:

import { MemoryRouter } from "react-router-dom";
import { render } from "@testing-library/react";
import { Provider } from "react-redux";
import { createStore, applyMiddleware } from "redux";
import thunk from "redux-thunk";
import reducer from "../reducers/rootReducer";

const middleware = [thunk];

export const renderWithRouterAndRedux = (
    component: React.ReactElement,
    { initialState = {}, store = createStore(reducer, initialState, applyMiddleware(...middleware)), route = "/", ...renderOptions } = {},
) => {
    window.history.pushState({}, "Initial Page", route);

    const Wrapper: React.FC = ({ children }) => (
        <Provider store={store}>
            <MemoryRouter>{children}</MemoryRouter>
        </Provider>
    );
    return render(component, { wrapper: Wrapper, ...renderOptions });
};


// re-export everything
export * from "@testing-library/react";
// override render method
export { render };
Related