Cypress.io中元素条件检查问题:if条件无法正常生效
如何在Cypress中正确判断弹窗关闭按钮是否存在并关闭?
我现在遇到个麻烦:网页里有个弹窗,当特定cookie存在时不会显示,但这个cookie的名称带GUID,我没法提前获取到它。我想做的是检查弹窗是否存在,存在就关闭,不存在就跳过,但试了几种基于body元素的写法都有问题:
比如这段代码:
cy.get("body").then($body => { if ($body.find('[data-id="guide-close-button"]').length) { cy.get('[data-id="guide-close-button"]').click(); } else { assert.isOk('everything','everything is OK'); } })
还有类似的用has的版本:
cy.get("body").then($body => { if ($body.has('[data-id="guide-close-button"]')) { cy.get('[data-id="guide-close-button"]').click(); } else { assert.isOk('everything','everything is OK'); } })
这些代码要么是按钮明明存在却没触发点击,要么是弹窗已经关闭时直接超时失败。我不想用忽略错误的方式绕过去,想找个“正确”的解决办法,请问该怎么做?
问题出在哪?
你之前的写法踩了Cypress命令队列的坑:当你在then里用cy.get()时,Cypress会重新查询DOM,但如果此时弹窗已经消失(或者一开始就不存在),cy.get('[data-id="guide-close-button"]')会因为找不到元素而超时,直接导致测试失败。另外,$body.has()返回的是jQuery对象,在if判断里永远为真,这也是为什么你的断言没生效的原因。
正确的解决方案
下面两种方法都能完美解决你的需求,选哪种都可以:
方法1:使用Cypress.$直接同步查询DOM
这种方式直接在当前DOM快照里检查元素,不会触发Cypress的重试机制,适合这种“存在就操作,不存在就跳过”的场景:
// 同步检查按钮是否存在 const closeButtonExists = Cypress.$('[data-id="guide-close-button"]').length > 0; if (closeButtonExists) { cy.get('[data-id="guide-close-button"]').click(); } else { // 这里可以加个日志或者直接跳过,不需要断言 cy.log('弹窗关闭按钮不存在,跳过操作'); }
方法2:使用cy.get()结合should('exist')的可选断言
Cypress 12+支持给断言加optional修饰符,这样如果元素不存在也不会失败,而是返回null,你可以基于这个结果来判断:
cy.get('[data-id="guide-close-button"]', { timeout: 3000 }) // 可以设置短一点的超时,避免等太久 .should('be.visible') .optional() .then($button => { if ($button) { $button.click(); // 直接用jQuery对象点击,避免重新查询 } else { cy.log('没有找到弹窗关闭按钮'); } });
额外提示
如果你不想每次都写这段代码,可以把它封装成一个自定义命令,放在cypress/support/commands.js里:
Cypress.Commands.add('closeGuidePopup', () => { const closeButtonExists = Cypress.$('[data-id="guide-close-button"]').length > 0; if (closeButtonExists) { cy.get('[data-id="guide-close-button"]').click(); cy.log('已关闭引导弹窗'); } });
之后在测试里直接用cy.closeGuidePopup()就行,非常方便。
内容的提问来源于stack exchange,提问作者wafflenator
相关产品推荐
相关产品推荐

