Search code examples
javascriptfor-loopcypress

How to check if an attribute that belongs to multiple elements has one of several values


I'm trying to test whether an attribute that is shared by 3 elements has one of several values. Here's the html:


    <div class="wrapper">
      <a title="value 1"</a> 
      <a title="value 2"</a> 
      <a title="value 3"</a> 
    </div>

I need a way to assert that the title attribute of all three elements will have one of the 3 values, because their order might change in the future but I just need to make sure that they're there.

Here's what I've tried but didn't work for me:

cy.get('.wrapper')
    .children().as('socialLinks');

cy.get('@socialLinks')
    .should('have.attr', 'title').as('title');

expect('@title').to.contain.oneOf('value 1', 'value 2', 'value 3');

I suspect it might need a for-loop but I can't wrap my head around how to approach it.


Solution

  • A for-loop is possible but can cause problems in a Cypress test (search SO questions for some examples).

    There is the .each() command which performs the for-loop in a Cypress-friendly way

    cy.get('.wrapper').children()
      .each(($el) => {
        const title = $el.attr('title')
        expect(title).to.be.oneOf(['value 1', 'value 2', 'value 3'])
      })
    

    But if the values are loaded from an API, you should replace the expect() with a should() to make sure the test retries until loading is complete.

    cy.get('.wrapper').children()
      .each(($el) => {
        cy.wrap($el).invoke('attr', 'title')
          .should('be.oneOf', ['value 1', 'value 2', 'value 3'])
      })