import { expect, test, type Locator } from "@playwright/test"; async function expectDialogFits(dialog: Locator) { await expect(dialog).toBeVisible(); const sizes = await dialog.evaluate((panel) => { const body = panel.querySelector(".dialog-body")!; const rect = panel.getBoundingClientRect(); const overflowControls = Array.from(panel.querySelectorAll("input,select,textarea,.dialog-close,.dialog-footer button")).filter((control) => { const bounds = control.getBoundingClientRect(); return bounds.left < rect.left - 1 || bounds.right > rect.right + 1; }).map((control) => control.tagName); return { horizontalOverflow: body.scrollWidth - body.clientWidth, left: rect.left, right: rect.right, viewport: window.innerWidth, overflowControls }; }); expect(sizes.horizontalOverflow).toBeLessThanOrEqual(1); expect(sizes.left).toBeGreaterThanOrEqual(0); expect(sizes.right).toBeLessThanOrEqual(sizes.viewport); expect(sizes.overflowControls).toEqual([]); } for (const width of [320, 390, 768, 1280]) { test(`shared dialog keeps narrow form content and local table scrolling inside ${width}px`, async ({ page }) => { await page.setViewportSize({ width, height: 900 }); await page.goto("/?dialog-layout"); const dialog = page.getByRole("dialog"); await expectDialogFits(dialog); const tableScroll = page.getByTestId("dialog-local-scroll"); expect(await tableScroll.evaluate((element) => element.scrollWidth > element.clientWidth)).toBe(true); await tableScroll.evaluate((element) => { element.scrollLeft = element.scrollWidth; }); expect(await tableScroll.evaluate((element) => element.scrollLeft)).toBeGreaterThan(0); await expectDialogFits(dialog); }); for (const language of ["en", "de"]) { test(`actual Templates Add dialog fits ${width}px in ${language}`, async ({ page }) => { const unexpectedWrites: string[] = []; await page.route((url) => url.pathname.startsWith("/api/"), async (route) => { const request = route.request(); if (request.method() !== "GET") unexpectedWrites.push(`${request.method()} ${request.url()}`); await route.fulfill({ json: { items: [] } }); }); await page.setViewportSize({ width, height: 900 }); await page.goto(`/?dialog-layout&fixture=templates&language=${language}`); await page.getByRole("button", { name: language === "de" ? "Vorlage hinzufügen" : "Add template", exact: true }).click(); const dialog = page.getByRole("dialog"); await expectDialogFits(dialog); await dialog.locator("input").fill("Eine sehr lange Vorlagenbezeichnung ".repeat(8)); await expectDialogFits(dialog); await expect(dialog.locator(".dialog-footer button").last()).toBeEnabled(); expect(unexpectedWrites).toEqual([]); }); } }