如何在运行Cypress测试前确保所有图片加载完成?(Nextjs+Percy)
问题
我有一个使用Percy(集成Cypress)进行可视化测试的Next.js项目,项目从CMS获取图片。如何确保页面所有图片加载完成后再执行快照或元素检查?
我见过两段相关代码,但都有问题:
- 检查损坏图片的示例代码:
const brokenImages = [] cy.get('img') .each(($el, k) => { if ($el.prop('naturalWidth') === 0) { const id = $el.attr('id') const alt = $el.attr('alt') const info = `${id ? '#' + id : ''} ${alt ? alt : ''}` brokenImages.push(info) cy.log(`Broken image ${k + 1}: ${info}`) } }) .then(() => { // report all broken images at once // enable the condition to see the thrown error if (false && brokenImages.length) { throw new Error( `Found ${ brokenImages.length } broken images\n${brokenImages.join(', ')}`, ) } })
- 检查单张图片
naturalWidth的示例代码(但在Next.js中无效):
cy.get('#loads') .should('be.visible') .and('have.prop', 'naturalWidth') .should('be.greaterThan', 0)
难道我只能设置固定等待时长,寄希望于图片加载完成吗?
解决方案
1. 拦截CMS图片请求,等待全部响应完成
既然图片来自CMS,直接拦截所有图片请求,确认它们都成功返回后再执行快照:
// 根据CMS图片实际路径调整匹配规则 cy.intercept('GET', '**/cms-images/**/*').as('cmsImages') cy.visit('/target-page') // 等待所有匹配的图片请求完成,超时时间按需调整 cy.wait('@cmsImages', { timeout: 10000, multiple: true }) // 执行Percy快照 cy.percySnapshot('Target Page')
注意:必须匹配CMS返回图片的真实URL路径,确保覆盖所有从CMS加载的资源。
2. 自定义命令检查所有图片加载状态
针对Next.js的懒加载特性(比如next/image组件),自定义命令确保每张图片都加载完成:
// 注册自定义命令 Cypress.Commands.add('waitForAllImages', () => { cy.get('img').each(($img) => { // 懒加载图片需要滚动到视图内才会触发加载 cy.wrap($img).scrollIntoView() // 断言图片已加载(naturalWidth>0表示图片有效且已加载) cy.wrap($img).should(($el) => { expect($el[0].naturalWidth).to.be.greaterThan(0) }) }) }) // 使用示例 cy.visit('/target-page') cy.waitForAllImages() cy.percySnapshot('Target Page')
3. 利用Percy快照的内置等待配置
Percy支持等待网络空闲后再快照,适合图片加载完成后无后续请求的场景:
cy.percySnapshot('Target Page', { waitForNetworkIdle: true, networkIdleTimeout: 5000 // 无网络请求5秒后触发快照 })
4. 拒绝固定等待时长
cy.wait(3000)这类固定等待完全依赖环境速度,极不稳定。如果有个别特殊图片无法通过上述方法覆盖,单独针对该图片做检查:
cy.get('#special-cms-image') .scrollIntoView() .should(($el) => { expect($el[0].naturalWidth).to.be.greaterThan(0) })
内容的提问来源于stack exchange,提问作者grabury
相关产品推荐
相关产品推荐

