赛普拉斯:如果找不到任何元素,我可以防止赛普拉斯cy.get失败吗?

Ste*_*ple 5 cypress

我正在使用Cypress 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);
  });
});
Run Code Online (Sandbox Code Playgroud)

我本来以为,如果那里没有任何元素,那么这段代码仍然可以,但事实并非如此。当我运行它时,出现以下错误:CypressError:重试超时:预期找到元素:“ [data-cy-component = list-item-title]”,但从未找到。

在存在元素的地方效果很好。如果未找到任何元素,我要继续进行其他测试。

这是我尝试的实验:

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();
});
Run Code Online (Sandbox Code Playgroud)

结果是:

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
Run Code Online (Sandbox Code Playgroud)

最终显示Cypress。$(listItemTitle).length不计算选择器listItemTitle的元素数量。

更新:

通过放置一个cy.wait(1000); 在执行完Add(在我的实验中)后-给DOM时间更新-找到了新元素。使用更具体的选择器,不需要等待

Fod*_*ody 25

赛普拉斯 12 更新

实现此目的的理想方法是使用 Gleb Bahmutov 的cypress-if,但由于 Cypress 版本 12 的更改,它目前被阻止。

这个问题正在解决中,但与此同时,这里有一个 hack,.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`))
Run Code Online (Sandbox Code Playgroud)

下面是我用来测试它的网页。它最初没有<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>
Run Code Online (Sandbox Code Playgroud)


Bre*_*dan 5

您可以使用jquery via Cypress.$检查是否存在。

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);
    });
  });
}
Run Code Online (Sandbox Code Playgroud)

  • 不按原样,因为您混合了同步和异步代码。有可能,这可能会帮助您更好地理解:https://docs.cypress.io/guides/core-concepts/introduction-to-cypress.html#Mishing-Async-and-Sync-code (4认同)
  • 一个潜在的差异(在您的实验中)是cy.get()具有5秒的内置重试时间,而Cypress。$(listItemTitle)是同步的。如果您在再次计数之前或者在最后一次cy.get(listItemTitle)之后计数cy.wait(5000)会怎样? (3认同)
  • 我有类似的问题,但这个答案对我不起作用,因为在运行其他任何内容之前会立即评估“if”。 (3认同)
  • Cypress.$(listItemTitle).length 没有给出您认为的答案。它不提供 listItemTitle 元素的计数。 (2认同)
  • 您确定选择器正确吗?如果它与您所期望的元素不匹配,那将解释曾经找到的0个元素。 (2认同)