next.js - Mock multiple images from nextimage in cypress - Stack Overflow

I need some help on mocking thetag from nextimage in cypress component tests.I am using Nextjs 15.1

I need some help on mocking the tag from next/image in cypress component tests.

I am using Nextjs 15.1.6, cypress 14.1.0, and turbo for nextjs instead of webpack.

After a lot of hard work, I ended up with this:

describe('<Home />', () => {
  it('renders', () => {
    cy.readFile('src/assets/bard.webp', null).then((img) => {
      // Intercept requests to Next.js backend image endpoint
      cy.intercept('_next/image*', {
        statusCode: 200,
        headers: { 'Content-Type': 'image/webp' },
        body: img.buffer,
      })
    })
    cy.mount(<Home />)
  })
})

where the image tag in a child component loaded by looks like this:

<Image
  src={imageSrc}
  alt={alt}
  width={width}
  height={0}
  className="rounded"
  priority={isPriority}
/>

This loads the bard.webp image just fine in the cypress test, however the problem is there's multiple images on the page. The above code means that all images are loaded as bard.webp, instead of being loaded as their own image.

I don't know how to make cy.readFile / cy.intercept work for multiple images, since readFile expects a string and not a regex.

I tried using chatgpt to help me out, and it kept giving me broken responses. The final result I got before running out of free messages was:

const imageFiles: string[] = ['bard.webp', 'elf.webp', 'dnddice.webp'];

interface ImageData {
  fileName: string;
  img: ArrayBuffer;
}

it('renders with multiple images', () => {
  cy.wrap([] as ImageData[]).then((images) => {
    return Cypress._.reduce(
      imageFiles,
      (prevChain, fileName) => {
        return prevChain.then((collectedImages) =>
          cy.readFile(`src/assets/${fileName}`, null).then((img: ArrayBuffer) => {
            collectedImages.push({ fileName, img });
            return collectedImages;
          })
        );
      },
      cy.wrap([] as ImageData[])
    );
  }).then((images: ImageData[]) => {
    images.forEach(({ fileName, img }) => {
      // Match Next.js image request with regex, ensuring query params are intercepted
      cy.intercept(new RegExp(`_next/image\\?.*url=.*${fileName}.*`), {
        statusCode: 200,
        headers: { 'Content-Type': 'image/webp' },
        body: img,
      });
    });

    // Mount the component after setting up intercepts
    cy.mount(<Home />);
  });
});

This didn't let the images load at all, they were back to a 404.

I can't find any helpful examples online on how to do this; I found but nothing here worked. Most answers I saw were based on using webpack, not turbo.

The cypress blog post linked, , doesn't work for me.

The example in that blog post gives the error "Cannot redefine property: default"

import * as NextImage from 'next/image'

const OriginalNextImage = NextImage.default
Object.defineProperty(NextImage, 'default', {
  configurable: true,
  // Add `unoptimized` to any use of `next/image` in our tests
  value: props => <OriginalNextImage {...props} unoptimized  />,
});

cy.mount(<MyComponent />)

I'm at a loss of where to go.

I need some help on mocking the tag from next/image in cypress component tests.

I am using Nextjs 15.1.6, cypress 14.1.0, and turbo for nextjs instead of webpack.

After a lot of hard work, I ended up with this:

describe('<Home />', () => {
  it('renders', () => {
    cy.readFile('src/assets/bard.webp', null).then((img) => {
      // Intercept requests to Next.js backend image endpoint
      cy.intercept('_next/image*', {
        statusCode: 200,
        headers: { 'Content-Type': 'image/webp' },
        body: img.buffer,
      })
    })
    cy.mount(<Home />)
  })
})

where the image tag in a child component loaded by looks like this:

<Image
  src={imageSrc}
  alt={alt}
  width={width}
  height={0}
  className="rounded"
  priority={isPriority}
/>

This loads the bard.webp image just fine in the cypress test, however the problem is there's multiple images on the page. The above code means that all images are loaded as bard.webp, instead of being loaded as their own image.

I don't know how to make cy.readFile / cy.intercept work for multiple images, since readFile expects a string and not a regex.

I tried using chatgpt to help me out, and it kept giving me broken responses. The final result I got before running out of free messages was:

const imageFiles: string[] = ['bard.webp', 'elf.webp', 'dnddice.webp'];

interface ImageData {
  fileName: string;
  img: ArrayBuffer;
}

it('renders with multiple images', () => {
  cy.wrap([] as ImageData[]).then((images) => {
    return Cypress._.reduce(
      imageFiles,
      (prevChain, fileName) => {
        return prevChain.then((collectedImages) =>
          cy.readFile(`src/assets/${fileName}`, null).then((img: ArrayBuffer) => {
            collectedImages.push({ fileName, img });
            return collectedImages;
          })
        );
      },
      cy.wrap([] as ImageData[])
    );
  }).then((images: ImageData[]) => {
    images.forEach(({ fileName, img }) => {
      // Match Next.js image request with regex, ensuring query params are intercepted
      cy.intercept(new RegExp(`_next/image\\?.*url=.*${fileName}.*`), {
        statusCode: 200,
        headers: { 'Content-Type': 'image/webp' },
        body: img,
      });
    });

    // Mount the component after setting up intercepts
    cy.mount(<Home />);
  });
});

This didn't let the images load at all, they were back to a 404.

I can't find any helpful examples online on how to do this; I found https://github/cypress-io/cypress/issues/18064 but nothing here worked. Most answers I saw were based on using webpack, not turbo.

The cypress blog post linked, https://www.cypress.io/blog/component-testing-next-js-with-cypress#helper-components, doesn't work for me.

The example in that blog post gives the error "Cannot redefine property: default"

import * as NextImage from 'next/image'

const OriginalNextImage = NextImage.default
Object.defineProperty(NextImage, 'default', {
  configurable: true,
  // Add `unoptimized` to any use of `next/image` in our tests
  value: props => <OriginalNextImage {...props} unoptimized  />,
});

cy.mount(<MyComponent />)

I'm at a loss of where to go.

Share Improve this question asked Mar 3 at 0:27 user1779418user1779418 5051 gold badge10 silver badges26 bronze badges
Add a comment  | 

1 Answer 1

Reset to default 3

Use a callback version of cy.intercept() RouteHandler.

It will look something like this

cy.readFile('src/assets/bard.webp', null).then((img) => {

  cy.intercept('_next/image*', (req) => {

    if (req.url.includes('bard') {  // some condition that is relevant

      req.reply({
        statusCode: 200,
        headers: { 'Content-Type': 'image/webp' },
        body: img.buffer,
      })
    }
  })
})

Or handling many images, set specific intercepts

const images = ['bard', 'beard', 'bad', 'bored']

images.forEach(image => {
  cy.readFile(`src/assets/${image}.webp`, null).then((img) => {
    cy.intercept(`_next/image/${image}.webp`, (req) => {
      req.reply({ 
        ...
      })
  })
})

For reference, the documentation is here Request/Response Modification with routeHandler

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1745113813a4612006.html

相关推荐

  • next.js - Mock multiple images from nextimage in cypress - Stack Overflow

    I need some help on mocking thetag from nextimage in cypress component tests.I am using Nextjs 15.1

    9小时前
    20

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信