[英]Cypress wait for an element to be loaded inside a foor loop
我有一個數組,其中的項目是一堆按鈕元素。 我想調用一個按鈕,然后等待一個元素(在 dom 中)被加載。
加載該元素后,只有我想進入下一次迭代(單擊下一個按鈕/元素)
在我當前的實現中,一次單擊所有按鈕。 但我希望一次單擊一個按鈕。
cy.document().then(document => {
const arra = [...document.querySelectorAll('.instances__action')];
for (let i = 1; i <= arra.length; i++) {
let state = document.querySelector(
`#root > section > section > main > div > div > section.instances > div > div > div > div > div > div > table > tbody > tr:nth-child(${i}) > td:nth-child(3) > span`
).innerText;
document
.querySelector(
`#root > section > section > main > div > div > section.instances > div > div > div > div > div > div > table > tbody > tr:nth-child(${i}) > td:nth-child(7) > div > button.ant-btn.ant-btn-primary.ant-btn-sm`
)
.click();
cy.wait(2000);
cy.waitUntil(() => {
cy.get(
`#root > section > section > main > div > div > section.instances > div > div > div > div > div > div > table > tbody > tr:nth-child(${i +
1}) > td:nth-child(3) > span`
).contains('Finished');
});
}
});
});
@jmargolisvt 是正確的,如果您將 .click .click()
操作更改為 Cypress 命令,您應該獲得正確的操作序列。
命令執行順序和測試循環
可以這樣想——上面的測試代碼像普通的 javascript 一樣運行,每個cy.X()
命令都會將一個命令放入隊列中。 命令保證按隊列順序依次運行,但不與測試代碼同步。
因此, cy.wait(2000)
並沒有減慢 for 循環的速度,而是暫停了隊列執行。
等待斷言
另請注意,命令具有對其斷言的內置等待,因此在這種情況下您可能不需要cy.wait()
或cy.waitUntil()
。 您可以使用timeout
選項控制等待的最長時間。
循環
如果將內部部分轉換為命令,for 循環將正常工作,但您也可以將循環本身轉換為 IMO 更簡潔的cy.get().each()命令。
測試異步內容
最后,在等待異步內容時,更喜歡cy.contains('mySelector', 'myContent')
命令而cy.get('mySelector').contains('myContent')
命令。
原因是cy.get('mySelector').contains('myContent')
只等待元素mySelector
,但它已經在 DOM 中。 如果內容正在異步更改,此命令將立即測試舊內容(假設為空)並通過測試失敗。
const tbodySelector = '#root > section > section > main > div > div > section.instances > div > div > div > div > div > div > table > tbody';
const buttonSelector = 'td:nth-child(7) > div > button.ant-btn.ant-btn-primary.ant-btn-sm';
const spanSelector = 'td:nth-child(3) > span'
cy.get('.instances__action').each(($el, i) => {
cy.get(`${tbodySelector} > tr:nth-child(${i+1}) > ${buttonSelector}`)
.click();
cy.contains(
`${tbodySelector} > tr:nth-child(${i+1}) > ${spanSelector}`,
'Finished',
{ timeout: 2000 } // increase timeout if a longer wait is required
);
});
注意jQuery 的:nth-child(index)
選擇器從索引 1 開始,但是.each(($el, i) =>
具有從零開始的索引,因此必須在這些選擇器中使用i+1
。
這是我用來測試的模擬 DOM。 在一個干凈的 Cypress 項目中,將它放在文件夾<project root>/app
。
<table>
<tbody>
<tr class="instances__action">
<td>
<button id="myBtn1"></button>
</td>
<td>
<span id="mySpan1"></span>
</td>
</tr>
<tr class="instances__action">
<td>
<button id="myBtn2"></button>
</td>
<td>
<span id="mySpan2"></span>
</td>
</tr>
</tbody>
</table>
<script>
document.getElementById("myBtn1").addEventListener("click", function() {
setTimeout(() => {
document.getElementById("mySpan1").innerHTML = "Finished";
}, 1000)
});
document.getElementById("myBtn2").addEventListener("click", function() {
setTimeout(() => {
document.getElementById("mySpan2").innerHTML = "Finished";
}, 500)
});
</script>
注意上面的嵌套被簡化了,所以我適當地改變了選擇器的內容。
測試上面的 HTML 片段
it('clicks buttons and waits for finished flag', () => {
cy.visit('app/iterate-table-buttons.html')
const tbodySelector = 'tbody';
const buttonSelector = 'td:nth-child(1) > button';
const spanSelector = 'td:nth-child(2) > span'
cy.get('.instances__action').each(($el, i) => {
console.log(`starting #${i}`)
cy.get(`${tbodySelector} > tr:nth-child(${i+1}) > ${buttonSelector}`)
.then(() => console.log(`clicking #${i}`))
.click();
cy.contains(
`${tbodySelector} > tr:nth-child(${i+1}) > ${spanSelector}`,
'Finished',
{ timeout: 2000 } // increase timeout if a longer wait is required
)
.then(() => console.log(`asserting #${i}`))
});
})
柏樹日志
這就是 Cypress 日志的樣子。
全部為綠色,並且只有在完成文本出現后才能看到點擊。
控制台日志
這就是控制台日志的樣子。
循環在命令隊列開始之前執行到完成,但沒關系,因為命令仍在以正確的順序執行。
開始#0
開始#1
點擊#0
斷言#0
點擊#1
斷言#1
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.