如何通过修改HTTP响应来触发剧作家中的服务工作者更新?

发布于 2025-02-06 06:46:33 字数 2224 浏览 2 评论 0原文

我正在为我最近添加了一个服务工作者的水疗中心工作,该水疗中心使用缓存优先策略预先插入了应用程序外壳,并使用网络 - firt策略来缓存导航请求。

该水疗中心包含一些显示“新版本可用的逻辑!”当它检测到“等待”服务工作者时,页面顶部的“重新加载”按钮的横幅。我想为此逻辑编写端到端测试,以及“重新加载”按钮背后的逻辑,但无法弄清楚如何触发剧作家中的服务工作者更新。

我一直使用的方法是在安装服务工作者并触发页面重新加载后修改服务工作者的响应。我可以修改响应及其响应标头,但它不会在浏览器中触发更新事件。

这是测试代码:

test("shows an update button when the service worker file has changed", async ({
  page,
  context
}, testInfo) => {
  const newScriptBytes = "/*test*/"
  const timeout = testInfo.timeout
  await page.goto("/")
  await waitForReadyServiceWorker({ context, page, timeout })

  // change the bytes of all additional service worker requests
  await page.route("/service-worker.js", async route => {
    const serverResponse = await page.request.fetch(serviceWorkerUrl, {
      ignoreHTTPSErrors: true
    })
    let serviceWorkerScript = await serverResponse.text()
    serviceWorkerScript = serviceWorkerScript.concat(newScriptBytes)
    await route.fulfill({
      response: serverResponse,
      body: serviceWorkerScript,
      headers: {
        ...serverResponse.headers(),
        "Etag": "v1",
        "Last-Modified": new Date().toUTCString(),
        "Content-Length": serviceWorkerScript.length.toString()
      }
    })
  })

  await page.reload()

  await expect(
    page.locator(`text=A new version is available!`)
  ).toBeVisible()
})

export async function waitForReadyServiceWorker(args: {
  context: BrowserContext
  page: Page
  timeout?: number
}): Promise<Worker | undefined> {
  const timeoutId = createOperationTimeout(args.timeout)
  const url = await args.page.evaluate(async () => {
    const readySw = await navigator.serviceWorker.ready
    return readySw.active.scriptURL
  })
  clearTimeout(timeoutId)
  return args.context.serviceWorkers().find(worker => worker.url() === url)
}

这是初始服务工作者响应

“初始服务工作者响应”

这是修改后的服务工作者响应

“修改后的服务工作者响应”

I am working on an SPA that I recently added a service worker to, which pre-caches the application shell using a cache-first strategy and caches navigation requests using a network -first strategy.

The SPA contains some logic that displays a "A new version is available!" banner with a "Reload" button at the top of the page when it detects a "waiting" service worker. I would like to write an end-to-end test for this logic and the logic behind the "Reload" button but cannot figure out how to trigger a service worker update in Playwright.

The approach that I have been playing with is modifying the service worker response after the service worker has been installed and a page reload has been triggered. I can modify the response and its response headers but it is not triggering an update event in the browser.

Here is the test code:

test("shows an update button when the service worker file has changed", async ({
  page,
  context
}, testInfo) => {
  const newScriptBytes = "/*test*/"
  const timeout = testInfo.timeout
  await page.goto("/")
  await waitForReadyServiceWorker({ context, page, timeout })

  // change the bytes of all additional service worker requests
  await page.route("/service-worker.js", async route => {
    const serverResponse = await page.request.fetch(serviceWorkerUrl, {
      ignoreHTTPSErrors: true
    })
    let serviceWorkerScript = await serverResponse.text()
    serviceWorkerScript = serviceWorkerScript.concat(newScriptBytes)
    await route.fulfill({
      response: serverResponse,
      body: serviceWorkerScript,
      headers: {
        ...serverResponse.headers(),
        "Etag": "v1",
        "Last-Modified": new Date().toUTCString(),
        "Content-Length": serviceWorkerScript.length.toString()
      }
    })
  })

  await page.reload()

  await expect(
    page.locator(`text=A new version is available!`)
  ).toBeVisible()
})

export async function waitForReadyServiceWorker(args: {
  context: BrowserContext
  page: Page
  timeout?: number
}): Promise<Worker | undefined> {
  const timeoutId = createOperationTimeout(args.timeout)
  const url = await args.page.evaluate(async () => {
    const readySw = await navigator.serviceWorker.ready
    return readySw.active.scriptURL
  })
  clearTimeout(timeoutId)
  return args.context.serviceWorkers().find(worker => worker.url() === url)
}

Here is the initial service worker response

initial service worker response

Here is the modified service worker response

modified service worker response

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文