如何使用 jest 在 React 中进行 Modal 的单元测试

问题描述 投票:0回答:1
// Delete.jsx

import React, {useCallback, useRef} from "react"
import {useDispatch} from "react-redux"
import {ModalComponent, modalOpen} from "../Modal"

export function Delete () {
    const dispatch = useDispatch()
    const modalRef = useRef(null)
    const handleDelete = () => {
        dispatchEvent(deleteData())
        modalRef.current.close
    }
    return (
        <Type>
            <Button
                onClick={modalOpen(modalRef)}
            >
                Delete
            </Button>
            <ModalComponent func={handleDelete} refer={modalRef} />
        </Type>
    )
}

// ModalComponent.jsx

import React, {useCallback} from "react"

export function ModalComponent (props) {
    const modalRef = props.refer

    return (
        <Modal
            ref={modalRef}
            onClose={modalClose(modalRef)}
            >
                <Type>
                    Are you sure ?
                </Type>
                <Type>
                    <ButtonGroup>
                        <Button
                            id='DeleteButton'
                            onClick={modalClose(modalRef)}
                        >
                            Close
                        </Button>
                        <Button
                            onClick={props.func}
                        >
                            Confirm
                        </Button>
                    </ButtonGroup>
                </Type>
            </Modal>
    )
}

export const modalOpen = (refModal) => {
    return useCallback(
        () => {
            refModal.current.open()
        }, [refModal]
    )
}

export const modalClose = (refModal) => {
    return useCallback(
        () => {
            refModal.current.close()
        }, [refModal]
    )
}

以上是Delete和ModalComponent的代码,我正在尝试为Delete按钮编写单元测试用例。

// Delete.test.js

import React from "react"
import {fireEvent, render} from "@testing-library/react"
import * as modal from '../ModalComponent'

jest.mock('react-redux', () => ({
    ...jest.requireActual('react-redux'),
    useDispatch: jest.fn()
}))

describe('Delete button', () => {
    it('should open modal when delete button is called', () => {
        const modalSpy = jest.spyOn(modal, 'modalOpen').mockImplementation(() => jest.fn())
        const component = render(
            <Delete />
        )
        const button = component.container.querySelector('#DeleteButton')
        fireEvent.click(button)
        expect(modalSpy).toHaveBeenCalled()
    })
})

在这里,我尝试测试模态是否打开并且它正在工作,但我想测试删除功能,但在这里我模拟了模态,所以我不确定如何测试句柄删除,当我尝试不模拟模态时它会抛出错误。

有人可以帮我处理模式事件,以便我可以测试句柄编辑吗?

reactjs unit-testing react-redux jestjs react-testing-library
1个回答
0
投票

问题

不要嘲笑你正在尝试进行单元测试的内容。您的单元测试应该反映用户或其他组件如何与该组件交互,例如通过其渲染的 UI 和 props。

建议

由于您无法共享

Modal
组件,我创建了一个模拟模态组件,该组件通过 React 引用公开打开和关闭处理程序。

模拟模态组件:

import React, {
  forwardRef,
  useImperativeHandle,
  useState
} from "react";

const Modal = forwardRef((props, ref) => {
  const [open, setOpen] = useState(false);

  useImperativeHandle(
    ref,
    () => ({
      open: () => setOpen(true),
      close: () => setOpen(false)
    }),
    []
  );

  return open ? (
    <div data-testid="modal">
      <button type="button" onClick={props.onClose}>
        x
      </button>
      <div>{props.children}</div>
    </div>
  ) : null;
});

删除

const modalOpen = (refModal) => () => {
  refModal.current.open();
};

const modalClose = (refModal) => () => {
  refModal.current.close();
};

export default function Delete() {
  // const dispatch = useDispatch();
  const modalRef = useRef(null);

  const handleDelete = () => {
    // dispatchEvent(deleteData())
    modalRef.current.close();
  };

  return (
    <Type>
      <Button onClick={modalOpen(modalRef)}>Delete</Button>
      <ModalComponent func={handleDelete} refer={modalRef} />
    </Type>
  );
}

删除单元测试

import React from "react";
import { fireEvent, render } from "@testing-library/react";
import "@testing-library/jest-dom";
import Delete from "./Delete";

describe("Delete button", () => {
  it("should open modal when delete button is called", () => {
    const { queryByText, queryByTestId } = render(<Delete />);

    // Assert that the modal is not current in the DOM
    expect(queryByTestId("modal")).not.toBeInTheDocument();

    // Click delete button to toggle the modal open
    fireEvent.click(queryByText("Delete"));

    // Assert that the modal is now in the DOM
    expect(queryByTestId("modal")).toBeInTheDocument();

    // Click modal's close button to toggle the modal closed
    fireEvent.click(queryByText("Close"));

    // Assert that the modal is not current in the DOM
    expect(queryByTestId("modal")).not.toBeInTheDocument();
  });
});

当您更新代码并取消注释

useDispatch
挂钩和
dispatch
调用时,您还需要为测试创建一个 Redux 存储。

基本示例:

import React from "react";
import { fireEvent, render } from "@testing-library/react";
import "@testing-library/jest-dom";
import { configureStore } from "@reduxjs/toolkit";
import { Provider } from "react-redux";
import reducer from "../path/to/rootReducer";
import Delete from "./Delete";

const store = configureStore({
  reducer,
});

const Providers = ({ children }) => (
  <Provider store={store}>
    {children}
  </Provider>
);

describe("Delete button", () => {
  it("should open modal when delete button is called", () => {
    const { .... } = render(<Delete />, { wrapper: Providers });

    ... testing code ...
  });
});

请参阅 Redux Writing Tests 文档,了解更多一般测试信息和策略。

© www.soinside.com 2019 - 2024. All rights reserved.