Cypress测试Next.js预渲染React应用如何捕获hydration阶段加载屏?
解决方案
- 调整查询配置,新增超时和隐藏元素捕获参数
测试偶发失败的核心原因是双通渲染下,加载屏的存在窗口较短,Cypress默认4秒超时和忽略隐藏元素的规则可能刚好错过加载屏的捕获时机。给findByRole查询新增timeout参数延长等待窗口,添加includeHiddenElements: true配置捕获刚插入DOM还未移除隐藏属性的加载节点。 - 增加加载屏消失的断言确保渲染阶段完成
在完成加载屏的存在校验后,新增断言等待加载屏完全卸载,再执行后续表单操作,避免Cypress在渲染过渡阶段查询后续节点引发不稳定。 - 非必要场景可跳过加载屏存在校验
如果你的测试不需要验证加载屏是否正常渲染,可直接断言加载屏不存在,无需校验它的出现过程,彻底规避错过渲染窗口的问题。
调整后稳定的测试代码示例
// using @testing-library/cypress it('Some of my tests', () => { cy.visit('http://localhost:4000/annotation/edit'); // 捕获加载屏,调整配置避免漏捕 cy.get('div#__next').findByRole('alert', { name: /loading/i, timeout: 10000, includeHiddenElements: true }); // 等待加载阶段完全结束 cy.findByRole('alert', { name: /loading/i }).should('not.exist', { timeout: 10000 }); cy.findByRole('form', { name: /sign in form/i }).within(() => { cy.findByRole('textbox', { name: /account name/i }).type('...'); cy.findByRole('textbox', { name: /email/i }).type('...'); cy.findByLabelText(/password/i).type('...'); cy.findByRole('button', { name: /sign in/i }).click(); }); cy.findByRole('progressbar'); });
可选:直接获取当前DOM状态的方式
如果需要自行判断当前DOM的渲染状态,可以通过then回调获取挂载节点的DOM内容自行处理,不推荐常规场景使用,会引入条件测试的不稳定风险:
cy.get('div#__next').then($root => { const hasLoadingAlert = $root.find('[role="alert"][aria-label*="loading"]').length > 0; // 自行编写后续逻辑 });
不推荐使用固定时长的
cy.wait()做节流控制,固定等待时间会拉长测试执行耗时,且无法适配不同环境下的渲染速度差异,依然可能出现偶发失败。
内容的提问来源于stack exchange,提问作者BaHwan Han
相关产品推荐
相关产品推荐

