Search code examples
loopstestingautomationautomated-testscypress

Cypress - How to iterate through the values of an environment variable and verify each item from the carousel list


I want to test whether the carousel on my website contains the correct items that are represented as company logos. Each carousel item has an <img> element with the 'alt' attribute which is where the name of the company is stored.

I have set an environment variable in the cypress.env.json file, which is represented something like this:

"companyPartners": {     
    "title": "Company Partners",     
    "partners": {         
        "google": "Google",         
        "facebook": "Facebook",         
        "instagram": "Instagram",         
        "linkedin": "LinkedIn"     
    } 
} 

The carousel elements are represented in an unordered list, something like this:

<ul class="carousel-partners ...">
    <li>
        <a class="carousel-item">
            <img alt="Google" src="...">
        </a>
    </li>
    <li>
        <a class="carousel-item">
            <img alt="Facebook" src="...">
        </a>
    </li>
    ...
</ul>

So, I want to iterate through each carousel item and verify that the values from the environment variable match the 'alt' attribute of the carousel items.

While running this command in Cypress, I am getting an error which says that only the first letter is retrieved:

Cypress.Commands.add("verifyPartners", () => {
    const companyPartners = Cypress.env("companyPartners").partners
    let text = ""
    for(const x in companyPartners){
        text += companyPartners[x]
    }

    cy.get('*[class^="carousel-partners"]').find("li").each(($listItem, index) => {
        cy.wrap($listItem).find("img").should("have.attr", "alt", text[index])
    })
});

assert expected <img.h-12.w-auto.object-contain.saturate-0> to have attribute alt with the value G, but the value was Google

Is there any way I can verify the items? Any help would be appreciated.


Solution

  • I'm going to assume there is one-to-one equivalence between the list and the DOM elements.

    To do this

    • convert partners object to array of RHS values with Object.values()
    • use within() to narrow the scope of queries
    • check each partner name is in the DOM on an <img> inside an <li>
    • then check there's no surplus <img> tags
    const partners = Cypress.env("companyPartners").partners
    
    /* 
      take value part of key/value in partners object
      yields ['Google','Facebook',...]
    */
    const companies = Object.values(partners)
    
    cy.get('ul.carousel-partners').within(() => {
      // queries here only apply to the contents of the <ul>
    
      // Two questions:
    
      // 1) Does every partner exist in the DOM on an li[alt] attribute?
      companies.forEach((company) => {
        cy.get(`li img[alt="${company}"]`)   // passes if exists
      })
    
      // 2) Does every DOM <li> have a value in the partners list?
      cy.get('li img').each(($img) => {
        const alt = $img.attr('alt')
        expect(alt).to.be.oneOf(companies)
      })
    
    })