Cypress断言 - 元素可操作/未被覆盖

5
我想进一步讨论这个问题,因为我有一个类似的问题:
我想要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')

即使元素存在且覆盖其他元素,Cypress 也会通过断言,而 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>

{编辑 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()
}

{编辑3}我测试了很多可能的解决方案后,越来越确信问题不在叠加层上,而是Cypress代码本身存在问题。

当我手动打开表单时,加载旋转图标消失的时间从未超过一秒钟,通常只需0.1-0.2秒钟。

然而,当Cypress打开表单时,表单无法正常加载,因为加载旋转图标一直停留在那里。


你能提供一个完整的示例代码,以便我们可以重现你的问题吗? - Joshua
完整的代码非常长,使用了POM,但我将相关部分的代码添加到了我的OP中。 - cypher_null
很遗憾,我无法提供应用程序本身的链接,因为它是私有的 :( - cypher_null
我认为你可以使用.invoke('show')来改变元素的状态。这里有一个简短的视频,解释了如何做到这一点。https://testautomationu.applitools.com/advanced-cypress-tutorial/chapter4.html - ItsNotAndy
谢谢。我尝试了这个命令cy.get('#lead_portlet').invoke('show'),虽然它按预期触发了,但它并没有改变被覆盖的Overlay的事实 :( - cypher_null
2个回答

5
检查覆盖层应该分两步进行。
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在各处内部使用此方法来确定元素是否隐藏,大多数用于可操作性。


如果你真的卡住了,可以看一下Gleb Bahmutov在这里的演示视频 Debug the Element Visibility Problems in Cypress


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


首先,是的。我犯了一个非常愚蠢的错误。cy.get('.blockUI.blockOverlay').should('exist') 当然是正确的语法。 - cypher_null
然而,这个解决方案似乎仍然不起作用,因为cy.get('.blockUI.blockOverlay').should('not.exist')只会在覆盖层仍然存在时导致测试失败。超时重试4000毫秒后:期望DOM中不存在<div.blockUI.blockOverlay>,但它一直被找到 - cypher_null
当表单稳定下来时,覆盖层会消失吗?(在浏览器中,而不是在测试中) - user16695029
1
到目前为止,我已经相当确信我需要解决潜在的问题,而不是覆盖它:“为什么Cypress加载表单会破坏页面?” - cypher_null
我将您的答案标记为解决方案,因为我真的认为它可以解决原始问题。然而,经过越来越深入的研究,我确信我的问题是与原始问题无关的其他问题。但是,这个问题中的答案对于有类似问题的人仍然可能有帮助! - cypher_null
显示剩余6条评论

2
您可以在 type() 中使用 {force: true}。这将忽略其他元素的重叠。
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')

我也一直在考虑这个问题。这只是最后的选择,因为我更喜欢在开始测试之前完全加载表单。 - cypher_null
那么在表单完全加载后,覆盖部分就消失了吗? - Alapan Das
你可以这样做,检查元素是否没有不透明度,并设置一个超时时间,这样Cypress会等待超时值以确保元素没有不透明度。已更新答案。 - Alapan Das
它变得更奇怪了:超时重试7000毫秒后:期望值为'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;',但不包括'opacity: 0.9'错误消息中明确指出它包含opacity 0.9。 - cypher_null
cy.wait('20000') 会等待20秒,其也可以等待毫秒。但请避免使用 cy.wait,因为它会带来不稳定性。同时,在经过7000毫秒后,透明度似乎仍未被移除,这在您的错误消息中已正确提到。您尝试将超时时间从7000增加到9000了吗? - Alapan Das
显示剩余6条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接