CodeIssuesDiscussionsWikiPull RequestsProjectsCommitsActionsReleasesContributorsPulse● GatesSecuritySettingsDeploymentsPipelineInsightsAgents✨ Explain✨ Ask AI✨ Workspace✨ Spec✨ Tests▓ Debt Map✨ NL Search🏛 Archaeology
Blame · Line-by-line history
pwa.test.ts
Each line is annotated with the commit that last touched it. Click any SHA to jump to that commit and see the surrounding change.
| eae38d1 | 1 | /** |
| 44fe49b | 2 | * PWA route smoke tests — post-rip-out (2026-05-16). |
| eae38d1 | 3 | * |
| 44fe49b | 4 | * The PWA layer was removed because it produced recurring reload-loop |
| 5 | * bugs (admin dashboard, deploy pill, admin-screen flash). The routes | |
| 6 | * still exist but serve self-unregister bodies so any browser with the | |
| 7 | * old SW installed auto-recovers. The layout no longer registers a SW. | |
| eae38d1 | 8 | */ |
| 9 | ||
| 10 | import { describe, it, expect } from "bun:test"; | |
| 11 | import app from "../app"; | |
| 12 | import { MANIFEST, SERVICE_WORKER_SRC, PWA_REGISTER_SNIPPET } from "../routes/pwa"; | |
| 13 | ||
| 44fe49b | 14 | describe("pwa — manifest (kept for any pre-existing install)", () => { |
| eae38d1 | 15 | it("GET /manifest.webmanifest → 200 JSON", async () => { |
| 16 | const res = await app.request("/manifest.webmanifest"); | |
| 17 | expect(res.status).toBe(200); | |
| 18 | const ct = res.headers.get("content-type") || ""; | |
| 19 | expect(ct).toContain("application/manifest+json"); | |
| 20 | const body = await res.json(); | |
| 21 | expect(body.name).toBe("Gluecron"); | |
| 22 | expect(body.start_url).toBe("/"); | |
| 23 | expect(body.display).toBe("standalone"); | |
| 24 | expect(Array.isArray(body.icons)).toBe(true); | |
| 25 | expect(body.icons.length).toBeGreaterThan(0); | |
| 26 | }); | |
| 27 | ||
| 28 | it("MANIFEST constant has required install-prompt fields", () => { | |
| 29 | expect(MANIFEST.name).toBeDefined(); | |
| 30 | expect(MANIFEST.short_name).toBeDefined(); | |
| 31 | expect(MANIFEST.start_url).toBeDefined(); | |
| 32 | expect(MANIFEST.icons.length).toBeGreaterThan(0); | |
| 33 | expect(MANIFEST.display).toBe("standalone"); | |
| 34 | }); | |
| 35 | }); | |
| 36 | ||
| 44fe49b | 37 | describe("pwa — service worker (self-unregister edition)", () => { |
| eae38d1 | 38 | it("GET /sw.js → 200 JavaScript", async () => { |
| 39 | const res = await app.request("/sw.js"); | |
| 40 | expect(res.status).toBe(200); | |
| 41 | expect(res.headers.get("content-type") || "").toContain( | |
| 42 | "application/javascript" | |
| 43 | ); | |
| 44 | expect(res.headers.get("service-worker-allowed")).toBe("/"); | |
| 45 | }); | |
| 46 | ||
| 44fe49b | 47 | it("served SW body unregisters itself on activate", async () => { |
| 48 | const res = await app.request("/sw.js"); | |
| 49 | const body = await res.text(); | |
| 50 | expect(body).toContain("self.registration.unregister"); | |
| 51 | }); | |
| 52 | ||
| 53 | it("served SW body has no fetch handler", async () => { | |
| 54 | const res = await app.request("/sw.js"); | |
| 55 | const body = await res.text(); | |
| 56 | expect(body).not.toContain('addEventListener("fetch"'); | |
| 57 | expect(body).not.toContain("addEventListener('fetch'"); | |
| 58 | }); | |
| 59 | ||
| 60 | it("locked SERVICE_WORKER_SRC constant kept for back-compat tests", () => { | |
| eae38d1 | 61 | expect(SERVICE_WORKER_SRC).toContain("addEventListener('install'"); |
| 62 | expect(SERVICE_WORKER_SRC).toContain("addEventListener('activate'"); | |
| e1c7aa6 | 63 | expect(SERVICE_WORKER_SRC).toContain("self.registration.unregister"); |
| 64 | expect(SERVICE_WORKER_SRC).toContain("caches.delete"); | |
| eae38d1 | 65 | }); |
| 66 | ||
| 44fe49b | 67 | it("locked SERVICE_WORKER_SRC has no fetch handler", () => { |
| e1c7aa6 | 68 | expect(SERVICE_WORKER_SRC).not.toContain("addEventListener('fetch'"); |
| eae38d1 | 69 | }); |
| 70 | }); | |
| 71 | ||
| 72 | describe("pwa — icon", () => { | |
| 73 | it("GET /icon.svg → 200 SVG", async () => { | |
| 74 | const res = await app.request("/icon.svg"); | |
| 75 | expect(res.status).toBe(200); | |
| 76 | expect(res.headers.get("content-type") || "").toContain("image/svg+xml"); | |
| 77 | const body = await res.text(); | |
| 78 | expect(body).toContain("<svg"); | |
| 79 | expect(body).toContain("</svg>"); | |
| 80 | }); | |
| 81 | }); | |
| 82 | ||
| 44fe49b | 83 | describe("pwa — register snippet (legacy, no longer used by layout)", () => { |
| 84 | it("snippet still references serviceWorker for legacy callers", () => { | |
| eae38d1 | 85 | expect(PWA_REGISTER_SNIPPET).toContain("serviceWorker"); |
| 86 | expect(PWA_REGISTER_SNIPPET).toContain("'/sw.js'"); | |
| 87 | }); | |
| 88 | }); | |
| 89 | ||
| 44fe49b | 90 | describe("pwa — layout no longer registers a service worker", () => { |
| 91 | // 2026-05-16 — PWA ripped out. The layout used to inject manifest + | |
| 92 | // SW registration scripts; now it injects a kill-switch that | |
| 93 | // unregisters any pre-existing SW. These tests pin the new contract. | |
| 94 | it("home page does NOT include the manifest link", async () => { | |
| eae38d1 | 95 | const res = await app.request("/"); |
| 96 | const body = await res.text(); | |
| 44fe49b | 97 | expect(body).not.toContain('rel="manifest"'); |
| eae38d1 | 98 | }); |
| 99 | ||
| 44fe49b | 100 | it("home page does NOT call serviceWorker.register", async () => { |
| eae38d1 | 101 | const res = await app.request("/"); |
| 102 | const body = await res.text(); | |
| 44fe49b | 103 | expect(body).not.toContain("serviceWorker.register"); |
| eae38d1 | 104 | }); |
| d7ba05d | 105 | |
| 44fe49b | 106 | it("home page includes the kill-switch (unregisters legacy SWs)", async () => { |
| d7ba05d | 107 | const res = await app.request("/"); |
| 108 | const body = await res.text(); | |
| 44fe49b | 109 | expect(body).toContain("getRegistrations"); |
| 110 | expect(body).toContain("reg.unregister"); | |
| d7ba05d | 111 | }); |
| eae38d1 | 112 | }); |