【问题标题】:Cypress: How to scroll a dropdown to find item赛普拉斯:如何滚动下拉列表以查找项目
【发布时间】:2021-05-26 17:46:09
【问题描述】:

我需要单击下拉列表并滚动以按文本查找项目。

目前我知道该项目位于列表的底部,所以我可以这样做:

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() 可用于查找元素。

【问题讨论】:

  • 你的任务让你对那个元素做什么动作?
  • 我正在填写表格,所以我只需要在下拉列表中选择一个项目
  • 选择通常需要 cy.select() docs.cypress.io/api/commands/select 所以你的情况是cy.get('.ng-dropdown-panel-items').select(/test/i)
  • 好点,我试过了,但我发现我们的开发人员已经使用了 Angular。这是我在使用 select() 时遇到的错误:cy.select() can only be called on a <select>. Your subject is a: <div class="ng-dropdown-panel-items scroll-host">...</div>
  • 我明白了。您能否将下拉菜单的 HTML 结构添加到帖子中,以便我们可以看到和想到一些东西?如果它是 div 中的下拉菜单,我想你可以使用 cy.get('.ng-dropdown-panel-items').focus().wait(1000).contains(/test/i).click()

标签: cypress angular-ngselect


【解决方案1】:

虚拟模式下的 Angular ng-select 处理起来相当棘手。

它的列表是虚拟的,这意味着它一次只包含 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().select,例如:

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

    【讨论】:

      【解决方案3】:

      您可以使用each() 循环遍历下拉元素,当您找到所需的文本时,创建click()

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

      【讨论】:

      • 只是一个建议,因为他需要滚动到它:在 if 之前添加 cy.wrap($ele).scrollIntoView()
      • @RosenMihaylov 不需要滚动,点击 cypress 时会自动将元素带入视图并点击它。
      • 当然,我只是在解释他的请求,即页面需要在视图中呈现元素。
      • 我尝试了ng-select.github.io/ng-select#/data-sources,我猜它具有相同的角度分量,并且它在没有滚动的情况下工作。
      • 感谢您的工作。我没有在哪里测试它,只是一个理论
      【解决方案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;
      }  
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-12-23
        • 1970-01-01
        • 1970-01-01
        • 2021-10-16
        • 2020-05-15
        • 2021-12-11
        相关资源
        最近更新 更多