playwright-service-worker-bypasses-page-route-mocks
Written the self-contained solution to ~/playwright-service-worker-bypasses-page-route-mocks.md.
Note: the referenced codebase (apps/web/public/sw.js, auth-fetch.ts, the e2e specs) is not present in this environment, so I could not run the tests or edit the real files. Instead I:
#dc2626 on #fef2f2 reproduces exactly the reported 4.41:1, and #b91c1c gives 5.91:1, a solid WCAG AA pass (≥4.5:1).event.respondWith(fetch(request)) runs in the SW context where page.route page-context interception doesn't apply, so mocked /api/* specs hit the real API, got 401, and authFetch redirected client-side to /login?expired=1.sw.js: early-return (no respondWith) for same-origin /api/* GETs, so browser-default (mockable) fetch applies — with an explicit warning not to "fix" it with caching, which would keep the context-switch bug.#dc2626 → #b91c1c (4.41 → 5.91:1), with a color comparison table.npx playwright test → 2 failed/6 passed), post-fix commands, SW-scope assertion, and regression greps.The document is ready to drop into the actual repo; once the files are available I can apply the edits directly.
# Evidence - Problem class: playwright-service-worker-bypasses-page-route-mocks - Model: openrouter/deepseek/deepseek-v4-flash-0731 - Solved: 2026-09-04T18:08:53.410Z - Verification: solution produced by pi in sandbox; see signatures.json
{"description": "Next.js offline service worker (BETA-126, apps/web/public/sw.js) registered a same-origin branch event.respondWith(fetch(request)) for /api/* GETs. Requests answered via respondWith execute in the SW context where Playwright page.route(\"**/api/**\") interception does NOT apply, so mocked-API e2e specs (fake token in cookies/localStorage) suddenly hit the REAL API, got 401, and authFetch redirected to /login?expired=1. Diagnosis path: repro with bare npx playwright test (2 failed/6 passed), read error-context.md (login?expired=1 vs expected class URL), grep middleware for expired (absent), grep auth-fetch.ts:107 (client-side redirect), git log recent web commits (SW landed after spec last green), read sw.js fetch handler. Key lesson: respondWith(fetch(request)) with no cache logic is a no-op passthrough in the default path but changes WHO handles the request (SW vs page context), breaking test interception; exclude same-origin /api from the SW fetch handler so browser-default fetch (mockable) applies. Second failure in same run was data-dependent WCAG contrast violations (safety review-queue pending badge #dc2626 on #fef2f2 = 4.41:1) that only fire when the queue is non-empty (1708 live).", "environment": "", "language": "", "model": "openrouter/deepseek/deepseek-v4-flash-0731", "problem_class": "playwright-service-worker-bypasses-page-route-mocks", "provider": "openrouter", "solved_at": "2026-09-04T18:08:53.410Z", "version": ""}Written the self-contained solution to ~/playwright-service-worker-bypasses-page-route-mocks.md.
Note: the referenced codebase (apps/web/public/sw.js, auth-fetch.ts, the e2e specs) is not present in this environment, so I could not run the tests or edit the real files. Instead I:
#dc2626 on #fef2f2 reproduces exactly the reported 4.41:1, and #b91c1c gives 5.91:1, a solid WCAG AA pass (≥4.5:1).event.respondWith(fetch(request)) runs in the SW context where page.route page-context interception doesn't apply, so mocked /api/* specs hit the real API, got 401, and authFetch redirected client-side to /login?expired=1.sw.js: early-return (no respondWith) for same-origin /api/* GETs, so browser-default (mockable) fetch applies — with an explicit warning not to "fix" it with caching, which would keep the context-switch bug.#dc2626 → #b91c1c (4.41 → 5.91:1), with a color comparison table.npx playwright test → 2 failed/6 passed), post-fix commands, SW-scope assertion, and regression greps.The document is ready to drop into the actual repo; once the files are available I can apply the edits directly.
# Evidence - Problem class: playwright-service-worker-bypasses-page-route-mocks - Model: openrouter/deepseek/deepseek-v4-flash-0731 - Solved: 2026-09-04T18:08:53.410Z - Verification: solution produced by pi in sandbox; see signatures.json
{"description": "Next.js offline service worker (BETA-126, apps/web/public/sw.js) registered a same-origin branch event.respondWith(fetch(request)) for /api/* GETs. Requests answered via respondWith execute in the SW context where Playwright page.route(\"**/api/**\") interception does NOT apply, so mocked-API e2e specs (fake token in cookies/localStorage) suddenly hit the REAL API, got 401, and authFetch redirected to /login?expired=1. Diagnosis path: repro with bare npx playwright test (2 failed/6 passed), read error-context.md (login?expired=1 vs expected class URL), grep middleware for expired (absent), grep auth-fetch.ts:107 (client-side redirect), git log recent web commits (SW landed after spec last green), read sw.js fetch handler. Key lesson: respondWith(fetch(request)) with no cache logic is a no-op passthrough in the default path but changes WHO handles the request (SW vs page context), breaking test interception; exclude same-origin /api from the SW fetch handler so browser-default fetch (mockable) applies. Second failure in same run was data-dependent WCAG contrast violations (safety review-queue pending badge #dc2626 on #fef2f2 = 4.41:1) that only fire when the queue is non-empty (1708 live).", "environment": "", "language": "", "model": "openrouter/deepseek/deepseek-v4-flash-0731", "problem_class": "playwright-service-worker-bypasses-page-route-mocks", "provider": "openrouter", "solved_at": "2026-09-04T18:08:53.410Z", "version": ""}