You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Cypress中测试React MUI Drawer组件的open属性值

问题根因
  • 你无法获取open属性和依赖缺失无关,核心原因是MUI组件的open是React内部维护的状态props,不会直接作为原生DOM属性渲染到页面节点上,因此用should('have.attr','open')的写法永远无法匹配到对应属性。
  • 你使用的是variant="permanent"模式的永久抽屉,这类抽屉的DOM节点会一直挂载在页面中,open状态仅控制抽屉宽度、内部元素布局/透明度,不会触发DOM的挂载卸载,也不会给根节点添加原生open属性。
  • 额外提醒:你贴的组件代码存在拼写错误,ListItemText的sx属性中opeacity是错误写法,正确CSS属性为opacity,该错误会导致你控制文字显隐的样式完全不生效,需要先修复再开展测试。
关于MUI测试依赖的说明

所谓“需要引入额外依赖才能测试MUI组件”的说法,仅针对React组件单元测试场景(比如用Jest+Testing Library编写组件单测时,可能需要MUI官方提供的测试工具包辅助)。使用Cypress开展E2E测试时不需要引入任何额外依赖,E2E测试的核心原则是从真实用户视角验证可见的交互结果,不需要强绑定组件内部的状态属性。

可落地的测试方案

方案1:基于可见UI特征断言(最推荐,符合E2E测试规范)

直接断言随open状态变化的、用户可感知的UI特征,稳定性最高,也最符合E2E测试的设计初衷:

// 初始关闭状态断言
// MUI永久抽屉默认关闭宽度为64px,打开宽度为240px,如果你自定义了宽度请替换为实际值
cy.get('[name="permDrawer"] .MuiDrawer-paper').should('have.css', 'width', '64px');
cy.get('[name="permDrawer"] .MuiListItemText-root').should('have.css', 'opacity', '0');

// 触发抽屉打开操作
cy.get('.MuiToolbar-root > :nth-child(1) > .MuiButtonBase-root').click();

// 打开状态断言
cy.get('[name="permDrawer"] .MuiDrawer-paper').should('have.css', 'width', '240px');
cy.get('[name="permDrawer"] .MuiListItemText-root').should('have.css', 'opacity', '1');

你之前写的cy.get('.MuiDrawer-root > .MuiPaper-root').should('be.visible')对永久抽屉无效,因为永久抽屉无论开关状态都处于可见状态,该断言永远会通过,无法校验状态变化。

方案2:添加自定义状态标记(折中方案,稳定性高)

如果你不想依赖CSS样式特征做判断,可以在组件层面给抽屉的纸张节点添加自定义数据属性,直接把open状态映射到DOM属性上,测试时直接读取该属性即可:

// 修改Drawer组件的PaperProps配置
<Drawer
  name="permDrawer"
  open={openSideDrawer}
  style={{ zIndex: -1000 }}
  variant="permanent"
  onMouseEnter={handleMouseEnter}
  onMouseLeave={handleMouseLeave}
  PaperProps={{
    'data-automation-id': 'sideDrawerPaper',
    'data-drawer-open': openSideDrawer
  }}
>
  {/* 原有抽屉内容保持不变 */}
</Drawer>

对应测试代码可以直接写:

cy.get('[data-automation-id="sideDrawerPaper"]').should('have.attr', 'data-drawer-open', 'false');
// 触发打开点击操作
cy.get('[data-automation-id="sideDrawerPaper"]').should('have.attr', 'data-drawer-open', 'true');

方案3:读取React内部状态(不推荐,版本兼容性差)

如果一定要直接读取组件内部的open props值,可以通过DOM节点挂载的React Fiber实例获取,但这种方式依赖React的内部实现,React或MUI版本升级后很容易失效,仅作为临时方案使用:

cy.get('[name="permDrawer"]').then($el => {
  const fiberKey = Object.keys($el[0]).find(key => key.startsWith('__reactFiber$'));
  const componentProps = $el[0][fiberKey].return.memoizedProps;
  expect(componentProps.open).to.eq(true);
})
测试优化建议
  • 尽量避免使用.MuiToolbar-root > :nth-child(1)这类依赖MUI内部类名和DOM层级的选择器,MUI小版本迭代可能调整DOM结构或类名哈希规则,导致测试用例随机失败。推荐给所有需要交互、断言的元素添加data-automation-id自定义属性,基于该属性选择元素的稳定性最高。
  • 永久抽屉的zIndex设置为-1000可能会导致抽屉被其他页面元素遮挡,出现点击失效、hover不触发的问题,如果后续遇到交互异常可以优先排查该配置。

内容的提问来源于stack exchange,提问作者ManBearPig

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 00:48:20