stein korsveien
stein korsveien

Reputation: 1117

Test loading of image in Cypress

I want to test Cypress that an image is loaded into the page.

My source code looks like this:

import React from "react";

export default class Product extends React.Component {
  render() {
    return (
      <div className="item">
        <div className="image">
          <img src="../images/Banana-Snowboard.png" alt="Snow Board" />
        </div>
        <div className="middel aligned content">
          <div className="description">
            <a>Snow Board</a>
            <p>Cool Snow Board</p>
          </div>
          <div className="extra">
            <span>Submitted by:</span>
            <img
              className="ui avatar image"
              src="./images/avatar.png"
              alt="Avatar"
            />
          </div>
        </div>
      </div>
    );
  }
}

And my test is like this:

it("should display a image in element div with class image", () => {
  cy.get('div[class="image"]').find("img"); // some code that test that image is loaded so that it is displaye on the web page
});

it("shoul diplay a image in element div with class image inside class extra", () => {
  cy.get('div[class="extra"]').find('img[class="ui avatar image"]');
  //some code that check that image is loaded so that it is display the web page
});

How will that code look like?

Upvotes: 25

Views: 43690

Answers (5)

Sudheer Singh
Sudheer Singh

Reputation: 664

You can simply do it by

    it('Test Broken Images', function() {
    cy.get('img').each(($img) => {
    cy.wrap($img).scrollIntoView().should('be.visible');
    expect($img[0].naturalWidth).to.be.greaterThan(0);
    expect($img[0].naturalHeight).to.be.greaterThan(0);
    });
    })

Upvotes: 0

MetaWhirledPeas
MetaWhirledPeas

Reputation: 486

I like jehon's take. But in my case our team is not able to follow the best practice of having a dependable, static image set, so I don't want broken image urls to fail the test. This version of the code doesn't fail on missing images:

cy.get('img', { timeout: 10000, includeShadowDom: true })
  .filter(selector)
  .filter(':visible')
  .each((el) => {
    const url = el[0]?.src || el[0]?.srcset
    if (url)
      cy.request({ url: url, failOnStatusCode: false }).then((resp) => {
        if (resp.status == 200)
          cy.get(el).should((el) => {
            expect(el[0].naturalWidth).to.be.greaterThan(0)
          })
      })
  })

Upvotes: 1

jehon
jehon

Reputation: 1668

I use this chain of cypress to wait for all images that should load for the user, and not more (excluding invisble or not initialized images):

Get all images (including in shadow dom - https://docs.cypress.io/api/commands/get#Arguments)

cy.get('img', { includeShadowDom: true })

that have a src tag (css selector - https://docs.cypress.io/api/commands/filter)

.filter('[src]')

and are visible (jquery selector - https://docs.cypress.io/guides/references/assertions#Chai-jQuery)

.filter(':visible')

and are all loaded ("naturalWidth" and "naturalHeight" are set when the image loads)

.should(($imgs) => $imgs.map((i, img) => expect(img.naturalWidth).to.be.greaterThan(0)));

All in one:

cy.get('img', { includeShadowDom: true })
        .filter('[src]')
        .filter(':visible')
        .should(($imgs) => $imgs.map((i, /** @type {HTMLImageElement} */ img) => expect(img.naturalWidth).to.be.greaterThan(0)));

Thanks to others posts here and at other places.

Upvotes: 3

gleb bahmutov
gleb bahmutov

Reputation: 1919

I have updated our recipe for static resource loading, see https://github.com/cypress-io/cypress-example-recipes/pull/363

To check if an image has finished loading, the simplest way is to check the image's naturalWidth or naturalHeight property.

// we can wait for the <img> element to appear
// but the image has not been loaded yet.
cy.get('[alt="delayed image"]')
.should('be.visible')
.and(($img) => {
  // "naturalWidth" and "naturalHeight" are set when the image loads
  expect($img[0].naturalWidth).to.be.greaterThan(0)
})

Alternatively, you can use performance entries to confirm that any static resource has finished loading, see the above pull request for the details.

Upvotes: 55

sesamechicken
sesamechicken

Reputation: 1981

What you're looking for is assertions, and in this case, should('be.visible') seems like it would fit the bill. https://docs.cypress.io/api/commands/should.html

it("should display a image in element div with class image", () => {
  cy.get('div[class="image"]').find("img").should('be.visible');
});

Upvotes: 8

Related Questions