Cypress:获取JQuery值而不需要"then"或"each"



我希望有人能帮忙,但我也把这作为Cypress的讨论发布了,尽管我可能只是理解这是错误的

我需要使用列标题和同一行中另一个单元格的值来获取表单元格的Cypress.Chainable<JQuery<HTMLElement>>

以下是JQuery TS Fiddle的一个工作示例:https://jsfiddle.net/6w1r7ha9/

我目前的实现如下:

static findCellByRowTextColumnHeaderText(
rowText: string,
columnName: string,
) {
const row = cy.get(`tr:contains(${rowText})`);
const column = cy.get(`th:contains(${columnName})`)
const columnIndex = ???
return row.find(`td:eq(${columnIndex})`)
}

这个功能是必需的,因为我想写DRY代码来轻松找到用于内容验证的单元格,点击其中的元素等。

我见过的唯一的例子是https://stackoverflow.com/a/70686525/1321908,但以下不起作用:

const columns = cy.get('th')
let columnIndex = -1
columns.each((el, index) => {
if (el.text().includes(columnName) {
columnIndex = index
}
cy.log('columnIndex', columnIndex) // Outputs 2 as expected
})
cy.log('finalColumnIndex', columnIndex) // Outputs -1

我目前的想法是:

const columnIndex: number = column.then((el) => el.index())

然而,这会返回一个Chainable<number>如何将其转换为数字,我不知道。我用这个答案来指导我在这方面的思考。

在Cypress测试中使用.then()几乎是强制性的,以避免片状测试。

为了避免测试代码在网页更新之前出现问题,Cypress使用Chainable重试DOM查询,直到成功或超时。

但是Chainable接口不是一个承诺,所以你不能await它。你只能then()它。

如果你能用unchain这样的关键词来代替,那就太好了

const column = unchain cy.get(`th:contains(${columnName})`)

但不幸的是,Javascript不能用新的关键字进行扩展。只能将类似.then()的方法添加到类似Chainable的对象中。


话虽如此,仍有一些代码模式允许提取Chainable值并像使用普通Javascript变量一样使用它。

但它们仅限于特定场景,例如在before()中分配给全局,并在it()中使用它。


如果你放弃Cypress的核心功能,即自动重试功能,那么它只是jQuery,就像你在小提琴里一样(但使用Cypress.$()而不是$()(。

但即使是Mikhail的thenify,当你添加少量异步时,也依赖于测试的结构

示例应用

<foo>abc</foo>
<script>
setTimeout(() => {
const foo = document.querySelector('foo')
foo.innerText = 'def'
}, 1000)
</script>

测试

let a = cy.get("foo").thenify()
// expect(a.text()).to.eq('def')           // fails 
// cy.wrap(a.text()).should('eq', 'def')   // fails
cy.wrap(a).should('have.text', 'def')      // passes
let b = cy.get("foo")                      // no thenify
b.should('have.text', 'def')               // passes

根据您的工作示例,您需要首先获取标题,映射出文本,然后找到列的索引(我选择了"Col B"(。之后,您将找到包含另一个单元格值的行,然后获取行中的所有单元格,并对前面找到的列索引使用.eq((。

// get headers, map text, filter to Col B index
cy.get("th")
.then(($headers) => Cypress._.map($headers, "innerText"))
.then(cy.log)
.invoke("indexOf", "Col B")
.then((headerIndex) => {
// find row containing Val A
cy.contains("tbody tr", "Val A")
.find("td")
// get cell containing Val B
.eq(headerIndex)
.should("have.text", "Val B");
});

这是一个例子。

最新更新