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

升级React18/Next.js13后Cypress点击测试突发失败

解决React 18 + Next.js 13升级后Cypress测试的DOM元素脱离问题

问题背景

项目升级React 18、Next.js 13后,开启React严格模式的开发环境下,Cypress测试持续抛出element has detached from the DOM错误,核心问题集中在MUI 5组件的交互上:

  • 对话框内的MUI复选框执行click()后无报错,但实际未选中,添加cy.wait()可临时生效但不优雅
  • MUI Card组件的链接点击直接失败,添加等待后测试变得不稳定,还影响其他原本正常的测试

测试代码参考

// 测试代码
cy.getBySel('more-filters-button').click(); // 打开MUI对话框模态框
cy.get('input[name="condition"][value="New"]').click(); // 获取Checkbox组件并点击
cy.getBySel('save-filter-modal').click(); // 点击按钮关闭模态框
cy.getBySel('vehicle-card-link').first().click(); // 获取首个MUI Card并点击链接
cy.getBySel('vehicle-name').should('exist'); // 验证新页面的指定元素已加载

// commands.js 自定义命令
Cypress.Commands.add('getBySel', (selector, args, operator = '') => cy.get(`[data-cy${operator}=${selector}]`, { ...args }));

关键信息

  • 仅升级分支出现问题,其他PR测试稳定无异常
  • 仅部分MUI组件测试失败,同类型其他组件测试正常
  • 疑似与React 18严格模式的双重渲染/卸载重挂载机制有关

解决方案

1. 确保操作最新DOM元素,避免缓存失效

React严格模式下组件会被卸载后重新挂载,Cypress之前获取的元素会直接失效。建议给MUI组件添加专属data-cy标记,每次操作前重新查询并验证元素状态:

// 给MUI Checkbox组件添加data-cy="condition-new-checkbox"
cy.getBySel('more-filters-button').click();
// 先验证元素可见,确保获取最新DOM节点
cy.getBySel('condition-new-checkbox').should('be.visible').click();
cy.getBySel('save-filter-modal').click();

// Card链接点击:强制点击+前置状态验证
cy.getBySel('vehicle-card-link')
  .first()
  .should('be.visible')
  .click({ force: true }); // 强制点击可绕过部分DOM状态检测问题

2. 临时关闭React严格模式定位问题

在Next.js 13的next.config.js中关闭严格模式,验证是否为双重渲染导致的问题:

module.exports = {
  reactStrictMode: false,
};

注意:此方法仅用于调试定位,生产环境建议保持严格模式以检测潜在问题。

3. 使用真实浏览器点击替代模拟事件

Cypress原生click()是模拟DOM事件,对React重渲染后的元素兼容性较差。可以使用cypress-real-events插件触发真实浏览器点击:

  1. 安装插件:
npm install cypress-real-events --save-dev
  1. 在cypress/support/e2e.js中导入:
import 'cypress-real-events/support';
  1. 修改测试代码:
cy.get('input[name="condition"][value="New"]').realClick();
cy.getBySel('vehicle-card-link').first().realClick();

4. 等待组件状态稳定后再操作

针对模态框关闭后的DOM更新,等待列表重新渲染完成再执行后续操作:

cy.getBySel('save-filter-modal').click();
// 等待筛选后的车辆列表加载完成(根据实际业务调整断言)
cy.getBySel('vehicle-card-link').should('have.length.greaterThan', 0).first().click();

原理说明

React 18严格模式在开发环境下会双重执行组件挂载、更新逻辑,并主动卸载后重新挂载组件,导致Cypress缓存的DOM节点被标记为“脱离DOM”。此时需要确保每次操作前获取最新的DOM节点,或使用更贴近真实用户交互的事件触发方式。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 03:50:26