如何使用酶,玩笑和反应来测试材料设计事件侦听器

时间:2018-08-13 22:26:46

标签: reactjs material-design jestjs

我正在测试模拟函数(onAccept)的调用,该函数应在 Accept 按钮单击(类名为mdc-dialog__footer__button--accept的按钮)上执行。我尝试了我所知道的一切,但是没有运气。在(非测试)开发环境中,这一切都可以正常工作。

我总是遇到以下错误:

  

expect(jest.fn())。toHaveBeenCalled()
      预期的模拟函数已被调用,但未被调用。

有什么主意我在做错什么吗?

这是我的Dialog.tsx组件,用于包装材料Dialog:

import { MDCDialog } from '@material/dialog';
import * as React from 'react';
import { RefObject } from 'react';

import { IDialogProps } from '.';

export class Dialog extends React.Component<IDialogProps, any> {
    private dialogRef: RefObject<HTMLDivElement>;
    private dialog: MDCDialog;

    public componentWillMount() {
        const elementRef = this.props.elementRef;
        this.dialogRef = elementRef ? elementRef : React.createRef();
    }

    public render() {
        const {
            elementRef,
            className,
            children,
            role,
            isVisible,
            onClose,
            onAccept,
            onCancel,
            ...other
        } = this.props;

        return (
            <aside
                ref={ this.dialogRef }
                className={ this.getClassName() }
                role="alertdialog"
                { ...other }
            >
                <div className="mdc-dialog__surface">
                    { ...children }
                </div>
                <div className="mdc-dialog__backdrop"></div>
            </aside>

        );
    }

    public componentDidMount() {
        const {
            onAccept,
            onCancel,
            onClose,
            isVisible
        } = this.props;
        this.dialog = new MDCDialog(this.dialogRef.current);

        if (onAccept) {
            this.dialog.listen("MDCDialog:accept", onAccept);
        }

        if (onCancel) {
            this.dialog.listen("MDCDialog:cancel", onCancel);
        }

        if (onClose) {
            this.dialog.listen("MDCDialog:accept", onClose);
            this.dialog.listen("MDCDialog:cancel", onClose);
        }

        if (isVisible) {
            this.dialog.show();
        }
    }

    public componentDidUpdate(prevProps: IDialogProps) {
        if (prevProps.isVisible !== this.props.isVisible) {
            this.toggleVisibility();
        }
    }

    private toggleVisibility = () => {
        const isVisible = this.props.isVisible;
        isVisible ? this.dialog.show() : this.dialog.close();
    }

    private getClassName = (): string => {
        const {
            className
        } = this.props;

        let result = "mdc-dialog";
        result += className ? ` ${className}` : "";

        return result;
    }
}

这是我的考验:

test("should execute onAccept on 'accept' button of dialog click", () => {

const onAccept = jest.fn();
const component = (
    <Dialog onAccept={ onAccept } isVisible>
        <button id="cancelButton" className="mdc-dialog__footer__button--cancel">Cancel</button>
        <button id="acceptButton" className="mdc-dialog__footer__button--accept">Accept</button>
    </Dialog>
);

const wrapper = mount(component);
wrapper.find("#acceptButton").at(0).simulate("click");

    expect(onAccept).toHaveBeenCalled();
});

重要的事实是MDCDialog.listen("MDCDialog:accept", onAccept)<aside>元素上放置了“ MDCDialog:accept”自定义事件。因此,问题是,是否有任何方法可以测试模拟函数的调用,或者至少检查是否已附加自定义事件?

1 个答案:

答案 0 :(得分:0)

经过几天的研究,我找不到答案。但是,最后,我通过使用ReactDOM.render()将组件附加到文档主体来实现了。它可能不是最好的解决方案,但似乎可行。解决方法如下:

test("should execute onAccept on accept button of dialog click", () => {
const onAccept = jest.fn();
const component = (
    <Dialog onAccept={ onAccept } isVisible>
        <button id="cancelButton" className="mdc-dialog__footer__button--cancel">Cancel</button>
        <button id="acceptButton" className="mdc-dialog__footer__button--accept">Accept</button>
    </Dialog>
);

ReactDOM.render(component, document.body);
const el = document.getElementById("acceptButton");
el.click();

    expect(onAccept).toHaveBeenCalled();
});

我仍然不确定为什么前面的示例不起作用。