首页 > 解决方案 > 如何测试未作为道具传递的onClick事件

问题描述

我正在尝试测试一个like 按钮,它使用redux hooks。我想刺激事件的点击,看看它是否被调用。我将如何测试如下用例:

LikeButton.tsx

const { likePost, dislikePost } = storehooks();
const memoizedLike = React.useCallback((id) => likePost(id), [likePost]);
const memoizedDislike = React.useCallback((id) => dislikePost(id), [
  dislikePost,
]);

{
  props.type === "liked" && (
    <Fragment>
      <span
        style={{ cursor: "pointer" }}
        onClick={() => memoizedDislike(props.postId)}
      >
        <span style={{ padding: "12px" }}>Likes {props.likeCounts}</span>
        <FavoriteIcon
          style={{ color: "red", cursor: "pointer", margin: "-7px" }}
        />
      </span>
    </Fragment>
  );
}

likeButton.test.tsx

 it("should test onClick of liked button", () => {
        const container = mount(
            <Provider store={store}>
                <LikeButton {...mockProps} />
            </Provider>,
        );
        console.log( // this gets called which calls the redux hook. 
            container
                .find("span")
                .at(0)
                .props()
                .onClick(),
        );
        // how should i pass jest.fn() to the onClick prop ?
        
    });

标签: reactjsenzyme

解决方案


所以我认为最好的做法是将 onClicks 作为从父组件传递给子组件的道具。

所以我不得不重构

type LikeButtonProps = {
    type: "liked" | "unliked";
    likeCounts: number;
    postId?: number;
    dislike?: (id: number) => void;
    like?: (id: number) => void;
};

const LikeButton: React.FC<LikeButtonProps> = (props) => {
    return (
        <Fragment>
            {props.type === "liked" && (
                <Fragment>
                    <span style={{ cursor: "pointer" }} onClick={() => props.dislike?.(props.postId!)}>
                        <span style={{ padding: "12px" }}>Likes {props.likeCounts}</span>
                        <FavoriteIcon style={{ color: "red", cursor: "pointer", margin: "-7px" }} />
                    </span>
                </Fragment>
            )}
            {props.type === "unliked" && (
                <Fragment>
                    <span onClick={() => props.like?.(props.postId!)}>
                        <span style={{ padding: "12px" }}>Likes {props.likeCounts}</span>
                        <FavoriteBorderIcon style={{ color: "red", cursor: "pointer", margin: "-7px" }} />
                    </span>
                </Fragment>
            )}
        </Fragment>
    );
};

export default LikeButton;

父组件

const { likePost, dislikePost } = storehooks();
const memoizedLike = React.useCallback((id) => likePost(id), [likePost]);
const memoizedDislike = React.useCallback((id) => dislikePost(id), [dislikePost]);

{
  type === "post-buttons" &&
    (Object.entries(currentUser!).length === 0 ? (
      <Fragment>
        <span onClick={handleClickOpen}>
          <LikeButton
            like={memoizedLike}
            type="unliked"
            likeCounts={post.likeCounts}
          />
        </span>
        {openModal ? (
          <OurModal open={openModal} handleClose={handleCloseModal} />
        ) : null}
      </Fragment>
    ) : (
      <Fragment>
        {post.likedByMe === true ? (
          <LikeButton
            postId={post!.id}
            dislike={memoizedDislike}
            type="liked"
            likeCounts={post.likeCounts}
          />
        ) : (
          <LikeButton
            postId={post!.id}
            like={memoizedLike}
            type="unliked"
            likeCounts={post.likeCounts}
          />
        )}
      </Fragment>
    ));
}

LikeButton.test.tsx

 const mockProps2 = {
   type: "unliked",
   likeCounts: 3,
 };

 it("should test onClick of liked button", () => {
        const mockFn = jest.fn();
        const container = mount(
            <Provider store={store}>
                <LikeButton {...mockProps2} like={mockFn} />
            </Provider>,
        );

        container
            .find("span")
            .at(0)
            .simulate("click");
        expect(mockFn).toHaveBeenCalled();
        // test passes
    });

推荐阅读