user9847788
user9847788

Reputation: 2433

How to choose option of select control in Cypress based on default value?

Below is a select control in my app:

<select id="answer">
    <option value="yes"> Yes <option>
    <option value="no"> No <option>
    <option value="maybe"> Maybe <option>
</select>

One of the above values will always be selected by default when the page loads.

A problem I have is that I won't know what that default value will be each time.

Here is an example of the Cypress test I'm trying to write:

Given the select control is visible
When I select a different option
Then the selected option is updated

Here's what I am trying to do in pseudo-code:

cy.get('select').select(~~ any option that isn't the default value ~~)

Is it possible to write something like the above? I just want to update the selected option to something other than the default value (but I won't know that default value until during the test, as it will be random)

Example of how it would work during a test run:

Example of how the test might run a second time:

Upvotes: 1

Views: 362

Answers (2)

agoff
agoff

Reputation: 7165

You can grab the value of the element on load, and use the option underneath the select to find one that does not equal the initial value.

cy.get('select')
  .invoke('val')
  .then((val) => {
    cy.get('select').find('option').then(($options) => {
      const notSelected = $options.filter((x) => $options[x].value !== val);
      const ranNum = Math.floor(Math.random() * notSelected.length);
      cy.get('select').select(notSelected[ranNum].value);
    });
  });

Upvotes: 1

Fody
Fody

Reputation: 32044

The random starting value is a bit of an anti-pattern for testing.

Maybe try to force the initial value to be the 1st, then cycle through the options.

const options = ['yes', 'no', 'maybe']

function nextOption(current) {
  return (options.indexOf(current) + 1) % options.length
} 

function selectAnotherOption() {
  cy.get('select')
    .invoke('val')
    .then(current => {
      cy.get('select').select(nextOption(current))
    }) 
}

cy.get('select').select('Yes')
cy.get('select').should('have.value', 'yes')

selectAnotherOption()
cy.get('select').should('have.value', 'no')

selectAnotherOption()
cy.get('select').should('have.value', 'maybe')

selectAnotherOption()
cy.get('select').should('have.value', 'yes')

I had a crack at making the above test "blind" (starting from any random value) but frankly the test gets awfully complicated and it's hard to know if you're testing anything of value.

Upvotes: 1

Related Questions