reactjs - React 模式对话框的内容不可用于使用 mount() 的 enzyme 测试

标签 reactjs unit-testing modal-dialog jestjs enzyme

我有一个带有模式对话框的 React 组件(使用 reactstrap 构建,但其他人报告了 react-bootstrap 和其他类型的模式组件的类似问题)。 Enzyme 无法找到模态中的任何组件,即使它们在实际应用程序中呈现良好。最小示例:

import React from 'react'
import { Modal } from 'reactstrap'

export default class MyModal extends React.Component {

    render() {
        return (
            <div className="outside"> Some elements outside of the dialog </div>
            <Modal isOpen={this.props.modalOpen}>
                <div className="inside"> Content of dialog </div>
            </Modal>
         );
    } 
}

我想像这样测试内容(在本例中使用 jest )

import React from 'react'
import MyModal  from './MyModal'
import { mount } from 'enzyme'

it('renders correctly', () => {
    const wrapper = mount( <MyModal modalOpen/> );

    expect(wrapper).toMatchSnapshot();

    // Passes
    expect(wrapper.find('.outside')).toHaveLength(1);

    // Fails, 0 length
    expect(wrapper.find('.inside')).toHaveLength(1);
});

测试正确找到了 Modal 之外的内容,但没有找到里面的任何内容。查看快照表明,<Modal> 内确实没有任何内容。被渲染。但是,如果我替换 mount 它确实有效与 shallow 。问题是我需要 mount测试生命周期方法,如 componentDidMount .

为什么不mount渲染模式的内容?我认为重点在于它渲染了整个子元素树。

最佳答案

编辑:这在 React 16 + Enzyme 3 中不再是问题,因为 React 16 supports portal components .

在 React 15 及之前版本中,问题在于模式对话框(在大多数实现中)是 portal成分。这意味着它创建直接附加到文档根的 DOM 元素,而不是父 React 组件的子元素。

ReactWrapperfind 方法create by mount 从顶级组件创建的元素开始查找 DOM,因此它找不到模态框的内容。但 Enzyme 的 shallow 并不附加到 DOM,而是构建自己的包含模式内容的组件树。

要测试门户组件,您首先需要找到已附加到文档正文的 DOM 元素。然后您可以围绕它们创建一个新的 ReactWrapper ,以便所有常用的 Enzyme 功能都可以工作:

import React from 'react'
import MyModal  from './MyModal'
import { mount, ReactWrapper } from 'enzyme'

it('renders correctly', () => {
    const wrapper = mount( <MyModal modalOpen/> );

    expect(wrapper).toMatchSnapshot();

    // Passes
    expect(wrapper.find('.outside')).toHaveLength(1);

    // Construct new wrapper rooted at modal content
    inside_els = document.getElementsByClassName("inside")[0]
    inside_wrapper = new ReactWrapper(inside_els, true)

    // Passes
    expect(inside_wrapper.find('.inside')).toHaveLength(1);
});

目前,这是 open bug在 enzyme 中。

更新:测试完成后,Enzyme 似乎还会将模态附加到 DOM,因此您最终可能会在稍后的测试中打开多个对话框。如果这是一个问题,您可以在每次测试后清除 DOM,如下所示:

afterEach(() => {
  var node = global.document.body;
  while (node.firstChild) {
    node.removeChild(node.firstChild);
  }
}); 

关于reactjs - React 模式对话框的内容不可用于使用 mount() 的 enzyme 测试,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45644244/

相关文章:

reactjs - React.js 样式组件导入图像并将其用作 div 背景

javascript - 为什么我的导航栏折叠切换在 react 中不起作用

c# - xUnit.net 和 Debug.Assert

html - 单击链接后是否可以关闭 Bootstrap 模式?

javascript - 当我链接到 React.js 中的不同页面时,我如何传递一个数字?

javascript - 检查子组件是否呈现 - Jest, Enzyme

java - 如何使用 XMLUnit 只比较文件的某些部分?

Javascript 混淆和模态框

iphone - 关闭 GameKit 模态视图

javascript - 通知父组件子组件的连接状态