/** * Flutter-Web-Helfer ohne Abhaengigkeit von `auth-config.ts` (Projekte `web` und `perf`). * * Flutter zeichnet auf ein Canvas; Playwright sieht Elemente erst, wenn der Semantics-Baum * eingeschaltet ist (Platzhalter `flt-semantics-placeholder`). `perf` darf gegen eine fremde * Umgebung laufen und importiert deshalb nichts, was lokale Auth-Konstanten voraussetzt. */ import { expect, type Locator, type Page } from '@playwright/test'; /** * Sichtbarer Text im Semantics-Baum. Flutter legt Texte teils als Textknoten, teils als * `aria-label` ab (z. B. der Inhalt der CheckEmail-Seite). */ export function textOf(page: Page, text: string | RegExp): Locator { return page.getByText(text).or(page.getByLabel(text)).first(); } /** Schaltet den Semantics-Baum ein (einmal je Seitenladen). */ export async function enableSemantics(page: Page): Promise { const placeholder = page.locator('flt-semantics-placeholder'); await placeholder.waitFor({ state: 'attached' }); await placeholder.evaluate((el: HTMLElement) => el.click()); await page.locator('flt-semantics').first().waitFor({ state: 'attached' }); } /** Navigiert und schaltet Semantics ein. */ export async function open(page: Page, path: string): Promise { await page.goto(path); await enableSemantics(page); } /** * Fuellt ein Flutter-Textfeld. Das Semantics-Textfeld legt das echte erst beim Fokus an; * `fill` allein geht dann gelegentlich verloren. Deshalb klicken, fuellen und den Wert pruefen * (mit Wiederholung). */ export async function fillField(field: Locator, value: string): Promise { await expect(async () => { await field.click(); await field.fill(''); await field.pressSequentially(value); await expect(field).toHaveValue(value, { timeout: 1_000 }); }).toPass({ timeout: 15_000 }); }