Кипарис: Как прокрутить выпадающий список, чтобы найти элемент

#cypress #angular-ngselect

Вопрос:

Мне нужно щелкнуть раскрывающийся список и прокрутить его, чтобы найти элемент по тексту.

введите описание изображения здесь

На данный момент я знаю, что этот пункт находится в нижней части списка, поэтому я могу сделать:

cy.get('.ng-dropdown-panel-items').scrollTo("bottom").contains(/test/i).click()

и это работает, но если предмет переместится и больше не будет находиться внизу, это сломается.

Я попробовал scrollIntoView, но безуспешно:

cy.get('.ng-dropdown-panel-items').contains(/test/i).scrollIntoView().click()

и

cy.get('.ng-dropdown-panel-items').scrollIntoView().contains(/test/i).click()

Кто-нибудь знает, как я могу это сделать?

Обновление: список параметров генерируется динамически (не все параметры изначально находятся в DOM), поэтому для получения всех параметров требуется прокрутка вниз. Как только все параметры будут доступны .contains() , их можно будет использовать для поиска элемента.

Комментарии:

1. какие действия ваша задача заставляет вас выполнять с этим элементом?

2. Я заполняю форму, поэтому мне просто нужно выбрать элемент в раскрывающемся списке

3. Выбирает обычно требуется cy.выберите() docs.cypress.io/api/commands/select ТАК что для вашего случая это было бы cy.get('.ng-dropdown-panel-items').select(/test/i)

4. хорошая мысль, и я попробовал, но я вижу, что наши разработчики использовали Angular. Это ошибка, которую я получаю при использовании select(): cy.select() can only be called on a <select>. Your subject is a: <div class="ng-dropdown-panel-items scroll-host">...</div>

5. Я понимаю. Не могли бы вы добавить HTML-структуру раскрывающегося списка в сообщение, чтобы мы могли что — то увидеть и придумать? Если это выпадающий список в div, я полагаю, вы можете использовать cy.get('.ng-dropdown-panel-items').focus().wait(1000).contains(/test/i).click()

Ответ №1:

Угловой ng-выбор в виртуальном режиме довольно сложен в обращении.

Этот список является виртуальным, что означает, что в нем одновременно есть только некоторые элементы в DOM, поэтому вы не можете выбрать их все и повторить их.

Вы можете рекурсивно сканировать список опций и использовать .type({downarrow}) его для перемещения новых опций в DOM (что является одним из способов взаимодействия пользователя с ним).

 it('selects an option in a virtual-scroll ng-select', () => {

  cy.visit('https://ng-select.github.io/ng-select#/virtual-scroll')

  cy.get('ng-select').click();                    // open the dropdown panel

  cy.get('.ng-option')
    .should('have.length.gt', 1);                 // wait for the option list to populate

  function searchForOption(searchFor, level = 0) {

    if (level > 100) {                                         // max options to scan
      throw 'Exceeded recursion level'                         // only useful for 100's
    }                                                          // not 1000's of options 

    return cy.get('ng-select input')
      .then($input => {
        const activeOptionId = $input.attr('aria-activedescendant') // highlighted option
        const text = Cypress.$(`#${activeOptionId}`).text()         // get it's text
        if (!text.includes(searchFor)) {                            // not the one?
          cy.wrap($input).type('{downarrow}')                       // move the list
          return searchForOption(searchFor, level   1)              // try the next
        }
        return cy.wrap(Cypress.$(`#${activeOptionId}`))
      })
  }

  searchForOption('ad et natus qui').click();             // select the matching option

  cy.get('.ng-value')
    .should('contain', 'ad et natus qui');                // confirm the value 

})
 

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

Ответ №2:

В большинстве случаев вам понадобится cy.get().выберите, например, нравится:

cy.get('.ng-dropdown-panel-items').select(/test/i)

Ответ №3:

Вы можете использовать an each() для перебора выпадающих элементов, а когда найдете нужный текст, сделайте an click() .

 cy.get('span.ng-option-label.ng-star-inserted').each(($ele) => {
  if($ele.text() == 'desired text') {
    cy.wrap($ele).click({force: true})
  }
})
 

Комментарии:

1. Просто предложение, так как ему нужно прокрутить его: добавьте cy.wrap($ele).scrollIntoView() перед тем, если

2. @RosenMihaylov Прокрутка не требуется, при нажатии на cypress автоматически отобразится элемент в представлении и нажмите на него.

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

4. Я примерил ng-select.github.io/ng-select#/data-sources , который, по моему мнению, имеет тот же угловой компонент, и он работал без прокрутки.

5. спасибо за вашу работу. У меня не было места, чтобы проверить это, просто теория

Ответ №4:

Попробуйте что-то вроде приведенной ниже рекурсивной функции:

 function scrollUntilElementFound(scrollIndex) {
scrollIndex = scrollIndex 10;
if(!cy.get('.ng-dropdown-panel-items').contains(/test/i)){
    cy.get('.ng-dropdown-panel-items').scrollTo(scrollIndex);
    scrollUntilElementFound(scrollIndex);
} else {
    //element found
    return;
}  
}