React中使用Enzyme如何定位渲染在root外的Material UI模态框
问题根因
你遇到的查找失败问题是由Material UI组件的Portal挂载机制导致的:v4版本的Alert默认会把组件内容挂载到document.body节点下,不在你通过Enzyme mount渲染的组件根节点范围内,因此wrapper.find只能查询你挂载的组件树内部元素,自然找不到外部的弹窗。
可用解决方案
下面按改造成本从低到高给出3种可行方案:
方案1:禁用Alert的Portal逻辑(最推荐)
如果不需要测试Portal挂载行为,直接给Alert组件添加disablePortal属性,强制弹窗渲染在当前组件树内即可:
<Alert elevation={6} variant="filled" className='test' open={open} disablePortal // 添加这一行即可 > {children} </Alert>
修改后原测试代码不需要任何改动,wrapper.find('.MuiAlert-root')就能正常命中元素。
如果不想影响生产环境表现,可以按环境动态配置:disablePortal={process.env.NODE_ENV === 'test'}
方案2:直接从全局DOM查询
如果不能修改业务代码,可以直接从document对象查找挂载到body的弹窗,不需要通过Enzyme的wrapper查询:
const wrapper = mount(<Page/>); wrapper.find('my-id').hostNodes().simulate('click'); // 直接用原生DOM查询 const alertDom = document.querySelector('.MuiAlert-root'); expect(alertDom).not.toBeNull(); // 验证文本内容 expect(alertDom.textContent).toContain('hihi');
方案3:统一挂载容器
如果需要保留Portal逻辑进行完整测试,可以指定Alert的挂载容器和Enzyme的挂载容器为同一个节点:
// 测试代码中提前创建挂载节点 const mountNode = document.createElement('div'); document.body.appendChild(mountNode); const wrapper = mount(<Page />, { attachTo: mountNode }); // 业务代码中给Alert指定container为该挂载节点 // <Alert container={mountNode} ... />
注意事项
如果模拟点击后还是查询不到,可以在断言前调用wrapper.update()强制同步组件渲染状态,排除状态更新不及时的问题。
内容的提问来源于stack exchange,提问作者Asking
相关产品推荐
相关产品推荐

