diff --git a/web/e2e/smoke.spec.js b/web/e2e/smoke.spec.js index cbfa9dd..70fe2e9 100644 --- a/web/e2e/smoke.spec.js +++ b/web/e2e/smoke.spec.js @@ -183,6 +183,12 @@ test('manifestet og service workeren findes, og ikonerne findes også', async ({ expect(iconResponse.ok(), `${icon.src} findes ikke`).toBeTruthy(); } + // Safari never reads the manifest's icons; it looks for this by name, and + // without it an installed PWA on iOS gets a screenshot of the page as its + // home-screen icon. + const appleIcon = await request.get('/apple-touch-icon.png'); + expect(appleIcon.ok(), 'apple-touch-icon.png findes ikke').toBeTruthy(); + // The service worker is what Web Push needs; without it a subscription cannot // be created at all. const worker = await request.get('/sw.js'); diff --git a/web/scripts/generate-icons.js b/web/scripts/generate-icons.js new file mode 100644 index 0000000..2674b61 --- /dev/null +++ b/web/scripts/generate-icons.js @@ -0,0 +1,40 @@ +/** + * Renders static/icon.svg to the PNGs the manifest and iOS need. + * + * node scripts/generate-icons.js + * + * A script rather than a test, so CI never runs it and never rewrites a tracked + * binary. Run it when the icon changes; the smoke test fetches every icon the + * manifest names, so a reference with no file behind it fails there. + * + * It drives Chromium because there is no SVG renderer on this machine — which is + * why these references were once removed rather than left pointing at files that + * did not exist. Playwright is a renderer, and it is already a dependency. + */ +import { chromium } from '@playwright/test'; +import { readFileSync, writeFileSync } from 'node:fs'; + +const SIZES = [ + // The two the manifest asks for: 192 for a launcher, 512 for a splash screen. + { file: 'static/icon-192.png', size: 192 }, + { file: 'static/icon-512.png', size: 512 }, + // And the one Safari wants by name. It ignores the manifest's icons entirely + // and looks for this, which is why an installed PWA on iOS otherwise gets a + // screenshot of the page as its home-screen icon. + { file: 'static/apple-touch-icon.png', size: 180 } +]; + +const svg = readFileSync('static/icon.svg', 'utf8'); +const browser = await chromium.launch(); +const page = await browser.newPage(); + +for (const { file, size } of SIZES) { + await page.setViewportSize({ width: size, height: size }); + await page.setContent( + `${svg}` + ); + writeFileSync(file, await page.locator('svg').screenshot()); + console.log(`${file} ${size}×${size}`); +} + +await browser.close(); diff --git a/web/src/app.html b/web/src/app.html index f913c5d..3e8fe18 100644 --- a/web/src/app.html +++ b/web/src/app.html @@ -7,6 +7,10 @@ + +