JD.
JD.

Reputation: 2487

How to select nth item inside select element in cypress

say I have the 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>

Selecting an option with a known value, such as 'Careers' is as easy as:

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

How do I select the nth option in this field, regardless of its value?

Upvotes: 110

Views: 185259

Answers (12)

Robert K. Bell
Robert K. Bell

Reputation: 10224

In the particular context of selecting the nth option, this may be appropriate:

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

Upvotes: 57

ismail ouzzine
ismail ouzzine

Reputation: 33

If you look for the nth option in the select dropdown, for example, in case the data is dynamically changed and you want to select the nth one, whatever the content may be, you can use this syntax:

App

<select name="mySelect">
  <option value="option_1">option 1</option>
  <option value="option_2">option 2</option>
  ...
  <option value="option_n">option n</option>
  ...
</select>

Spec

cy.get("[name='mySelect'] option:nth-of-type(n)")
.invoke("text")
.then((text) => {
  cy.get("[name='mySelect']").select(text);
});

And note that n is the order of the option that you want to select. The count start from 1.

Upvotes: 0

t_dom93
t_dom93

Reputation: 11476

You can now select an option by index within the .select(index) command:

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

This should be easy now with the release of cypress v8.5.0. See documentation for more.

Upvotes: 24

Milan Maksimovic
Milan Maksimovic

Reputation: 1

if you are looking a value to select then you cannot use .eq(), you need to use .contains() .eq() is only for numbers(indexes)

Example: cy.get(dropdownOptions).contains(some_value).click()

Upvotes: 0

Pradnyesh patil
Pradnyesh patil

Reputation: 321

Find dropdown using ID or Class -

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

After Click dropdown result dropdown element will popup, find that result ID or Class using inspect element, Then -

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

This will click on the first element of the dropdown.

Upvotes: 3

Tim Van Laer
Tim Van Laer

Reputation: 2534

You can also rely on the :nth-child css pseudo-class:

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

It's probably less flexible than using the cypress constructs but it is nice and clean. (And doesn't make me crawl through the cypress docs)

Upvotes: 1

Joelle Boulet
Joelle Boulet

Reputation: 390

since the working answers are using then anyways, eq or something fancier is redundant with array indexing...

// 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();});

Upvotes: 8

Arnaud P
Arnaud P

Reputation: 12627

Update

As pointed out by @dpstree in the comments, this doesn't answer the original question. Please see more recent answers for a complete solution.

Original

By using eq

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

Upvotes: 144

GHULAM NABI
GHULAM NABI

Reputation: 496

Capture all the elements in the drop-down using a selector. Get the length. Use math.random() to randomly get a number. Select the option at the index.

cy.get("ul > li").as("options")
cy
.get("@options")
.its('length')
.then(len => Math.floor(Math.random() * Math.floor(len)))
.then((index) => {
cy.get("@options").eq(index).click()
})

Upvotes: -3

Ajay Rawat
Ajay Rawat

Reputation: 307

Let's assume you wanna select 2nd option, you can do that simply by this

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

just keep in mind that cy.get() works like jquery's $().

Upvotes: 3

Tom Ehrlich
Tom Ehrlich

Reputation: 6651

Based on solution from Miguel Rueda, but using prevSubject option:

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

Usage:

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

Explanation:

  • Using children('option') and .eq(pos) traverse children of select to specific element.
  • Call select method with value of selected element.

Upvotes: 28

Miguel Rueda
Miguel Rueda

Reputation: 119

I had the same problem and solved it by creating a custom cypress command. No as pretty as I would like, but it did the job.

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

then I used in the test as such

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

The option +option part was the only way I could find to get the full list of options inside a select and it's currently the bit of code i'm trying to work arround although it works fine.

Upvotes: 11

Related Questions