javascriptcypresscypress-conditional-testing

How to check that element has either of classes in Cypress?


We search for an invalid element as following:

const invalidClasses = '.invalid, .invalid-default';

getInvalidElement() {
    cy.get(invalidClasses)
};

Now I have another function which accepts the element and checks if it has the invalid classes:

isInvalid(selector) {
 return cy.get(selector).should('have.class','invalid');
}

How can I check that the element has any of the two classes?

I know I can do

cy.get(selector).invoke('attr','class').should('match','/invalid/');

But what if the classes were different?

(Also the conditional testing does not apply to this case, there is no logic whether it's the first of the classes or the second one, we just want more abstract class for reusing)


Solution

  • Cypress .should() wraps chai assertions, so from how to do an “or” in chai should

    the following html fragment

    <div id="1" class="class1"></div>
    <div id="2" class="class2"></div>
    <div id="3" class="class1 class2"></div>
    <div id="4" class="class3"></div>
    

    can be tested like this

    it('finds either class1 or class2', () => {
    
      cy.get('div#1')
        .should('satisfy', ($el) => {
          const classList = Array.from($el[0].classList); 
          return classList.includes('class1') || classList.includes('class2') // passes
        }) 
    
      cy.get('div#2')
        .should('satisfy', ($el) => {
          const classList = Array.from($el[0].classList); 
          return classList.includes('class1') || classList.includes('class2') // passes
        }) // passes
    
      cy.get('div#3')
        .should('satisfy', ($el) => {
          const classList = Array.from($el[0].classList); 
          return classList.includes('class1') || classList.includes('class2') // passes
        }) 
    
      cy.get('div#4')
        .should('satisfy', ($el) => {
          const classList = Array.from($el[0].classList); 
          return classList.includes('class1') || classList.includes('class2') // fails
        }) 
    
    })
    

    Notes

    You can also make things a bit more generic by extracting the function,

    it('finds either class1 or class2', () => {
    
      const hasAtLeastOneClass = (expectedClasses) => {
        return ($el) => {
          const classList = Array.from($el[0].classList); 
          return expectedClasses.some(expectedClass => classList.includes(expectedClass));
        }
      }
    
      cy.get('div#1').should('satisfy', hasAtLeastOneClass(['class1', 'class2']));  //passes
    
      cy.get('div#2').should('satisfy', hasAtLeastOneClass(['class1', 'class2']));  //passes
    
      cy.get('div#3').should('satisfy', hasAtLeastOneClass(['class1', 'class2']));  //passes
    
      cy.get('div#4').should('satisfy', hasAtLeastOneClass(['class1', 'class2']));  //fails
    
    })