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 | /** |
| 2 | * Block G1 — PWA route smoke tests. | |
| 3 | * | |
| 4 | * Verifies manifest/icon/service-worker endpoints serve the right content | |
| 5 | * types + the manifest parses as JSON with the required install-prompt fields. | |
| 6 | */ | |
| 7 | ||
| 8 | import { describe, it, expect } from "bun:test"; | |
| 9 | import app from "../app"; | |
| 10 | import { MANIFEST, SERVICE_WORKER_SRC, PWA_REGISTER_SNIPPET } from "../routes/pwa"; | |
| 11 | ||
| 12 | describe("pwa — manifest", () => { | |
| 13 | it("GET /manifest.webmanifest → 200 JSON", async () => { | |
| 14 | const res = await app.request("/manifest.webmanifest"); | |
| 15 | expect(res.status).toBe(200); | |
| 16 | const ct = res.headers.get("content-type") || ""; | |
| 17 | expect(ct).toContain("application/manifest+json"); | |
| 18 | const body = await res.json(); | |
| 19 | expect(body.name).toBe("Gluecron"); | |
| 20 | expect(body.start_url).toBe("/"); | |
| 21 | expect(body.display).toBe("standalone"); | |
| 22 | expect(Array.isArray(body.icons)).toBe(true); | |
| 23 | expect(body.icons.length).toBeGreaterThan(0); | |
| 24 | }); | |
| 25 | ||
| 26 | it("MANIFEST constant has required install-prompt fields", () => { | |
| 27 | expect(MANIFEST.name).toBeDefined(); | |
| 28 | expect(MANIFEST.short_name).toBeDefined(); | |
| 29 | expect(MANIFEST.start_url).toBeDefined(); | |
| 30 | expect(MANIFEST.icons.length).toBeGreaterThan(0); | |
| 31 | expect(MANIFEST.display).toBe("standalone"); | |
| 32 | }); | |
| 33 | }); | |
| 34 | ||
| 35 | describe("pwa — service worker", () => { | |
| 36 | it("GET /sw.js → 200 JavaScript", async () => { | |
| 37 | const res = await app.request("/sw.js"); | |
| 38 | expect(res.status).toBe(200); | |
| 39 | expect(res.headers.get("content-type") || "").toContain( | |
| 40 | "application/javascript" | |
| 41 | ); | |
| 42 | expect(res.headers.get("service-worker-allowed")).toBe("/"); | |
| 43 | }); | |
| 44 | ||
| e1c7aa6 | 45 | it("v4 self-nuke service worker installs + activates + unregisters", () => { |
| eae38d1 | 46 | expect(SERVICE_WORKER_SRC).toContain("addEventListener('install'"); |
| 47 | expect(SERVICE_WORKER_SRC).toContain("addEventListener('activate'"); | |
| e1c7aa6 | 48 | expect(SERVICE_WORKER_SRC).toContain("self.registration.unregister"); |
| 49 | expect(SERVICE_WORKER_SRC).toContain("caches.delete"); | |
| eae38d1 | 50 | }); |
| 51 | ||
| e1c7aa6 | 52 | it("v4 service worker has no fetch handler — every request hits network", () => { |
| 53 | expect(SERVICE_WORKER_SRC).not.toContain("addEventListener('fetch'"); | |
| eae38d1 | 54 | }); |
| 55 | }); | |
| 56 | ||
| 57 | describe("pwa — icon", () => { | |
| 58 | it("GET /icon.svg → 200 SVG", async () => { | |
| 59 | const res = await app.request("/icon.svg"); | |
| 60 | expect(res.status).toBe(200); | |
| 61 | expect(res.headers.get("content-type") || "").toContain("image/svg+xml"); | |
| 62 | const body = await res.text(); | |
| 63 | expect(body).toContain("<svg"); | |
| 64 | expect(body).toContain("</svg>"); | |
| 65 | }); | |
| 66 | }); | |
| 67 | ||
| 68 | describe("pwa — register snippet", () => { | |
| 69 | it("registers a service worker when available", () => { | |
| 70 | expect(PWA_REGISTER_SNIPPET).toContain("serviceWorker"); | |
| 71 | expect(PWA_REGISTER_SNIPPET).toContain("'/sw.js'"); | |
| 72 | }); | |
| 73 | }); | |
| 74 | ||
| 75 | describe("pwa — layout wiring", () => { | |
| 76 | it("home page includes the manifest link", async () => { | |
| 77 | const res = await app.request("/"); | |
| 78 | const body = await res.text(); | |
| 79 | expect(body).toContain('rel="manifest"'); | |
| 80 | expect(body).toContain("/manifest.webmanifest"); | |
| 81 | }); | |
| 82 | ||
| 83 | it("home page registers the service worker", async () => { | |
| 84 | const res = await app.request("/"); | |
| 85 | const body = await res.text(); | |
| 86 | // JSX entity-escapes quotes inside <script>; just check the SW path is wired. | |
| 87 | expect(body).toContain("serviceWorker.register"); | |
| 88 | expect(body).toContain("/sw.js"); | |
| 89 | }); | |
| 90 | }); |