I need to click a dropdown list and scroll to find an item by text.

At the moment I know that the item is at the bottom of the list so I can do:
cy.get('.ng-dropdown-panel-items').scrollTo("bottom").contains(/test/i).click()
and this works, but if the item moves and is no longer at the bottom, this will break.
I tried scrollIntoView but with no luck:
cy.get('.ng-dropdown-panel-items').contains(/test/i).scrollIntoView().click()
and
cy.get('.ng-dropdown-panel-items').scrollIntoView().contains(/test/i).click()
Does anyone know how I can do this?
Update: the list of options is dynamically generated (not all options are in the DOM initially) so scrolling to the bottom is required to get all options. Once all options are available .contains() can be used to find the element.
The Angular ng-select in virtual mode is quite tricky to handle.
It's list is virtual, which means it only has some of the items in the DOM at one time, so you can't select them all and iterate over them.
You can recursively scan the options list and use .type({downarrow}) to move new options into the DOM (which is one way a user would interact with it).
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 
})
Note that recursion can be hard on memory usage, and this code could be optimized a bit.
For most cases you would need cy.get().select like for example:
cy.get('.ng-dropdown-panel-items').select(/test/i)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With