Verified with the coordinated workspace changes by devkit full run 2026-09-08T225814-186389-0000-3e3ed7cd (all seven phases passed). This shared UI pass does not mark the individual module reviews complete.
103 lines
6.1 KiB
TypeScript
Executable File
103 lines
6.1 KiB
TypeScript
Executable File
import { expect, test, type Locator } from "@playwright/test";
|
|
|
|
async function expectHelpBesideHeading(anchor: Locator) {
|
|
const heading = anchor.locator(":scope > :is(h1,h2,h3)");
|
|
const link = anchor.getByRole("link");
|
|
await expect(heading).toBeVisible();
|
|
await expect(link).toBeVisible();
|
|
await expect(heading.locator("a,button,[role=status]")).toHaveCount(0);
|
|
const geometry = await anchor.evaluate(element => {
|
|
const heading = element.querySelector(":scope > :is(h1,h2,h3)")!.getBoundingClientRect();
|
|
const link = element.querySelector("a")!.getBoundingClientRect();
|
|
return { gap: link.left - heading.right, right: link.right, viewport: window.innerWidth };
|
|
});
|
|
expect(geometry.gap).toBeGreaterThanOrEqual(4);
|
|
expect(geometry.gap).toBeLessThanOrEqual(8);
|
|
expect(geometry.right).toBeLessThanOrEqual(geometry.viewport);
|
|
}
|
|
|
|
for (const width of [390, 3085]) {
|
|
for (const language of ["en", "de"]) {
|
|
test(`documentation remains beside headings during loading and long-title wrapping (${width}px, ${language})`, async ({ page }) => {
|
|
await page.setViewportSize({ width, height: 1100 });
|
|
await page.goto(`/?heading-help&language=${language}`);
|
|
const pageTitle = page.locator(".page-title-with-loader");
|
|
await expect(page.getByRole("heading", { level: 1, name: "Dashboard", exact: true })).toBeVisible();
|
|
await expect(pageTitle.getByRole("status")).toBeVisible();
|
|
await expect(pageTitle.getByRole("link")).toHaveAccessibleName(language === "de" ? "Benutzerdokumentation öffnen" : "Open user documentation");
|
|
for (const anchor of await page.locator(".text-with-help:has(> :is(h1,h2,h3))").all()) await expectHelpBesideHeading(anchor);
|
|
const rawLabel = page.getByTestId("raw-text-help");
|
|
const rawGeometry = await rawLabel.evaluate(element => ({ width: element.clientWidth, scrollWidth: element.scrollWidth, right: element.getBoundingClientRect().right, helpRight: element.querySelector("a")!.getBoundingClientRect().right }));
|
|
expect(rawGeometry.scrollWidth).toBeLessThanOrEqual(rawGeometry.width);
|
|
expect(rawGeometry.helpRight).toBeLessThanOrEqual(rawGeometry.right);
|
|
await page.getByRole("button", { name: "Toggle loading", exact: true }).click();
|
|
await expect(pageTitle.getByRole("status")).toHaveCount(0);
|
|
await expectHelpBesideHeading(pageTitle.locator(".text-with-help"));
|
|
await expect(page.locator('[data-page-action-slot="help"]')).toHaveCount(0);
|
|
expect(await page.evaluate(() => document.documentElement.scrollWidth - window.innerWidth)).toBeLessThanOrEqual(1);
|
|
});
|
|
}
|
|
}
|
|
|
|
test("card help stays available when collapsed and opening it does not toggle content", async ({ page, context }) => {
|
|
await context.route("https://govoplan.add-ideas.de/**", route => route.fulfill({ body: "Documentation fixture" }));
|
|
await page.goto("/?heading-help&language=en");
|
|
const card = page.getByTestId("help-card");
|
|
const popupPromise = page.waitForEvent("popup");
|
|
await card.getByRole("link").click();
|
|
const popup = await popupPromise;
|
|
await popup.close();
|
|
await expect(page.getByTestId("help-card-content")).toBeVisible();
|
|
await card.getByRole("button", { name: "Show header only", exact: true }).click();
|
|
await expect(page.getByTestId("help-card-content")).toHaveCount(0);
|
|
await expectHelpBesideHeading(card.locator(".text-with-help"));
|
|
await card.getByRole("button", { name: "Show content", exact: true }).click();
|
|
await expect(page.getByTestId("help-card-content")).toBeVisible();
|
|
});
|
|
|
|
test("dialog help has its own name, remains in keyboard order, and does not dismiss the dialog", async ({ page, context }) => {
|
|
await context.route("https://govoplan.add-ideas.de/**", route => route.fulfill({ body: "Documentation fixture" }));
|
|
await page.setViewportSize({ width: 390, height: 1000 });
|
|
await page.goto("/?heading-help&language=en");
|
|
await page.getByTestId("open-help-dialog").click();
|
|
const dialog = page.getByRole("dialog");
|
|
await expect(dialog).toHaveAccessibleName(/^Dashboard DokumentationsüberschriftOhneLeerzeichen/);
|
|
await expectHelpBesideHeading(dialog.locator(".text-with-help"));
|
|
const help = dialog.getByRole("link");
|
|
await expect(help).toBeFocused();
|
|
await help.press("Shift+Tab");
|
|
await expect(page.getByTestId("dialog-last-action")).toBeFocused();
|
|
await page.getByTestId("dialog-last-action").press("Tab");
|
|
await expect(help).toBeFocused();
|
|
const popupPromise = page.waitForEvent("popup");
|
|
await help.click();
|
|
const popup = await popupPromise;
|
|
await popup.close();
|
|
await expect(dialog).toBeVisible();
|
|
await dialog.getByRole("button", { name: "Close", exact: true }).click();
|
|
await expect(dialog).toHaveCount(0);
|
|
await expect(page.getByTestId("open-help-dialog")).toBeFocused();
|
|
});
|
|
|
|
test("widget documentation stays beside its one existing title in display, configuration, and drag markup", async ({ page }) => {
|
|
await page.goto("/?heading-help&widgets&language=en");
|
|
const title = page.getByRole("heading", { name: "Scheduling requests", exact: true });
|
|
const anchor = page.locator(".card-title-with-help");
|
|
await expect(title).toHaveCount(1);
|
|
await expectHelpBesideHeading(anchor);
|
|
await expect(anchor.getByRole("link")).toHaveAttribute("href", "/docs?type=user&topic=scheduling.find-and-decide-meeting-time");
|
|
await page.getByRole("button", { name: "Toggle configuration", exact: true }).click();
|
|
await expect(title).toHaveCount(1);
|
|
await expectHelpBesideHeading(anchor);
|
|
await expect(page.locator(".card-actions .documentation-help-link")).toHaveCount(0);
|
|
await page.getByRole("button", { name: "Toggle drag preview", exact: true }).click();
|
|
// A drag placeholder retains hidden content only to preserve the widget height.
|
|
const preview = page.locator(".dashboard-widget-placeholder-content");
|
|
await expect(preview.locator("h2")).toHaveCount(1);
|
|
await expect(preview.locator(".card-title-with-help .documentation-help-link")).toHaveAttribute("href", "/docs?type=user&topic=scheduling.find-and-decide-meeting-time");
|
|
await expect(preview).toBeHidden();
|
|
await page.getByRole("button", { name: "Toggle drag preview", exact: true }).click();
|
|
await expect(title).toHaveCount(1);
|
|
await expectHelpBesideHeading(anchor);
|
|
});
|