如何在Cypress中选择下拉列表(select element)里的第n个选项?

103

假设我有以下HTML:

<select name="subject" data-testid="contact-us-subject-field">
  <option value="What is this regarding?">What is this regarding?</option>
  <option value="Partnerships">Partnerships</option>
  <option value="Careers">Careers</option>
  <option value="Press">Press</option>
  <option value="Other">Other</option>
</select>

选择已知值的选项,例如“职业”,只需要:

cy.get('[data-testid="contact-us-subject-field"]').select('Careers');

如何选择这个字段中的第n个选项,无论其值为何?

12个回答

137

更新

正如评论中@dpstree指出的那样,这并没有回答原始问题。请查看最新的答案以获取完整的解决方案。

原始内容

通过使用eq

cy.get('tbody>tr').eq(0)    // Yield first 'tr' in 'tbody'
cy.get('ul>li').eq(4)       // Yield fifth 'li' in 'ul'

2
eq 是一个缩写吗?它代表什么意思? - nitzel
2
正如我所链接的文档页面所述,该术语来自于jQuery。因此,您可能会对这篇文章感兴趣。请点击此处 - Arnaud P
4
这并没有选中任何东西。它展示了解决方案中需要的.eq()语法,但错过了需要操作选择器的重要背景。请参见下面的Robert或Miguel的解决方案。 - dpsthree
此外,Cypress中的eq()根本不起作用。我已经尝试在我的Angular 8应用程序的几乎任何地方使用它,在其中有一些元素的行具有相同ID的某些元素。如果有两个具有相同ID的按钮,则Cypress将始终单击第一个按钮,无论我使用eq(0)或eq(1)。同时,它确实尝试遵守索引,因为当只有两个时,它不会接受eq(2)。但是它根本不起作用。 - user9347168
1
只需记住,如果将此选择保存到变量中,则无法正常工作。const mySelection = cy.get('tbody>tr'); mySelection.eq(0); mySelection.eq(1) --> 将没有第二个元素。您需要再次调用选择函数。 - Rantiev
显示剩余2条评论

51

在选择第n个option的特定情况下,这可能是适当的:

cy.get('select[name=subject] > option')
  .eq(3)
  .then(element => cy.get('select[name=subject]').select(element.val()))

这个聪明的解决方案非常棒,点赞! - nullsteph
1
正是我在寻找的,但请注意不久将会有更简单的解决方案。建议 @Robert 使用 cy.wrap() + parents() 避免选择器重复:.eq(2).then(($el) => cy.wrap($el).parent('select').select($el.val()))。https://github.com/cypress-io/cypress/issues/757。 - TimNode

28

基于Miguel Rueda的解决方案,但使用prevSubject选项:

Cypress.Commands.add(
  'selectNth',
  { prevSubject: 'element' },
  (subject, pos) => {
    cy.wrap(subject)
      .children('option')
      .eq(pos)
      .then(e => {
        cy.wrap(subject).select(e.val())
      })
  }
)

使用方法:

cy.get('[name=assignedTo]').selectNth(2)

解释:

  • 使用children('option').eq(pos)遍历选择器的子元素到特定元素。
  • 使用选定元素的值调用select方法。

23

现在您可以通过 .select(index) 命令中的 index 来选择选项:

cy.get('select').select(0)        // selects by index (yields first option) ie "What is this regarding?"
cy.get('select').select([0, 1])   // select an array of indexes

有了 cypress v8.5.0 的发布,现在应该很容易了。详见文档以获得更多信息。


尝试过了,对我有效。谢谢。 - Ivan Lim
如果我有一个动态选择框,并且想要选择最后一个选项,但不知道它的名称或值怎么办? - Darksymphony
这正是它应该做的,感谢您提供这个简短的解决方案! - Torben

10

我曾经遇到过同样的问题,并通过创建自定义的Cypress命令来解决它。虽然不如我所希望的那么漂亮,但它完成了工作。


Cypress.Commands.add("selectNth", (select, pos) => {
  cy.get(`${select} option +option`)
    .eq(pos)
    .then( e => {
       cy.get(select)
         .select(e.val())
    })
})

然后我在测试中使用了这样的方法

    cy.viewport(375, 667)
      .selectNth("customSelector", 3)

option + option 这部分是我找到的唯一获取一个 select 元素中所有选项的完整列表的方法,尽管它可以正常工作,但目前我正在努力解决这段代码。


7

由于实际工作中已经使用了then,因此eq或其他更高级的操作都与数组索引重复。

// to click on the 1st button
cy.get('button').then($elements => {cy.wrap($elements[0]).click();});
// to click on the 4th tr
cy.get('tr').then($elements => {cy.wrap($elements[3]).click();}); 
// to click on the last div:
cy.get('div').then($elements => {cy.wrap($elements[$elements.length - 1]).click();});

1
最终,一个可行的方案。在我的情况下:cy.wrap($recordings[0]).findByRole('button', { name: 'Remove' }).click({ force: true }) - Jason G

3

假设您想选择第二个选项,您可以通过以下方式轻松实现

cy.get("select option").eq(2)

请记住,cy.get() 的工作方式类似于 jQuery 的 $()


索引编号从0开始。如果您想要第2个元素,则应执行以下操作:cy.get("select option").eq(1)。 - Kyon Perez

2

使用ID或类查找下拉菜单 -

cy.get('#ID').contains("dowpdown placeholder or name").click();

点击下拉菜单后,下拉元素将弹出。使用“检查元素”找到该结果的ID或类,然后-

cy.get('#result-ID').children().first().click();

这将点击下拉列表的第一个元素。

1

你也可以依赖于 :nth-child CSS 伪类:

cy.get("[data-testid="contact-us-subject-field"] option:nth-child(2)").click();

这种方法可能比使用Cypress构造方式不够灵活,但它更加简洁明了。(而且不需要我在Cypress文档中搜索)


0
如果你想选择一个值,那么你不能使用.eq(),你需要使用.contains().eq()只适用于数字(索引)。
例如:cy.get(dropdownOptions).contains(some_value).click()

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接