skip to Main Content

I have a very basic Cypress component test that intercepts an API request. The request response includes the URL of an image which is rendered in the component being tested. This response is saved as a state object called selectedLogo, and the src of the image being displayed is taken from the value of selectedLogo.url. I’ve saved a copy of the image to the fixtures folder – how do I get Cypress to display it in place of the original one?

This is the test:

import React from 'react';
import Logo from '../../src/logo/logo';

const allApiInterceptors = () => {
  cy.intercept('/logos/123456', {
    id: 5295911,
    url: '../fixtures/Banner.jpg' // this doesn't work
  });
};

describe('Logo', () => {
  beforeEach(() => {
    allApiInterceptors();
  });
  it('mounts', () => {
    cy.mount(<Logo />);
  });
});

In the React component being tested, a state object is created:

const [selectedLogo, setSelectedLogo] = useState(null);

The response to the API request is saved to the state object:

setSelectedLogo(response);

An image in the component picks up it’s src from the state object:

{selectedLogo && (
   <img src={selectedLogo.url} />
)}

2

Answers


  1. To display the image from the fixtures folder in place of the original one during the Cypress test, you can’t directly use the relative path ‘../fixtures/Banner.jpg’ in the response intercepted by cy.intercept. You should use cy.fixture() to load the fixture and then return it as a response. Something like this,

    import React from 'react';
    import Logo from '../../src/logo/logo';
    
    const allApiInterceptors = () => {
      cy.intercept('/logos/123456', (req) => {
        req.reply((res) => {
          res.send({
            id: 5295911,
            url: 'Banner.jpg' // Adjust this according to your actual folder structure
          });
        });
      }).as('logoRequest');
    };
    
    describe('Logo', () => {
      beforeEach(() => {
        allApiInterceptors();
      });
    
      it('mounts', () => {
        cy.fixture('Banner.jpg').then((image) => {
          cy.mount(<Logo />, {
            state: { selectedLogo: { url: image } }
          });
        });
    
        cy.wait('@logoRequest'); // ensure the intercept is called
      });
    });
    
    Login or Signup to reply.
  2. Seems like a timing issue, since the API call is involved. It will take time to resolve. Even though mocking the response makes it fast, there is still a useState() involved.

    Two suggestions:

    • wait for the intercept to allow the useState() hook to run

    • assert the image URL to make sure the test does not finish before the image is displayed

    cy.intercept('/logos/123456', {   
      id: 5295911,
      url: '../fixtures/Banner.jpg' 
    }).as('image')
    
    cy.mount(<Logo />) 
    
    cy.wait('@image')  
    
    // approximate assertion, the value will be something non-empty
    cy.get('img').should('have.attr', 'src', 'Banner.jpg')  
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search