为什么Cypress中的循环仅执行一次?附对应测试代码
问题原因
cy.contains()默认仅返回首个匹配元素:Cypress 内置的cy.contains()方法默认只会返回页面中第一个匹配指定文本的DOM元素,你代码中初始的cy.get('body').contains('Automation')实际上只查询到了1个元素,所以each循环只会执行1次。- 循环内未使用当前迭代的元素对象:你在
each的回调函数中没有使用本次迭代拿到的$el元素,反而重新执行全局的cy.get('body').contains('Automation')查询,每次查询都会拿到当前页面第一个匹配元素,逻辑上也只会操作第一个元素。 - DOM更新导致初始元素集合失效:每次执行删除操作后,页面DOM会重绘,你最开始查询拿到的元素集合是静态快照,和更新后的DOM不匹配,Cypress会丢失剩余元素的引用,无法继续后续迭代。
修复方案
首先要正确获取所有包含指定文本的元素,同时循环内直接操作当前迭代的元素,避免重复全局查询:
// 获取所有包含Automation文本的元素,可将*替换为目标元素的具体标签减少冗余匹配 cy.get('*:contains("Automation")').each(($el) => { // 直接用当前迭代的$el操作,无需重新全局查询 cy.wrap($el) .parents() .eq(1) .find('mfc-dropdown > div > mfc-button > button', { timeout: 6000 }) .first() .click({ force: true }); cy.get(this.DELETE_FILE_BUTTON).click(); cy.get('.mfc-dialog-container') .find(this.CONFIRM_DELETE) .click({ force: true }); // 等待删除操作完成,DOM更新稳定后再进入下一轮迭代,可替换为等待删除成功的状态提示更稳定 cy.wait(200); });
如果删除操作会导致剩余元素的索引变化,建议使用反向迭代避免匹配错位:
cy.get('*:contains("Automation")').then($list => { // 从最后一个元素开始删除,不会影响前面元素的索引 for(let i = $list.length - 1; i >= 0; i--) { cy.get('*:contains("Automation")').eq(i) .parents() .eq(1) .find('mfc-dropdown > div > mfc-button > button', { timeout: 6000 }) .first() .click({ force: true }); cy.get(this.DELETE_FILE_BUTTON).click(); cy.get('.mfc-dialog-container') .find(this.CONFIRM_DELETE) .click({ force: true }); cy.wait(200); } })
注意:上述代码中的通配符
*会匹配所有包含目标文本的元素,你可以根据实际情况替换为目标元素的具体标签(比如span、div),减少不必要的匹配,提升用例稳定性。
内容的提问来源于stack exchange,提问作者khiz
相关产品推荐
相关产品推荐

