I have a functional component that I want to write test with jest. But I couldn't evaluate the results. How should I write tests for a component like this? Here is my component that I want to test:
import React from "react";
import { useDispatch } from "react-redux";
import { useNavigate } from "react-router-dom";
import ExpenseForm from "./ExpenseForm";
import { addExpense } from "../store/expenses/actions";
const AddExpensePage = () => {
const dispatch = useDispatch();
const navigate = useNavigate();
function onSubmit(expense) {
dispatch(addExpense(expense));
navigate("/");
}
return (
<div>
<h1>Add Expense</h1>
<ExpenseForm onSubmit={onSubmit} />
</div>
);
};
export default AddExpensePage;
I've write this tests:
import React from "react";
import * as reactRedux from "react-redux";
import { shallow } from "enzyme";
import AddExpensePage from "../AddExpensePage";
import expenses from "../../fixtures/expenses";
// Mock useDispatch hook
const useDispatch = jest.spyOn(reactRedux, "useDispatch");
jest.mock("react-redux", () => ({
...jest.requireActual("react-redux"),
useDispatch: jest.fn(),
}));
const mockedUsedNavigate = jest.fn();
jest.mock("react-router-dom", () => ({
...jest.requireActual("react-router-dom"),
useNavigate: () => mockedUsedNavigate,
}));
beforeEach(() => {
useDispatch.mockClear();
});
test("should render AddExpensePage correctly", () => {
const wrapper = shallow(<AddExpensePage />);
expect(wrapper).toMatchSnapshot();
});
test("should handle onSubmit", () => {
const dispatch = jest.fn();
useDispatch.mockReturnValue(dispatch);
const onSubmitSpy = jest.fn();
const wrapper = shallow(<AddExpensePage onSubmit={onSubmitSpy} />);
wrapper.find("ExpenseForm").prop("onSubmit")(expenses[1]);
expect(dispatch).toHaveBeenCalled();
expect(mockedUsedNavigate).toHaveBeenLastCalledWith("/");
// expect(onSubmitSpy).toHaveBeenLastCalledWith(expenses[1]);
});
I am not sure if this line works "wrapper.find("ExpenseForm").prop("onSubmit")(expenses[1]);"
I also want to test this "expect(onSubmitSpy).toHaveBeenLastCalledWith(expenses[1]);". But I couldn't find how to do this.
Do you have any idea to help me?
Please advise how should I write tests such components.
Thanks in advance.
It is recommended to test the behaviour of components, not their implementation. So instead of programmatically invoking your function, you should find the button that invokes it and simulate the click. The same with the text input (I suppose) that is accepting the data handled by the tested function.
Also, you can't simply mock a function by passing it as a prop if your component doesn't accept such a prop.
test("should handle onSubmit", () => {
const dispatch = jest.fn();
const navigate = jest.fn();
useDispatch.mockReturnValue(dispatch);
useNavigate.mockReturnValue(navigate);
const wrapper = shallow(<AddExpensePage />);
const submitBtn = wrapper.find('button[type="submit"]');
submitBtn.simulate('change', { target: { value: 'myMock' } } );
expect(dispatch).toHaveBeenCalled();
expect(navigate).toHaveBeenCalledWith("/");
});