Cypress conditional statement for a disabled button element

Viewed 1490

Trying to click a button based on another element with enabled/disabled status. For some reason, my disabled check code is not working and it always ends in another statement ('No existing routes found') even though the UI has a select button enabled.

cy.get('voyage-suggested-routes')
  .find('button.selectButton')
  .then(($routes) => {
    if ($routes.is(":disabled")) {
      cy.log("No existing routes found...")
    } else {
      cy.log("Deleting......")
      cy.get('.delete-button').click({ force: true, multiple: true })
    }
  });

This is the DOM: (There are 3 elements by default and a delete option will be there for each Select button if it is not disabled.)

<button class="selectButton" disabled route="1">
       <svg xmlns="http://www.w3.org/2000/svg" viewBox="..."></path></svg>
        SELECT
</button>

Tried the jquery method as well but the same result.

var btnStatus = Cypress.$('.selectButton')
  .is(":disabled");

if (btnStatus == true) {
  cy.log("Deleting......")
  cy.get('.delete-button').click({ force: true, multiple: true })
} else {
  cy.log("No existing routes found...")
}

What am I missing?

Update 1: After Electron's input, my new code is:

 cy.get('voyage-suggested-routes')
     .find('button.selectButton')
     .then(($routes) => {
         if ($routes.is(":disabled").length === 0) {
            cy.log("No existing routes found...")
         } else {
            cy.log("Deleting......")
            cy.get('.delete-button').click({ force: true, multiple: true })
         }
     });
3 Answers

From the docs jQuery .is()

Description: Check the current matched set of elements against a selector, element, or jQuery object and return true if at least one of these elements matches the given arguments.

So if only one route is disabled, the delete will not go ahead.

Try using a filter to see if any are disabled.

cy.get('voyage-suggested-routes')
  .find('button.selectButton')
  .then(($routes) => {
    const disabled = $routes.filter(":disabled")
    if ($routes.length === disabled.length) {
      cy.log("No existing routes found...")
    } else {
      cy.log("Deleting......")
      cy.get('.delete-button').click({ force: true, multiple: true })
    }
  })

It's because you need each instead of then, like this:

.each(($routes) => {

in order to perform as many actions as there are button elements.

Edit: as Electron stated in the comments, the suggestion below will fail a test if all buttons are disabled, so take care if you use it.

And to better optimize your code, your can set the selector as .find('button.selectButton:not(:disabled)') then you don't need if block at all, just the delete statement.

Here's a custom command which conditionally runs a callback, depending on the result of filtering by given selector.

Not a lot of difference to .then(($routes) => { const disabled = $routes.filter(":disabled") pattern. Unfortunately ending part of a chain is quite difficult, as the whole test is considered one chain.

Cypress.Commands.add('maybe', {prevSubject:true}, (subject, selector, callback) => {
  const result = subject.filter(selector)
  if (result.length > 0) {
    cy.log(`Maybe: Found ${result.length} "${selector}"`)      
    cy.wrap(result).then(callback)
    return
  }
  cy.log(`Maybe: Not found: "${selector}"`)
})


cy.get('button.selectButton')
  .maybe(':not(:disabled)', ($result) => {

    // can use result of filter here
    console.log('result is', $result))  

    // or conditionally run some other commands
    cy.log(`Deleting...`)
    cy.get('.delete-button').click({ force: true, multiple: true })
  })

// runs either way
cy.wrap('something')
  .then(x => console.log('next', x))  
Related