I want to test connected React component. I am using Jest, React Testing Library and redux-mock-store. I'm mocking the getPatternPageInfo function and When I'm trying to get some elements, I get an error:
TypeError: SidebarActions_1.selectPattern is not a function
package.json
"redux-mock-store": "^1.5.4",
"typescript": "^3.9.7",
"@testing-library/jest-dom": "^5.11.4",
"@testing-library/react": "^11.0.4",
"@types/jest": "^26.0.13",
"@types/redux-mock-store": "^1.0.2",
"jest": "^26.4.2",
"ts-jest": "^26.3.0",
"react-redux": "5.0.7",
"react-router-dom": "^5.1.2",
"redux": "3.7.2",
SidebarActions.ts
import axios from "axios";
import { ActionType, AppDispatch } from "./Actions";
import { Pattern } from "../reducers/SidebarMenuReducer";
import { simpleDataExtract } from "./common/common";
import { ResponseStatus } from "../../enums/status";
import { Urls } from "../../enums/Urls";
import { SelectedItemTypes } from "../../enums/SelectedItemTypes";
export const getPatternPageInfo = (patternId: number): Promise<Pattern> => {
return axios
.get(`${Urls.GET_PATTERN_PAGE_INFO}?patternId=${patternId}`)
.then(simpleDataExtract)
.then(response => {
if (response.status === ResponseStatus.OK) return response.data;
});
};
export const selectPattern = (patternId: number | undefined) => (dispatch: AppDispatch) => {
dispatch({
type: ActionType.SET_SELECTED_ITEM,
data: { id: patternId, type: SelectedItemTypes.PATTERN },
});
};
PatternForm.tsx
import * as React from "react";
import { FC, useEffect, useState } from "react";
import { Box, Grid, } from "@material-ui/core";
import { connect } from "react-redux";
import { Pattern } from "../redux/reducers/SidebarMenuReducer";
import { AppDispatch } from "../redux/actions/Actions";
import { getPatternPageInfo, selectPattern } from "../redux/actions/SidebarActions";
import PageLoader from "../components/loaders/PageLoader";
interface Events {
onPatternClick(patternId: number): void;
}
interface MatchParams {
params: { patternId: number | undefined };
isExact: boolean;
path: string;
url: string;
}
interface Match {
match: MatchParams;
}
const PatternForm: FC<Events & Match> = props => {
const [pattern, setPattern] = useState<Pattern | undefined>(undefined);
const [isLoading, setIsLoading] = useState<boolean>(true);
const { onPatternClick } = props as Events;
const { match } = props as Match;
const patternId = match && match.params && Number(match.params.patternId);
useEffect(() => {
if (patternId) {
setIsLoading(true);
getPatternPageInfo(patternId).then(data => {
setPattern(data);
setIsLoading(false);
});
}
onPatternClick(patternId);
}, [patternId]);
if (isLoading) return <PageLoader />;
return (
<Box data-testid="content" className="layout__content">
<Grid item xs className="layout__body">
Test
</Grid>
</Box>
);
};
const mapDispatchToProps = (dispatch: AppDispatch): Events => ({
onPatternClick: patternId => dispatch(selectPattern(patternId)),
});
export default React.memo(connect(null, mapDispatchToProps)(PatternForm));
PatternForm.test.tsx
import React from "react";
import { render, fireEvent, screen } from "@testing-library/react";
import { Provider } from "react-redux";
import configureMockStore from "redux-mock-store";
import thunk from "redux-thunk";
import PatternForm from "../../pages/PatternForm";
import { Pattern, Oiv } from "../../redux/reducers/SidebarMenuReducer";
const middlewares = [thunk];
const mockStore = configureMockStore(middlewares);
const store = mockStore({});
jest.mock("../../redux/actions/SidebarActions", () => ({
getPatternPageInfo: jest.fn(),
}));
const getPatternPageInfo = require("../../redux/actions/SidebarActions").getPatternPageInfo as jest.Mock;
const match = {
params: { patternId: 1 },
isExact: true,
path: "path",
url: "url",
};
describe("<PatternForm/>", () => {
it("should render data", () => {
const pattern = {
id: 936,
name: "test",
oivs: [{ id: 29109, name: "oiv" } as Oiv],
} as Pattern;
getPatternPageInfo.mockImplementationOnce(() => Promise.resolve(pattern));
render(
<Provider store={store}>
<PatternForm match={match} />
</Provider>,
);
expect(screen.getByTestId("content")).toBeInTheDocument();
});
});
The solution in this docs worked for me https://jestjs.io/docs/en/jest-object#jestrequireactualmodulename
PatternForm.test.tsx
jest.mock("../../redux/actions/SidebarActions", () => {
const originalModule = jest.requireActual("../../redux/actions/SidebarActions");
return {
...originalModule,
getPatternPageInfo: jest.fn(),
};
});
const getPatternPageInfo = require("../../redux/actions/SidebarActions").getPatternPageInfo as jest.Mock;