如何使用Cypress测试离线模式Service Workers?fetch异常如何解决?
Service Worker Cypress 测试问题解决建议
一、优先尝试Cypress环境内修复方案
1. 修复fetch被劫持问题
Cypress 默认会改写页面的fetch请求用于请求录制、断言,导致Service Worker无法正常拦截fetch。你需要在cypress.config.js中添加配置禁用该行为:
const { defineConfig } = require('cypress') module.exports = defineConfig({ e2e: { experimentalFetchPolyfill: false, experimentalModifyObstructiveThirdPartyCode: false, // 若测试地址非localhost,添加以下启动参数保证SW可正常注册 chromeWebSecurity: false, args: ['--unsafely-treat-insecure-origin-as-secure=http://你的测试地址'] } })
2. 替换不可靠的硬等待逻辑
你当前使用wait(1000)等待SW注册,可能出现SW未完成激活、资源未完成缓存就切换离线的情况,替换为状态监听逻辑:
it('can load if sw registered and try to visit', () => { cy.visit(folder) cy.contains('#sw-status', 'SW not registered') cy.get('#register').click() // 等待SW注册完成的状态更新,替代硬等待 cy.contains('#sw-status', 'SW registered', { timeout: 5000 }) // 可选:等待SW缓存所有必要资源后再切离线 cy.waitUntil(() => cy.window().then(win => win.navigator.serviceWorker.ready.then(() => true) ) ) Cypress.goOffline() Cypress.assertOffline() // 手动修正navigator.onLine返回值,解决浏览器表现不一致问题 cy.window().then(win => { Object.defineProperty(win.navigator, 'onLine', { value: false, configurable: true }) }) cy.get('#fetch').click() cy.contains('#fetch-response', '200', { timeout: 3000 }) })
3. 确认离线模拟范围
Cypress的CDP离线模拟默认会拦截所有网络请求,若你的SW会请求部分非缓存的跨域资源,可在CDP配置中添加例外规则,或提前mock对应的跨域响应。
二、更换测试框架方案(若上述方案无效)
如果Cypress的hack成本过高,可选择对Service Worker兼容性更好的测试框架:
- Playwright:原生支持多浏览器离线状态控制,不会改写页面原生fetch、SW逻辑,可直接通过
browserContext.setOffline(true)切换离线状态,和真实浏览器行为完全一致,是SW测试的优先替代方案。 - Web Test Runner:配合Puppeteer控制真实浏览器的离线状态,轻量无侵入,适合小型SW测试场景。
内容的提问来源于stack exchange,提问作者raultm
相关产品推荐
相关产品推荐

