如何使用酶、笑话和反应测试材料设计事件监听器

Posted

技术标签:

【中文标题】如何使用酶、笑话和反应测试材料设计事件监听器【英文标题】:How to test material design event listener using enzyme, jest and react 【发布时间】:2019-01-20 17:15:22 【问题描述】:

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

我总是收到以下错误:

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

任何想法我做错了什么?

这是我的 Dialog.tsx 组件,它包装了材质对话框:

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) 将“MDCDialog:accept”自定义事件放在&lt;aside&gt; 元素上。那么问题来了,有没有什么方法可以测试模拟函数的调用,或者至少检查自定义事件是否已附加?

【问题讨论】:

【参考方案1】:

经过几天的研究,我找不到答案。但是,最后,我通过使用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();
);

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

【讨论】:

以上是关于如何使用酶、笑话和反应测试材料设计事件监听器的主要内容,如果未能解决你的问题,请参考以下文章

用笑话和酶覆盖无操作功能

当它被包装在提供者组件中时,如何使用 mocha + 酶 + chai 测试反应原生组件

让笑话/酶测试等待上下文

笑话:如何模拟监听事件的依赖项?

材料表反应。如何使表格标题和标题具有粘性

如何使用反应酶检查实际的 DOM 节点