我正在使用赛普拉斯cy.get
来抓取元素,但是如果没有,我的测试就失败了。我不希望它失败。我希望它继续下去。测试只是列出那里的项目(如果有的话)。
const listItemTitle = '[data-cy-component=list-item-title]';
cy.get(listItemTitle).each(($el, index, $list) => {
cy.wrap($el).then(($span) => {
const spanText = $span.text();
cy.log(`index: ` + index + ' ' + spanText);
});
});
我会认为,如果那里没有元素 - 这段代码仍然可以,但事实并非如此。当我运行它时,我收到此错误:CypressError: Timed out retrying: Expected to find element: '[data-cy-component=list-item-title]', but never found it.
它在存在元素的地方工作正常。如果没有找到元素,我想继续做一个不同的测试。
这是我尝试过的一个实验:
let count: number = Cypress.$(listItemTitle).length;
cy.log('before:' + count);
cy.get(actionsBarActionsAdd).click();
cy.get(singlePickerSearch).type('Assets' + '{enter}');
cy.get(listItemCheckboxTitle)
.first()
.click();
cy.toast({
type: 'Success',
});
count = Cypress.$(listItemTitle).length;
cy.log('after:' + count);
cy.get(listItemTitle).each(($li, index, $lis) => {
cy.log('interface no. ' + (index + 1) + ' of ' + $lis.length);
cy.wrap($li).click();
});
结果是这样的:
18 LOG before:0
19 GET [data-cy-component-key="actions-add"] input
20 CLICK
21 GET [data-cy-component=single-picker-search] input
22 TYPE Assets{enter}
23 GET [data-cy-component="list-item-checkbox-title"]
24 FIRST
25 CLICK
26 GET .iziToast toast2
27 ASSERT expected [ <div.iziToast.iziToast-opening.fadeInUp.iziToast-theme-
alloy.iziToast-color-green.iziToast-animateInside>, 1 more... ] to have class iziToast-color-green
28 LOG after:0
29 GET [data-cy-component=list-item-title]
30 LOG interface no. 1 of 1
最终表明Cypress.$(listItemTitle).length
不会使用选择器计算元素的数量:listItemTitle。
更新:
通过放置一个cy.wait(1000)
;在执行Add之后(在我的实验中) - 给DOM时间更新 - 找到了新元素。使用更具体的选择器,不需要等待
你可以通过 Cypress.$
使用 jquery 来检查是否存在。
const listItemTitle = '[data-cy-component=list-item-title]';
if (Cypress.$(listItemTitle).length > 0) {
cy.get(listItemTitle).each(($el, index, $list) => {
cy.wrap($el).then(($span) => {
const spanText = $span.text();
cy.log(`index: ` + index + ' ' + spanText);
});
});
}
赛普拉斯 12 的更新
理想的方法是使用Gleb Bahmutov的cypress-if,但由于Cypress版本12的更改,它目前被阻止了。
这个问题正在处理中,但与此同时,这里有一个关于.should()
的黑客,它通过重试执行检查,但在没有元素出现时不会失败 - 基于 @M.Justin 的方法。
let start = Date.now()
const commandRetry = ($subject, {assert, timeout}) => {
const elapsed = Date.now() - start
console.log(elapsed, assert($subject))
if (elapsed < timeout && !assert($subject)) {
const err = new Error('Retry')
err.isDefaultAssertionErr = true
throw err
}
}
cy.get('li')
.should($subject => commandRetry($subject, {
assert: ($subject) => $subject.length > 0,
timeout: 3000
}))
.should("have.length.gte", 0)
.then($subject => cy.log(`Found ${$subject.length} items`))
下面是我用来测试它的网页。它最初没有<li>
元素,两秒钟后添加一个。
您可以看到测试在控制台中重试断言,并在 2 秒后通过。
如果注释掉页面上的脚本,因此不添加任何<li>
,则会看到测试运行 4 秒,但不会失败。
如果这两种情况都记录正确的元素计数。
<ul></ul>
<script>
setTimeout(() => {
const ul = document.querySelector('ul')
const li = document.createElement('li')
li.innerText = 'A list item'
ul.appendChild(li)
}, 2000)
</script>
cy.get(".field").should("have.length", 0)
我有一个类似的情况:如果没有找到元素,我希望测试成功,但如果有元素,我需要用 should.我遇到了这个问题,根据贾斯汀先生的回答,我想出了以下内容:
cy.get('td:eq(0) i').should("have.length.gte", 0).then (($hits) => {
cy.log ('number of hits: ' + $hits.length)
if ($hits.length == 0) {
cy.log ('no hits OK');
cy.wrap (true);
}
else {
cy.log ('hits. test hits....');
// this is only an example
cy.wrap($hits).should('have.css',
'color').and('equal', 'rgb(170, 181, 0)');
}
});
以下内容检索项目,即使没有项目:
cy.get(listItemTitle).should("have.length.gte", 0)
请注意,如果页面仍在加载项目,这不会等待项目存在,因此可能会在元素存在之前返回。 当您知道这些项目已经加载时,应该可以安全使用。
这种模式很容易导致有问题的测试,因此要小心何时以及如何使用它。
我们可以使用此解决方案在 DOM 中查找可选元素。
我将其添加为常量函数。
`export const optionalFindingElement = (element: string) => {
return Cypress.$(element).length;
};
`
然后像这样使用它:
`Given('There are not assets generated by cypress in the kanban', () => {
const assetNumber = optionalFindingElement('[data-fx-name="assetName"]');
if (assetNumber > 0) {
// Do something if the element was found
} else {
// Do something if the element was not found
}
});
'
干杯!