Search code examples
javascripttypescriptcypresscypress-each

How to get the value of an element only if another specific element is visible?


What I am working with:

<ul class="abc">
 <li class="xyz">
  <a href="www.something.com">
   <div>
    <h2>
     <div>
      <div class="theText">
       <div>Get this text</DIV>
      </div>
     </div>
    </h2>
   </div>
  </a> 
  <button aria-label="remove">...</button>
 </li>
 <li class="xyz">...Same stuff here as above li...</li>
 <li class="xyz">...Same stuff here as above li...</li>
 <li class="xyz">...Same stuff here as above li...</li>
</ul>

The button here has two states for the aria-label attribute which is remove (for when the button is clicked) and add (for when the button is not yet clicked).

What I want to achieve:
I want to get the value within the <a> tag, which in this case is "Get this text", BUT only if the button within its same <li> tag is set to aria-label="remove". I will also be storing the values that I get within an array to later on compare with another array.

What I have tried:

let myArray: any = []

cy.get('li[class="xyz"]').each(($element) => {
    cy.get('li[class="xyz"]').within(($element) => {
        cy.wrap($element)
            .find('button[aria-label="remove"]')
            .find('div[class="theText"]')
            .invoke('text').then(text => {
                myArray.push(text)
            })
    })
}).then(() => {
    cy.wrap(myArray).as('myArray')
})

With the above code, I am getting this Assertion Error from Cypress.


Solution

  • If you want to use the :has() pseudo-selector, you should do so on the outer of the .each() loop.

    But please beware, :has() pseudo-selector will fail if there are zero buttons already clicked.

    let myArray: any = []
    
    cy.get('li[class="xyz"]:has(button[aria-label="remove"])')  // implied filter
      .each($li => {
        // only element with remove attribute inside here
        cy.wrap($li)
          .find('div[class="theText"]')
          .invoke('text')
          .then(text => {
            myArray.push(text)
          })
      })
    }).then(() => {
      cy.wrap(myArray).as('myArray')
    })