【问题标题】:select react-select dropdown list option using cypress使用 cypress 选择 react-select 下拉列表选项
【发布时间】:2019-07-29 12:27:46
【问题描述】:

有人知道如何从 cypress 测试中的 react-select 下拉列表中选择一个选项吗?

我尝试了很多东西,但都无济于事。

似乎 react-select 使用了隐藏的输入。那柏树不能写进去。而且cypress也不能写入的div。

我不知道如何检查开发工具中的实际下拉列表也无济于事,因为它没有保持打开状态。

我正在使用:

  • 反应选择 v2.4.1
  • 柏树 v3.1.5

编辑 1:

@bkucera 的回答有效。我最终得到的工作代码是:

it('updates Person', () => {
    cy.get('[data-id=bearbeiter]')
      .find('.css-10nd86i')
      .click()
      .find('input')
      .eq(1)
      .focus()
    cy.contains('Test Tester').click({ force: true })
  })

我不得不在find 之后添加一个.eq(1),因为似乎有两个输入。

编辑 2:

上述解决方案最终点击了我网站上导航树中恰好包含相同文本的元素。所以没有雪茄:-(

编辑 3:

我也试过这个解决方案:

Cypress.Commands.add('setSelectOption', ({ selector, option, value }) => {
  cy.get(selector)
    .find('.css-10nd86i input')
    .eq(1)
    .focus()
    .type(value, { force: true })
})

...但即使使用了force: true,我也会收到此错误:

The element typed into was:

  > <input name="aeId" type="hidden" value="862333db-31cf-444c-b8ea-021c640c7a44">

Cypress considers the 'body', 'textarea', any 'element' with a 'tabindex' or 'contenteditable' attribute, or any 'input' with a 'type' attribute of 'text', 'password', 'email', 'number', 'date', 'week', 'month', 'time', 'datetime', 'datetime-local', 'search', 'url', or 'tel' to be valid typeable elements.

编辑 4:

到目前为止效果最好:

Cypress.Commands.add('setSelectOption', ({ selector, option, value }) => {
  cy.get(selector)
    .find('.css-10nd86i input:text')
    .focus()
    .type(option, { force: true, delay: 600, timeout: 330000 })
    .type('{enter}', { force: true })
  cy.get(selector)
    .find('.css-10nd86i')
    .find('input')
    .eq(1)
    .should('have.value', value)
})

至少它适用于短名单。文字输入缓慢。对于我们的物种列表(7000 长),我添加了 delaytimeout 选项。延迟似乎有所帮助,但我无法准确理解这些选项如何影响行为。有时柏树会超时:-(

编辑 5:

同时(react-select v3.0.4,cypress v3.3.2)所有测试都失败了,因为:

Expected to find element '.css-10nd86i' but never found it

我想班级已经改变了。这样一个脆弱的解决方案并不奇怪:-(

【问题讨论】:

  • 你应该写你的柏树版本是什么
  • 什么版本的 react-select

标签: cypress react-select


【解决方案1】:

您必须先单击以打开 react-select 下拉菜单,然后单击要打开的实际元素。我们为此使用以下语法:

cy.get('.s3p-react-select__indicator').eq(1)
  .click()
cy.get('[id^="react-select-"]').contains('<value_dropdownbox>')
  .click()

并且 in 确实使用了隐藏的输入字段。要找到隐藏的输入字段,请打开您的开发者工具,选择元素并查找“input[type='hidden']”。

最后回答你的最新问题:

我不知道如何检查开发工具中的实际下拉列表也无济于事,因为它没有保持打开状态。

尝试下载适用于 Chrome 的 React 选择开发者插件:https://chrome.google.com/webstore/detail/react-developer-tools/fmkadmapgofadopljbjfkapdkoienihi

如果您打开了 Chrome 开发者工具,请点击 React 选项卡。现在右键单击您的 React 元素并选择检查元素。您会看到可以为该元素执行的所有选项。但可能它不会立即选择正确的元素,因此请查找带有复选框“menuIsOpen”的元素,并检查它。下拉菜单将保持打开状态,直到页面发生更改

【讨论】:

    【解决方案2】:

    不幸的是,您遇到了 两个 Cypress 错误,which are fixed in pending releases

    • 1) 在.type 之前验证已经具有焦点的输入,这是错误的

    • 2) 当浏览器失焦时 chrome 不会触发模糊/焦点事件,这是 react-select 所依赖的。由于这个错误,当 chrome 窗口没有聚焦时,您不会看到下拉菜单。
      赛普拉斯的下一版本将填充这些事件,修复这个问题。

      解决方法:

      对于 1) 您必须在 .type 期间使用 {force:true}(见下文)

      对于 2) 您可以确保在运行测试时使窗口聚焦,或者在下面的代码中查看解决方法

    it('react-select', () => {
      cy.visit('https://react-select.com/creatable')
      cy.get('.css-10nd86i input').eq(1) // get the first react-select input
        .focus() // workaround for bug #2
        .type('Ocean', {force:true}) // workaround for bug #1
    })
    

    另一个例子:

    it('react-select', () => {
      cy.visit('https://react-select.com/creatable')
      cy.get('.css-10nd86i').eq(1)
        .click() // click on the react-select div
        .find('input').focus() // workaround for bug #2
      cy.contains('Ocean').click({force:true}) // workaround for bug #1
      // Other actions to take ?
      // cy.focused().type('{downarrow}{enter}', {force:true}) 
      // cy.focused().type('{enter}', {force:true})
      // cy.focused().type('Ocean', {force:true})
    })
    

    【讨论】:

    • 我不得不在 find 之后添加一个.eq(1),因为似乎有两个输入。但这行得通!非常感谢
    • Uups。不能可靠地工作:cy.contains('Ocean') 在我的页面上的任何位置找到Ocean。在我的情况下,导航树的元素被点击。有没有办法确保它只在下拉列表中搜索?
    • 你可以结合使用 .closest() 和 .find() 从你的 react-scripts 元素中遍历 Dom
    • 是的。但是我必须搜索什么?
    • 这是我失败的地方,因为我无法检查下拉列表,因为它不断消失
    【解决方案3】:

    我在这里得到了这个解决方案:

    "cypress": "^3.4.1"
    "react-select": "^2.4.3"
    
    cy
     .get('[class*="-control"]')
     .click(0, 0, { force: true })
     .get('[class*="-menu"]')
     .find('[class*="-option"]')
     .eq(2)
     .click(0, 0, { force: true })
    
    

    【讨论】:

    • 我必须将 .find('[class*="-option"]') 更改为 .find('[id*="-option"]') 否则它对我有用。
    • 不错?@user3788955
    【解决方案4】:

    将ID传给react-select,找到如下:

        cy.get('#country').within($el => {
        cy.wrap($el)
            .click()
            .find('div[tabindex*="-1"]')
            .first()
            .click();
        });
    

    所以,首先在元素内查询,包装它并触发 click 事件,然后只使用每个元素具有的数据道具之一,我使用 tabindex -1 因为每个元素都有它,使用 eq(x) if你需要特定的元素。

    【讨论】:

      【解决方案5】:

      就我而言,这有帮助:

      cy.get("[for=country]")
              .click() 
              .type("Poland{enter}");
      

      但请记住,我点击的是标签,它很好地专注于 react-select 输入。

      【讨论】:

        【解决方案6】:

        在 Cypress 4.2.0 和 react-select 3.0.8 上按两次回车对我有用:

        cy.get('#react-select-component-id').type('Something{enter}{enter}');
        

        【讨论】:

        • 在我的情况下一次输入就足够了
        • 如果您连续提交多个 react-select 下拉菜单,使用 .type('Something{enter}{enter}', { delay: 100 添加轻微延迟对我很有帮助})
        【解决方案7】:

        我使用的是 Cypress 4.2.0,我可以执行以下链式命令:

        Cypress.Commands.add('selectDropdownlist', (dropDownSelectionId) => {
        cy.get('[data-id=bearbeiter]').click({force: true})
        .get(`[id="${dropDownSelectionId}"]`).click() //the id or any selector of the value 'Test Tester'
        })
        

        【讨论】:

          【解决方案8】:

          在最新版本的react-select中可以设置classNamePrefix属性。

          Quote from react-select docs:

          如果你为 react-select 提供 classNamePrefix 属性,所有内部 将根据您提供的元素为元素指定一个类名。

          例如,给定 classNamePrefix="react-select",DOM 会 大致是这样的:

          <div class="react-select">
            <div class="react-select__control">
              <div class="react-select__value-container">...</div>
              <div class="react-select__indicators">...</div>
            </div>
            <div class="react-select__menu">
              <div class="react-select__menu-list">
                <div class="react-select__option">...</div>
              </div>
            </div>
          </div>
          

          使用这个技巧,您可以使用类选择器在 Cypress 中轻松找到 react-select 组件。例如,这里是选择第一个选项的代码 sn -p:

          cy.get('.react-select__control') // find react-select component     
             .click() // click to open dropdown
             .get('.react-select__menu') // find opened dropdown
             .find('.react-select__option') // find all options
             .first() 
             .click() // click on first option
          

          您还可以探索 cypress 测试 in the official github repository of react-select

          【讨论】:

          • 这实际上是通过在get('.react-select__control') 之后添加eq(1) 来实现的。
          【解决方案9】:

          你可以试试我的代码模板。在这个测试中,我点击输入,在菜单列表中选择选项 3 次。注意:每次选择选项后,我的菜单列表都会关闭,因此我需要在此之后单击输入。

            it('test react-select', () => {
              cy.get('#react-select-2-input').click().focus()
              cy.get('#react-select-2-option-0').click()
              cy.get('#react-select-2-input').click().focus()
              cy.get('#react-select-2-option-1').click()
              cy.get('#react-select-2-input').click().focus()
              cy.get('#react-select-2-option-2').click()
            })

          【讨论】:

            【解决方案10】:

            这对我有用:

            cy.get('[id="react-select-component"] select > option ').eq(3);
            

            在我的例子中,id 用于选择组件:

            <select id="name_select" name="name_select">
            
            <option value="someValue_1"> someOptionText_1 </option>
            <option value="someValue_2"> someOptionText_2 </option>
            <option value="someValue_3"> someOptionText_3 </option>
            
            </select>
            

            eq(3) => value="someValue_2"; eq(1) 标题

            【讨论】:

              【解决方案11】:

              我正在开发的基于 React 的应用程序中有一个自定义下拉菜单。因此,我编写了以下函数来从下拉列表中选择一个值。

              // definition
              function selectOptionFromDropDown(elDropdown, stOptionElement, stOptionToSelect){
                cy.get(elDropdown).eq(0).click()
                .find(stOptionElement).first().focus()
                cy.contains(stOptionToSelect).click({force:true})
              } 
              // calling
              keywords.selectOptionFromDropDown('[id="dropdown-account-campaigns"]','input', 'Main (GBP)')
              

              【讨论】:

                【解决方案12】:

                我找到了解决同样问题的简单方法:

                -> cy.get('#basic_category').click()    //getting id of dropdown by cy.get() and using click()
                -> cy.contains('Test Category2').click()   //typing name of what you want to pick from dropdown in cy.contains() and using click()
                

                【讨论】:

                  【解决方案13】:

                  这适用于我的 State 下拉列表,它有一个 data-testid 用于 React 测试库:

                  cy.get("[data-testid='shippingAddress.state']").type("California{enter}");
                  

                  使用:

                  "@testing-library/react": "11.2.7"
                  "react-select": "3.2.0"
                  "cypress": "6.9.1"
                  

                  【讨论】:

                    【解决方案14】:

                    如果对象是只读的,你只需要读取对象然后选择它。

                    cy.get('XXXXX').click(); cy.contains(YYYY).click({ force: true })

                    【讨论】:

                    • 这个问题现有的答案有 13 个,其中包括几个得到社区支持的答案。您确定尚未提供您的答案吗?如果不是,为什么有人会更喜欢您的方法而不是提议的现有方法?您是否正在利用新功能?是否存在更适合您的方法的场景?
                    【解决方案15】:

                    cy.get(' [name=" Optionwithcheck[] "] ').select( ['Option 2','Option 3'] )

                    【讨论】:

                      猜你喜欢
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      相关资源
                      最近更新 更多