乐闻世界logo
搜索文章和话题

Cypress 如何等待某个元素消失?

5 个月前提问
3 个月前修改
浏览次数41

6个答案

1
2
3
4
5
6

在Cypress中等待某个元素消失,我们通常会用到.should('not.exist')断言。这将会让Cypress重试断言直到它通过为止,即直到元素不再存在于DOM中。这是一个非常实用的特性,尤其是当进行异步操作,例如等待一个加载指示器消失之后再进行下一步操作。

例如,假设您有一个加载指示器,它在异步操作期间在页面上显示,操作完成后消失。加载指示器的HTML元素可能是这样的:

html
<div id="loading-indicator">Loading...</div>

当您想要在测试中等待这个加载指示器消失时,可以这样编写Cypress代码:

javascript
// 等待加载指示器消失 cy.get('#loading-indicator').should('not.exist');

这段代码会获取ID为loading-indicator的元素,并断言它应该不存在。Cypress会不断尝试这个断言,直到默认的超时时间(通常是4秒,但是可以通过配置进行修改)结束,如果在这段时间内元素消失了,测试就会继续进行。如果元素没有在超时时间内消失,测试将会失败。

此外,如果需要等待某个元素不可见(即它仍然存在于DOM中,但是不再是可见状态),可以使用.should('not.be.visible')断言。

例如,如果加载指示器变成了不可见状态,但没有从DOM中移除,可以这样做:

javascript
// 等待加载指示器不可见 cy.get('#loading-indicator').should('not.be.visible');

这两种方法允许你在Cypress测试中处理元素消失的情况,确保在断言和操作之间有适当的同步。

2024年6月29日 12:07 回复

IMHO the cleanest way is not to use waits nor timeouts with get, this is kinda an antipattern.

I would recommend to use Cypress waitUntil command and use something like:

shell
cy.waitUntil(function() { return cy.get('element').should('not.exist'); })

or depending on the app code you can use not.be.visible.

2024年6月29日 12:07 回复

cypress-wait-until did not work for me. I just used the basic:

shell
cy.get('.ant-drawer-body').should('not.exist');

It waits automatically.

2024年6月29日 12:07 回复

If you specifically need to wait, you could use the wait() function of cypress before making an assertion, and provide the amount of time to wait before timeout.

But note, this is an anti-pattern as you can find in the docs:

You almost never need to wait for an arbitrary period of time. There are always better ways to express this in Cypress.

That said, if your loading indicator is bound to some network request, you can wait for them to finish before making an assertion. This could be achieved with something like this example:

shell
// Wait for the route aliased as 'getAccount' to respond // without changing or stubbing its response cy.server() cy.route('/accounts/*').as('getAccount') cy.visit('/accounts/123') cy.wait('@getAccount').then((xhr) => { // we can now access the low level xhr // that contains the request body, // response body, status, etc })

More info about waiting for requests could be found here.

Also, make sure that you really want to use .should('not.exist') and not .should('not.be.visible').

2024年6月29日 12:07 回复

Loading spinner implementations often just hide the element rather than removing it from the DOM. Hence, should("not.exist") won't work for them.

cy.get("element").should("not.be.visible") is the right approach in such cases (as Diogo's answer already hinted).

2024年6月29日 12:07 回复

.findByTestId('loading-spinner-data-testid').should('not.be.visible')

This works in a similar context for me.

As of "@testing-library/cypress": "^5.3.1",

Just make sure you give your spinner component a data-testid attribute.

<LoadingSpinner data-testid='loading-spinner-data-testid'>

2024年6月29日 12:07 回复

你的答案