gpt4 book ai didi

javascript - 访问其父项被隐藏的元素 - cypress.io

转载 作者:可可西里 更新时间:2023-11-01 02:23:34 25 4
gpt4 key购买 nike

题目如题,即访问父元素被隐藏的元素。问题是,根据 cypress.io docs :

An element is considered hidden if:

  • Its width or height is 0.
  • Its CSS property (or ancestors) is visibility: hidden.
  • Its CSS property (or ancestors) is display: none.
  • Its CSS property is position: fixed and it’s offscreen or covered up.

但我正在使用的代码要求我单击一个元素,该元素的父元素是隐藏的,而该元素本身是可见的

所以每次我尝试点击这个元素时,它都会抛出一个错误:

CypressError: Timed out retrying: expected '< mdc-select-item#mdc-select-item-4.mdc-list-item>' to be 'visible'

This element '< mdc-select-item#mdc-select-item-4.mdc-list-item>' is not visible because its parent '< mdc-select-menu.mdc-simple-menu.mdc-select__menu>' has CSS property: 'display: none'

enter image description here

我正在使用的元素是一个 dropdown item,它是用 pug 编写的。该元素是在 angular-mdc-web 中定义的组件,它使用 mdc-select 作为下拉菜单,使用 mdc-select-item 作为我必须访问的元素(项目)。

类似结构的示例代码:

//pug
mdc-select(placeholder="installation type"
'[closeOnScroll]'="true")
mdc-select-item(value="false") ITEM1
mdc-select-item(value="true") ITEM2

在上面,ITEM1 是我必须访问的元素。我在 cypress.io 中的操作如下:

//cypress.io
// click on the dropdown menu to show the dropdown (items)
cy.get("mdc-select").contains("installation type").click();
// try to access ITEM1
cy.get('mdc-select-item').contains("ITEM1").should('be.visible').click();

已尝试使用 {force:true} 强制点击项目,但没有成功。尝试在父级 mdc-select 上使用 {enter} 按键选择项目,但再次失败,因为它抛出:

CypressError: cy.type() can only be called on textarea or :text. Your subject is a: < mdc-select-label class="mdc-select__selected-text">Select ...< /mdc-select-label>

还尝试使用 select command ,但这是不可能的,因为 Cypress 引擎无法将元素识别为 select 元素(因为它不是,内部工作方式不同)。它抛出:

CypressError: cy.select() can only be called on a . Your subject is a: < mdc-select-label class="mdc-select__selected-text">Select ...< /mdc-select-label>

问题mdc-select-menumdc-select-item 的父级,其属性为 display:none 在打开下拉项时通过一些内部计算。

enter image description here

此属性被覆盖为 display:flex,但这没有帮助。

enter image description here

完全没有想法。这适用于 Selenium,但不适用于 cypress.io。除了转移到其他框架或更改 UI 代码之外,有什么线索可以解决这种情况?

最佳答案

经过多次咬牙切齿,我想我找到了答案。

我认为根本原因是 mdc-select-itemdisplay:flex ,它允许它超出它的 parent 的界限(严格来说,这感觉例如 display flex 的错误应用,如果我没记错教程的话……)。

Cypress 在确定可见性时会进行大量父检查,请参阅 visibility.coffee ,

## WARNING:
## developer beware. visibility is a sink hole
## that leads to sheer madness. you should
## avoid this file before its too late.
...
when $parent = parentHasDisplayNone($el.parent())
parentNode = $elements.stringify($parent, "short")

"This element '#{node}' is not visible because its parent '#{parentNode}' has CSS property: 'display: none'"
...
when $parent = parentHasNoOffsetWidthOrHeightAndOverflowHidden($el.parent())
parentNode = $elements.stringify($parent, "short")
width = elOffsetWidth($parent)
height = elOffsetHeight($parent)

"This element '#{node}' is not visible because its parent '#{parentNode}' has CSS property: 'overflow: hidden' and an effective width and height of: '#{width} x #{height}' pixels."

但是,当使用 .should('be.visible') 时,即使我们实际上可以看到子项,我们也会遇到父属性未通过子项可见性检查的情况。
我们需要一个替代测试。

变通办法

引用 jquery.js ,这是元素本身可见性的一种定义(忽略父属性)。

jQuery.expr.pseudos.visible = function( elem ) {
return !!( elem.offsetWidth || elem.offsetHeight || elem.getClientRects().length );
}

因此我们可以将其用作替代方案的基础。

describe('Testing select options', function() {

// Change this function if other criteria are required.
const isVisible = (elem) => !!(
elem.offsetWidth ||
elem.offsetHeight ||
elem.getClientRects().length
)

it('checks select option is visible', function() {

const doc = cy.visit('http://localhost:4200')
cy.get("mdc-select").contains("installation type").click()

//cy.get('mdc-select-item').contains("ITEM1").should('be.visible') //this will fail
cy.get('mdc-select-item').contains("ITEM1").then (item1 => {
expect(isVisible(item1[0])).to.be.true
});
});

it('checks select option is not visible', function() {

const doc = cy.visit('http://localhost:4200')
cy.get("mdc-select").contains("installation type").click()

cy.document().then(function(document) {

const item1 = document.querySelectorAll('mdc-select-item')[0]
item1.style.display = 'none'

cy.get('mdc-select-item').contains("ITEM1").then (item => {
expect(isVisible(item[0])).to.be.false
})
})
});

it('checks select option is clickable', function() {

const doc = cy.visit('http://localhost:4200')
cy.get("mdc-select").contains("installation type").click()

//cy.get('mdc-select-item').contains("ITEM1").click() // this will fail
cy.get('mdc-select-item').contains("ITEM1").then (item1 => {

cy.get('mdc-select-item').contains("ITEM2").then (item2 => {
expect(isVisible(item2[0])).to.be.true //visible when list is first dropped
});

item1.click();
cy.wait(500)

cy.get('mdc-select-item').contains("ITEM2").then (item2 => {
expect(isVisible(item2[0])).to.be.false // not visible after item1 selected
});
});

})

脚注 - 使用“then”(或“each”)

您通常在 cypress 中使用断言的方式是通过命令链,它基本上包装了被测试的元素并处理诸如重试和等待 DOM 更改之类的事情。

但是,在这种情况下,我们在标准可见性断言 .should('be.visible') 和用于构建页面的框架之间存在矛盾,因此我们使用 then( fn) ( ref ) 以访问未包装的 DOM。然后,我们可以使用 stand jasmine expect 语法应用我们自己版本的可见性测试。

事实证明,您也可以使用带有 .should(fn) 的函数,这同样有效

it('checks select option is visible - 2', function() {
const doc = cy.visit('http://localhost:4200')
cy.get("mdc-select").contains("installation type").click()

cy.get('mdc-select-item').contains("ITEM1").should(item1 => {
expect(isVisible(item1[0])).to.be.true
});
});

使用 should 而不是 then 对可见性测试没有影响,但请注意 should 版本可以多次重试函数,所以它不能与 click 测试一起使用(例如)。

来自文档,

What’s the difference between .then() and .should()/.and()?

Using .then() simply allows you to use the yielded subject in a callback function and should be used when you need to manipulate some values or do some actions.

When using a callback function with .should() or .and(), on the other hand, there is special logic to rerun the callback function until no assertions throw within it. You should be careful of side affects in a .should() or .and() callback function that you would not want performed multiple times.

您也可以通过扩展 chai 断言来解决该问题,但是这方面的文档并不广泛,因此可能需要更多工作。

关于javascript - 访问其父项被隐藏的元素 - cypress.io,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47551639/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com