赛普拉斯断言 - 元素是可操作的/未被覆盖

Cypress assertion - element is actionable / not covered

我想扩展 this question 因为我有一个类似的问题:

我想 cy.get('#lead_name').type('foo') 但在加载表单时它被不透明度为 0.9 的元素覆盖:

<div class="blockUI blockOverlay" style="z-index: 1000; border: none; margin: 0px; padding: 0px; width: 665px; height: 100%; top: 0px; left: 0px; background-color: rgb(0, 0, 0); opacity: 0.9; cursor: wait; position: absolute;"></div>

当我开始断言时

cy.get('#lead_name').should('be.visible)

它通过了断言(可能是因为不透明?)但是当我尝试在该字段中键入内容时,我收到错误消息,指出该元素已被覆盖。

当我尝试断言叠加层不再存在并添加

cy.get('.blockUI blockOverlay').should('not.exist')

赛普拉斯也通过了断言,即使该元素确实存在并覆盖了另一个元素并且 cy.get('#lead_name').type('foo') 失败。

有什么办法可以解决这个问题吗

//This does not work it's just a sample to explain what I want to do
//test if the element I want to get is not covered
cy.get('#lead_name').should('not.be.covered')
//or test if the element is actionable
cy.get('#lead_name').should('be.actionable')

确保它等到表单加载完毕?

{edit} 这是我从 Cypress 收到的错误消息:

Timed out retrying after 4000ms: cy.type() failed because this element:

<input name="CrmLead[first_name]" id="CrmLead_first_name" type="text" maxlength="255">

is being covered by another element:

<div class="blockUI blockOverlay" style="z-index: 1000; border: none; margin: 0px; padding: 0px; width: 665px; height: 100%; top: 0px; left: 0px; background-color: rgb(0, 0, 0); opacity: 0.9; cursor: wait; position: absolute;"></div>

{edit 2} 这是我使用的代码,浓缩为相关部分:

it('should select new lead', () {
cy.visit(Cypress.env('lead_url'))
cy.get('#new_lead).click() //this opens the new form which takes some time to load
cy.get('#lead_name').type('foo')
cy.get('#lead_last_name').type('bar')
cy.get('.button').click()
}

{edit 3} 我对可能的解决方案进行的测试越多,我就越确信问题不在于覆盖层,而在于赛普拉斯代码本身。

当我手动打开表单时,加载微调器消失的时间不会超过一秒,通常只需 0.1-0.2 秒。

然而,当 Cypress 打开表单时,表单无法正确加载,因为加载微调器会无限期地停留在那里。

您可以将 {force: true}type() 一起使用。这将忽略其他元素的重叠。

cy.get('#lead_name').type('foo', {force: true})

或者如果你想断言元素有 opacity 0.9 你可以使用:

cy.get('.blockUI blockOverlay')
  .should('have.attr', 'style')
  .and('include', 'opacity: 0.9')

或者,您可以等待元素不具有不透明度,在这种情况下您可以使用:

cy.get('.blockUI blockOverlay', {timeout: 7000})
  .should('have.attr', 'style')
  .and('not.include', 'opacity: 0.9')

overlay 的检查应该分两步完成。

cy.get('.blockUI.blockOverlay')
  .should('exist')
  .then($overlay => $overlay.remove()) 
cy.get('.blockUI.blockOverlay').should('not.exist')

cy.get('#lead_name', {timeout: 10000})
.should(($el) => {                    // should will cause retry
  return Cypress.dom.isFocusable($el) // instead of visible, more relevent to actionability
})

如果您只执行第二步,Cypress 会在 覆盖层出现之前 传递该命令。

这与检查加载微调器的原理相同,之前已在 SO 上解决。

顺便说一下,您正在选择一个具有两个分类的元素(根据错误消息),因此您需要在选择器中使用两个 .

也许这是您唯一需要的改变!


我在上面添加了另一项可能有帮助的检查。 Cypress.dom.isFocusable.

来自文档 Is focusable

Cypress internally uses this method everywhere to figure out whether an element is hidden, mostly for actionability.


如果您真的卡住了,请在此处观看 Gleb Bahmutov 的演练视频 Debug the Element Visibility Problems in Cypress


还有一个想法-您可以尝试在测试中删除覆盖层-在上面的示例中添加一行。