diff --git a/web/e2e/smoke.spec.js b/web/e2e/smoke.spec.js index 413accd..e5557bf 100644 --- a/web/e2e/smoke.spec.js +++ b/web/e2e/smoke.spec.js @@ -4360,3 +4360,66 @@ test('dagens plan står på I dag, og ikke kun som en besked', async ({ page }) expect(trouble).toEqual([]); }); + +/** + * En kalenderadresse gør ikke siden bredere end telefonen. + * + * Adressen på et abonnement er ét ord på et par hundrede tegn uden et mellemrum i, + * og den stod i en liste uden noget, der lod den ombryde. Det, man så, var ikke en + * linje, der løb ud over kanten — det var hele siden, der fik et vandret + * rullepanel, fordi det bredeste element på en side bestemmer sidens bredde. Derfor + * måler prøven dokumentet og ikke elementet: det er dokumentet, der var galt. + * + * Abonnementet kommer fra et svar, prøven selv skriver. Serveren ville skulle hente + * kalenderen for at have et at vise, og en prøve, der går på nettet, er en prøve, + * der fejler en dag af en anden grund end sin egen. + */ +test('en lang kalenderadresse giver ikke vandret rulning', async ({ page }) => { + const trouble = watchForTrouble(page); + + await page.route('**/api/v1/calendar', (route) => + route.fulfill({ + status: 200, + contentType: 'application/json', + body: JSON.stringify({ + connected: false, + calendars: [], + has_client: false, + read_only: true, + redirect_uri: 'http://localhost:8097/api/v1/calendar/callback', + subscriptions: [ + { + id: '0198f000-0000-7000-8000-000000000001', + provider: 'ics', + account: 'kw@netic.dk', + url: + 'https://calendar.google.com/calendar/ical/kw%40netic.dk/private-3f9a1c7e5b2d4a6f8c0e1d2b3a4f5e6d/basic.ics', + created_at: '2026-09-01T09:00:00+02:00' + } + ] + }) + }) + ); + + // En iPhone i stående format. Bredden er det eneste, der betyder noget her. + await page.setViewportSize({ width: 390, height: 844 }); + await page.goto('/indstillinger/integrationer'); + await expect(page.getByText('kw@netic.dk')).toBeVisible(); + + // `.content` og ikke dokumentet. Skallen holder selv siden på skærmens bredde, + // så documentElement måler 390 uanset hvad — det er indholdsspalten indeni, der + // ruller, og det er den, man skubber med tommelfingeren. En prøve på dokumentet + // består med fejlen i behold; den er prøvet. + const spill = await page.evaluate(() => { + const el = document.querySelector('.content'); + const url = document.querySelector('.subs-list .url'); + return { + content: el.scrollWidth - el.clientWidth, + past: Math.round(url.getBoundingClientRect().right) - document.documentElement.clientWidth + }; + }); + expect(spill.content).toBe(0); + expect(spill.past).toBeLessThanOrEqual(0); + + expect(trouble).toEqual([]); +}); diff --git a/web/src/routes/indstillinger/integrationer/+page.svelte b/web/src/routes/indstillinger/integrationer/+page.svelte index f948921..b4eec34 100644 --- a/web/src/routes/indstillinger/integrationer/+page.svelte +++ b/web/src/routes/indstillinger/integrationer/+page.svelte @@ -884,4 +884,38 @@ a { color: var(--accent); } + + /* The bullet list this was is why the page scrolled sideways on a phone. A + subscription address is one word with nothing to break at, so it cannot wrap + on its own — and the widest element on a page sets the width of the page, not + of its own line. Hence `anywhere`, which breaks mid-word when there is no + other opportunity, plus `min-width: 0` so the flex item is allowed to be + narrower than its content in the first place. */ + .subs-list { + list-style: none; + margin: 0; + padding: 0; + display: flex; + flex-direction: column; + gap: var(--s3); + } + + .subs-list li { + display: flex; + flex-direction: column; + align-items: flex-start; + gap: var(--s1); + min-width: 0; + } + + .subs-list .url { + font-size: var(--text-xs); + color: var(--ink-muted); + overflow-wrap: anywhere; + max-width: 100%; + } + + .subs-list button { + margin-top: var(--s1); + }