提问人:automation-ninja 提问时间:10/30/2023 最后编辑:automation-ninja 更新时间:10/31/2023 访问量:78
Cypress 分页处理
Cypress pagination handling
问:
我想首先获取当前页面上完整元素列表的 #product_list,然后找到此列表中的每个元素 如果元素 .ajax_block_product.col-xs-12.col-sm-4.col-md-3[data-id-product='22578'] 在第一页中,请单击它,否则单击页面底部的 #pagination_next_bottom 按钮,然后在其他页面中再次搜索以查找 #product_list 元素中存在的元素
我尝试使用此功能,但它只找到每个页面并在不单击所需元素的情况下进行导航。
// findItem("Printer Brother MFP Laser HL1222WEYJ1");
// function findItem(value) {
// let found = false;
// let attempts = 0;
// const maxAttempts = 20; // Define a maximum number of attempts
// function clickNext() {
// cy.get("#pagination_next_bottom").click()
// cy.wait(5000);
// }
// function findInPage() {
// if (found || attempts >= maxAttempts) {
// return; // If item found or max attempts reached, exit
// }
// cy.get("#product_list li div.produkti h5").each(itemNameEl => {
// const itemText = itemNameEl.text();
// console.log(itemText);
// if (itemText === value) {
// found = true;
// cy.get(itemNameEl).should('be.visible').click(); // Click the parent element of the product
// return false;
// }
// });
// if (!found) {
// clickNext(); // Click the "Next" button
// attempts++; // Increment attempts
// findInPage(); // Continue searching on the next page
// }
// }
// findInPage();
// }
答:
代码中的问题是,检查是否找到对象的行 () 是同步的,并且在 Cypress 执行(异步)之前运行,并可能更新 的值。因为您是在同步函数中执行 Cypress 命令,所以我建议使用 Cypress 自定义命令来处理您的递归。if (!found)
found
Cypress.Commands.add("findItem", (value, attempt) => {
let currAttempt = attempt ?? 0;
const maxAttempts = 20;
if (attempt < maxAttempts) {
let found = false;
cy.get("#product_list li div.produkti h5")
.each(($item) => {
const itemText = $item.text();
console.log(itemText);
if (itemText === value) {
found = true;
return false;
}
})
.then(() => {
if (!found) {
cy.get("#pagination_next_bottom").click();
cy.wait(5000);
cy.findItem(value, currAttempt++);
} else {
cy.wrap($item).should("be.visible").click(); // Click the parent element of the product
}
});
} else {
expect(true === false); // placeholder assertion to fail if too many attempts are made
}
});
此外,将行移动到块可以使块完全同步,并且不会与任何 Cypress 命令竞争执行时间。cy.wrap($item)...
.then()
.each()
有两件事可能是问题(因为没有发生点击)
itemText === value
这可能需要不精确匹配,例如由于空格字符itemText.includes(value)
cy.get('itemNameEl')
也许需要,虽然我不相信这一点cy.wrap('itemNameEl')
递归代码看起来不错,但请记住 Cypress 命令是异步的,因此您需要等待它们完成,然后再进行 .get/each
if (!found)
这适用于两个地方
- 之前
if (!found)
clickNext()
- 在顶部
if (found || attempts >= maxAttempts)
您不需要,只需检查变量并允许函数删除并完成(如果已设置)。return
found
found
用包装器做这两件事。cy.then()
let found = false;
let attempts = 0;
const maxAttempts = 20;
function clickNext() {
cy.get("#pagination_next_bottom").click()
cy.get("#product_list li div.produkti h5", {timeout:5000})
.should('have.length.gt', 0)
}
function findInPage() {
cy.then(() => { // to exit when found wrap this check
if (!found && attempts < maxAttempts) {
cy.get("#product_list li div.produkti h5").each(itemNameEl => {
if (itemNameEl.text() === value) {
found = true;
cy.get(itemNameEl)
.parent() // NOTE <h5> parent
.should('be.visible').click();
return false;
}
})
cy.then(() => { // wrap this check to allow get/each to complete
if (!found) {
clickNext();
attempts++;
findInPage();
}
})
}
})
}
您可以将 替换为检查页数,或者检查页码元素。cy.wait(5000)
cy.get("#product_list li div.produkti h5").should('have.length.gt', 0)
Timeout 总是比 好。cy.wait()
也许还可以为找到的元素添加别名,并在搜索完成后单击它。
通常,应尝试将查询代码与操作代码分开,因为操作可能会更改 DOM 并使已运行的查询无效。
function findInPage(value) {
...
if (itemText === value) {
found = true;
cy.get(itemNameEl).parent().as('product')
}
findInPage();
cy.get('@product').should('be.visible').click()
如果您对递归感到有点沮丧,请尝试使用 cypress-recurse 插件。
最简单的代码如下:
const itemsSelector = '#product_list li div.produkti' // leaving off h5
const nextPageSelector = '#pagination_next_bottom'
const value = 'Printer Brother MFP Laser HL1222WEYJ1'
recurse(
() => cy.get(itemsSelector),
(items) => expect(items).to.contain(value),
{
post: () => cy.get(nextPageSelector).click()
}
)
.contains(value) // filter down to one item
.click()
笔记:
- 这个 recurse() 返回页面上的所有项目,所以用
.contains()
- 它之所以有效,是因为您的值非常独特,但如果它可以部分出现在其他项目中,则必须使用
expect(items).to.contain(value)
.each()
评论