mardi 22 décembre 2020

How can I test a click event which changes a useState state with enzyme?

So I have the following component:

import React, { useState } from "react";

import { Button, ThirteenBold } from "@selfdecode/sd-component-library";
import { PlayIcon } from "assets/icons";
import { TourButtonProps } from "./interfaces";
import { WelcomeVideoModal } from "../../modals/welcome-video-modal";

/**
 * The tour button.
 */
export const TourButton: React.FC<TourButtonProps> = (props) => {
  const [isIntroVideoShowing, setIsIntroVideoShowing] = useState(false);

  return (
    <>
      <WelcomeVideoModal
        isOpen={isIntroVideoShowing}
        onClickX={() => setIsIntroVideoShowing(false)}
        data-test="tour-button-welcome-video"
      />

      <Button
        {...props}
        width={["max-content"]}
        variant="tour"
        onClick={() => setIsIntroVideoShowing(true)}
        data-test="tour-button"
      >
        <ThirteenBold
          mr={["12px"]}
          color="cl_blue"
          width={["max-content"]}
          letterSpacing={["1px"]}
          display={["none", "block"]}
          textTransform="uppercase"
        >
          welcome tour
        </ThirteenBold>

        <PlayIcon style= />
      </Button>
    </>
  );
};

And the test coverage report is complaining that I am not testing both of the onClick events, which change the state.

I've tried two approaches, and both fail. Approach one was to mock the useState and see if it gets called as I'd have expected it. This was the test I tried:

 const setState = jest.fn();
 const useStateMock: any = (initState: any) => [initState, setState];
 jest.spyOn(React, "useState").mockImplementation(useStateMock);
 
 const button = wrapper.find(`[data-test="tour-button"]`);
 expect(button).toHaveLength(1);
 button.simulate("click");
 expect(setState).toHaveBeenCalled();

This shouldn't even be the final test, as it doesn't check what was the valuee it was called with, but still, it failed because useState wasn't even called.

The second approach I've tried was to check the prop value on this component: <WelcomeVideoModal isOpen={isIntroVideoShowing} onClickX={() => setIsIntroVideoShowing(false)} data-test="tour-button-welcome-video" />

And this is the test I've tried

  test("Check the isIntroVideoShowing changes to true on buton click", () => {
    jest.spyOn(React, "useState").mockImplementation(useStateMock);
    const button = wrapper.find(`[data-test="tour-button"]`);
    const welcomeVideo = wrapper.find(
      `[data-test="tour-button-welcome-video"]`
    );
    expect(button).toHaveLength(1);
    expect(welcomeVideo.prop("isOpen")).toEqual(false);
    button.simulate("click");
    expect(welcomeVideo.prop("isOpen")).toEqual(true);
  });

This one failed claiming it was called with false even after the click.

Is there a way to make these work? Or a different approach to cover these?

Aucun commentaire:

Enregistrer un commentaire