I'm struggling with passing a button click test in my app component using Vitest, react-testing-library, and jest dom. As a newcomer to unit testing, I'm having difficulty figuring out how to make my test for the submit button in my form function properly. (Add Button)
I keep getting an AssertionError: expected "spy" to be called 1 time, but it was called 0 times.
Below is the code for my TaskForm component:
import { useDispatch } from "react-redux";
import { add } from "./taskFormSlice";
import { useRef, useState } from "react";
import Tasks from "./Tasks";
const TaskForm = () => {
const dispatch = useDispatch();
const task = useRef<string>("");
const [userInputVal, setUserInputVal] = useState("");
return (
<div className="flex flex-col space-y-8 items-center justify-center min-h-screen bg-indigo-900">
<div className="text-7xl text-white mt-10">To Do App</div>
<div className="flex flex-row space-y-4 items-center justify-center">
<form onSubmit={(e) => e.preventDefault()}>
<input
value={userInputVal}
onChange={(e) => {
setUserInputVal(e.target.value);
task.current = e.target.value;
}}
className="w-96 border-solid border-sky-500 rounded-full border-2 px-8 py-2 placeholder:text-center text-md"
placeholder="Enter Task"
/>
<div className="inline-block">
<button
className="px-4 py-2 bg-blue-700 rounded-full text-white shadow-lg hover:shadow-sky-700 ml-40 mt-2 sm:ml-2"
type="submit"
onClick={() => {
setUserInputVal("");
dispatch(add(task.current));
}}
>
Add
</button>
</div>
</form>
</div>
<Tasks></Tasks>
</div>
);
};
export default TaskForm;
In my test file, I have a unit test for the add/submit button. I'm not sure if mocking the button click by passing it into the component is the correct approach. How else can I mock the button click function to properly test that the button will be clicked?
import { describe, expect, test, vi } from "vitest";
import { fireEvent, screen, waitFor } from "@testing-library/react";
import TaskForm from "./TaskForm";
describe.sequential("to do list components render correctly", () => {
test("input box takes in user input", async () => {
renderWithProviders(<TaskForm></TaskForm>);
const input = screen.getByPlaceholderText("Enter Task");
fireEvent.change(input, { target: { value: "test todo" } });
await waitFor(() => {
expect(input).toHaveValue("test todo");
});
});
test("Test button click to ensure that it works", () => {
const handleClick = vi.fn();
renderWithProviders(<TaskForm onClick={handleClick}></TaskForm>);
fireEvent.click(screen.getByText("Add"));
expect(handleClick).toHaveBeenCalledTimes(1);
});
});