From 45a5d4e3537679c414220259166f9e86e9ea5172 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Bombeck?= Date: Thu, 12 Nov 2026 15:02:11 +0100 Subject: [PATCH] fix(pwa): never let the badge call hold up the worker's activation The new worker cleared a leftover app badge inside its activation and waited for it. A browser that never settles that call keeps the worker activating, so it never takes over its pages and every offline path is gone. The badge is now cleared beside the activation, best effort. The sign-in journey expects the page's own sentence for a wrong password, not the server's text. --- e2e/login.spec.ts | 3 ++- public/sw.js | 6 ++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/e2e/login.spec.ts b/e2e/login.spec.ts index 07761eecc..152f84f72 100644 --- a/e2e/login.spec.ts +++ b/e2e/login.spec.ts @@ -118,7 +118,8 @@ test.describe("login page", () => { await page.getByTestId("login-password-submit").click(); expect((await answer).status()).toBe(401); - await expect(page.getByText("Invalid credentials")).toBeVisible(); + // The page says it in its own words, not the server's. + await expect(page.getByText("Login failed")).toBeVisible(); await expect(page).toHaveURL(/\/auth\/login/); expect( (await context.cookies()).some((c) => c.name === SESSION_COOKIE), diff --git a/public/sw.js b/public/sw.js index 7b7df52cf..e7bdd02e2 100644 --- a/public/sw.js +++ b/public/sw.js @@ -68,9 +68,11 @@ self.addEventListener("activate", (event) => { self.registration.navigationPreload ? self.registration.navigationPreload.enable() : Promise.resolve(), - clearLeftoverAppBadge(), ]).then(() => self.clients.claim()), ); + // Not part of the activation: a browser that never settles the badge call + // must not keep the worker from taking over its pages. + clearLeftoverAppBadge(); }); self.addEventListener("fetch", (event) => { @@ -354,7 +356,7 @@ async function trimCache(cacheName, maxEntries) { } // Earlier releases set a dose count on the app icon; nothing sends one now, -// so clear what they left. Never fails the activation. +// so clear what they left. Best effort, outside the activation. async function clearLeftoverAppBadge() { try { await self.navigator?.clearAppBadge?.();