Элемент доступа, родитель которого скрыт-cypress.io

вопрос, как указано в заголовке, т. е. для доступа к элементу, родитель которого скрыт. Проблема в том, что, согласно Кипарис.io docs :

элемент является скрытый если:

  • его ширина или высота 0.
  • его свойство CSS (или предки) - visibility: hidden.
  • его свойство CSS (или предки) отображается: никто.
  • его свойство CSS-position: fixed, и он за кадром или закрыт.

но код, с которым я работаю, требует, чтобы я нажал на элемент,родитель скрывается, в то время как сам элемент.

поэтому каждый раз, когда я пытаюсь нажать на элемент, он выдает сообщение об ошибке:

CypressError: тайм-аут повторная попытка: ожидается ' 'быть " видимым"

этот элемент ' - это не видно, потому что его родитель ' имеет свойство CSS : 'display: none'

enter image description here

элемент, я работаю с dropdown item, в которой написано pug. Элемент является компонентом, определенным в угловой-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} чтобы заставить элемент щелкнуть, но не повезло. Попробовали выбрать элементы с помощью {enter} нажатие клавиши на родительском mdc-select, но опять не повезло, как он бросает :

CypressError: cy.тип () может вызываться только в textarea или :text. Ваш тема: выбрать ...

также попытался с помощью select команда, но это невозможно, потому что Cypress engine не может идентифицировать элемент как select элемент (потому что его нет, внутренняя работа отличается). Он бросает :

CypressError: cy.select () можно вызвать только на a . Ваш тема: выбрать ...

на это mdc-select-menu это родитель для mdc-select-item обладает свойством display:none некоторыми внутренними вычислениями при открытии раскрывающихся элементов.

enter image description here

это свойство перезаписываться к display:flex, но это не помогает.

enter image description here

все из идей. Это работает в Selenium, но не cypress.io. Любая подсказка, что может быть возможным взломом для ситуации, кроме перехода на другие фреймворки или изменения кода пользовательского интерфейса?

2 ответов


после долгих nashing в зубы, я думаю, у меня есть ответ.

я думаю, что основная причина в том, что mdc-select-item и display:flex, что позволяет ему превышать границы его родителей (строго говоря, это похоже на неправильное применение display flex, если я правильно помню учебник, однако...).

Cypress делает много родительской проверки при определении visibilty, см. видимости.кофе!--20-->,

## 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'), мы застряли с родительскими свойствами, не проверяющими видимость ребенка, хотя мы действительно можем видеть ребенка.
Нам нужен альтернативный тест.

работающим

Ref С помощью 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' (или 'каждый')

обычно вы используете утверждение в cypress с помощью командных цепочек, которые в основном обертывают тестируемые элементы и обрабатывают такие вещи, как повтор и ожидание изменений DOM.

однако в этом случае мы имеем противоречие между стандартным утверждением видимости .should('be.visible') и рамки, используемые для создания страницы, поэтому мы используем then(fn) (ref), чтобы получить доступ к развернутому DOM. Затем мы можем применить нашу собственную версию тест видимости с использованием синтаксиса ожидания stand jasmine.

получается, вы также можете использовать функцию .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 версия может повторить функцию несколько раз, поэтому ее нельзя использовать с


документы, Cypress выберите синтаксис синтаксис

cy.get('mdc-select-item').select('ITEM1')

вам понадобится {force: true} Как хорошо. Смотрите здесь select_spec.кофе!--5--> для примеров собственных тестов, e.g

it "can forcibly click even when element is invisible", (done) ->
  select = cy.$$("select:first").hide()
  select.click -> done()
  cy.get("select:first").select("de_dust2", {force: true})