0

I found lots of ways of using mock functions in jest to spy on callback functions that are passed down to a component but nothing on testing a simple onClick that is defined in the same component.

My Example Page:

const ExamplePage: NextPage = () => {
    const router = useRouter();
    const onClick = (): Promise<void> => {
        axios.post(`/api/track`, {
            eventName: Event.TRACK_CLICK,
        });
        router.push("/new-route");
        return Promise.resolve();
    };

    return (
        <Container data-testid="container">
            <Title>Example Title</Title>
            <CreateButton data-testid="create-button" onClick={onClick}>
                Create Partner
            </CreateButton>
        </Container>
    );
};

export default ExamplePage;

My current test where I am attempting to get the onClick from getAttribute:

import { fireEvent, render } from "../../../../test/customRenderer";
import ExamplePage from "../../../pages/example-page";

describe("Example page", () => {
    it("has a button to create", () => {
        const { getByTestId } = render(<ExamplePage />);

        const createButton = getByTestId("create-button");

        expect(createButton).toBeInTheDocument();
    });

    it(" the button's OnClick function should be executed when clicked", () => {
        const { getByTestId } = render(<ExamplePage />);
        // find the button
        const createButton = getByTestId("create-button");
        // check the button has onClick
        expect(createButton).toHaveAttribute("onClick");
        // get the onClick function
        const onClick = createButton.getAttribute("onClick");
        fireEvent.click(createButton);
        // check if the button's onClick function has been executed
        expect(onClick).toHaveBeenCalled();
    });
});

The above fails since there is no onClick attribute only null. My comments in the test highlight my thought process of trying to reach down into this component for the function on the button and checking if it has been called.

Is there any way to test a onClick that is self contained in a react component?

lpritchard
  • 121
  • 3
  • 11
  • Probably no way. – Konrad Sep 28 '22 at 19:51
  • Of course there is, you just test the _behaviour_ instead of the implementation. Use a test double for the request, test the navigation by where you end up (see e.g. https://stackoverflow.com/a/65275037/3001761). – jonrsharpe Sep 28 '22 at 19:57

1 Answers1

0

You need to provide mocked router provider and expect that a certain route is pushed to the routers. You also need extract the RestAPI into a separate module and mock it! You can use Dependency Injection, IOC container or import the Api in the component and mock it using jest. I will leave the RestAPi mocking to you.

Mocking router details here: How to mock useRouter


  const useRouter = jest.spyOn(require('next/router'), 'useRouter')


  describe("", () => {
    it("",() => {
       const pushMock = jest.fn();
      
       // Mocking Rest api call depends on how you are going to "inject it" in the component
       const restApiMock = jest.jn().mockResolvedValue();

       useRouter.mockImplementationOnce(() => ({
         push: pushMock,
       }))
       const rendrResult = render(<ExamplePage />);
       
       //get and click the create button

     //expect the "side" effects of clicking the button

      expect(restApiMock).toHaveBeenCalled();
      expect(pushMock).toHaveBeenCalledWith("/new-route");
    });
  });


Svetoslav Petkov
  • 1,117
  • 5
  • 13