import { expect, test } from '@playwright/test' import type { Page } from '@playwright/test' import { anmelden } from './hilfen' /** * Das Benutzermenü muss erreichbar sein, ohne danach zu suchen. * * Anlass ist Issue #1: Am Schreibtisch war „Mein Konto" praktisch nicht * zu finden — und damit auch nicht der Passwortwechsel, der zweite Faktor * und die Passkey-Verwaltung. Die Seitenleiste hatte keine feste Höhe und * wuchs mit der Seite mit; ihr Fuß landete deshalb am Ende der Seite statt * am unteren Bildschirmrand. Auf `/heute` waren das 1632 Pixel bei 900 * Pixel Fensterhöhe. * * Der Fehler sah nach nichts aus: Kein Element fehlte, nichts war kaputt, * die Seite sah richtig aus. Man musste nur ans Seitenende scrollen — und * darauf kommt niemand, der eine Seitenleiste vor sich hat. * * Geprüft wird deshalb nicht „ist das Element im DOM", sondern „steht es * im sichtbaren Bereich". */ /** Der Auslöser des Benutzermenüs in der Seitenleiste am Schreibtisch. */ function ausloeserInSeitenleiste(seite: Page) { return seite.locator('aside button[aria-haspopup="menu"]') } /** Steht das Element vollständig im Fenster, ohne zu scrollen? */ async function imSichtbarenBereich(seite: Page, auswahl: string): Promise { return seite.evaluate((sel) => { const el = document.querySelector(sel) if (!el) return false const k = el.getBoundingClientRect() return k.top >= 0 && k.bottom <= window.innerHeight && k.height > 0 }, auswahl) } test.describe('Benutzermenü am Schreibtisch', () => { test.skip(({ isMobile }) => Boolean(isMobile), 'Am Handy sitzt es in der Kopfzeile.') test('steht auch auf langen Seiten im Bild, ohne zu scrollen', async ({ page }) => { await anmelden(page) // Seiten, die laenger sind als das Fenster - genau dort trat der // Fehler auf. /fristen ist als Gegenprobe kurz. for (const ziel of ['/heute', '/vorgaenge', '/dokumente', '/finanzen', '/fristen']) { await page.goto(ziel) await page.waitForLoadState('networkidle') const sichtbar = await imSichtbarenBereich(page, 'aside button[aria-haspopup="menu"]') expect(sichtbar, `Benutzermenü nicht im Bild auf ${ziel}`).toBe(true) } }) test('bleibt an jeder Scrollposition stehen', async ({ page }) => { await anmelden(page) await page.goto('/heute') await page.waitForLoadState('networkidle') // Bewusst auch die Mitte pruefen. Nur oben und unten zu messen genuegt // nicht: Eine mitwachsende Leiste ist am Seitenende zufaellig doch // sichtbar - der Test waere dann gruen und der Fehler trotzdem da. for (const anteil of [0, 0.5, 1]) { await page.evaluate((a) => { const hoehe = document.documentElement.scrollHeight - window.innerHeight window.scrollTo(0, hoehe * a) }, anteil) await page.waitForTimeout(250) const sichtbar = await imSichtbarenBereich(page, 'aside button[aria-haspopup="menu"]') expect(sichtbar, `Benutzermenü nicht im Bild bei ${anteil * 100}% Scrollposition`).toBe(true) } }) test('führt in zwei Klicks nach „Mein Konto"', async ({ page }) => { await anmelden(page) await page.goto('/heute') await ausloeserInSeitenleiste(page).click() await page.getByRole('menuitem', { name: 'Mein Konto' }).click() await page.waitForURL('**/konto') // Und dort steht auch, worum es im Issue ging. await expect(page.getByRole('heading', { name: 'Mein Konto' })).toBeVisible() await expect(page.getByRole('heading', { name: 'Passwort ändern' })).toBeVisible() await expect(page.getByRole('heading', { name: 'Passkeys' })).toBeVisible() }) test('bleibt auf einem flachen Fenster erreichbar', async ({ page }) => { // Ein Laptop mit 1280x620 ist knapp: Kopf, Betreutenauswahl, // Navigation und Fuss muessen zusammen hineinpassen. Die Navigation // dazwischen darf scrollen, der Fuss nicht verschwinden. await anmelden(page) await page.setViewportSize({ width: 1280, height: 620 }) await page.goto('/heute') await page.waitForLoadState('networkidle') expect(await imSichtbarenBereich(page, 'aside button[aria-haspopup="menu"]')).toBe(true) }) }) test.describe('Benutzermenü am Handy', () => { test.skip(({ isMobile }) => !isMobile, 'Am Schreibtisch sitzt es in der Seitenleiste.') test('steht in der Kopfzeile und bleibt beim Scrollen stehen', async ({ page }) => { await anmelden(page) await page.goto('/heute') await page.waitForLoadState('networkidle') expect(await imSichtbarenBereich(page, 'header button[aria-haspopup="menu"]')).toBe(true) await page.evaluate(() => window.scrollTo(0, document.documentElement.scrollHeight)) await page.waitForTimeout(300) expect(await imSichtbarenBereich(page, 'header button[aria-haspopup="menu"]')).toBe(true) }) })