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.
80 lines
4.6 KiB
TypeScript
Executable File
80 lines
4.6 KiB
TypeScript
Executable File
import { expect, test, type Locator } from "@playwright/test";
|
|
|
|
const tableOnlyCards = ["direct-table", "collapsible-table", "loading-table", "admin-table", "loading-admin-table", "connection-table", "loading-connection-table", "explicit-table"];
|
|
|
|
async function expectFlush(card: Locator) {
|
|
const geometry = await card.evaluate((element) => {
|
|
const body = element.querySelector(".card-body")!;
|
|
const surface = element.querySelector(".data-grid-shell, .connection-tree")!;
|
|
const cardRect = element.getBoundingClientRect();
|
|
const bodyRect = body.getBoundingClientRect();
|
|
const rect = surface.getBoundingClientRect();
|
|
const grid = surface.querySelector(".data-grid");
|
|
const scrollRegion = surface.querySelector(".data-grid-scroll-region");
|
|
return {
|
|
left: rect.left - cardRect.left, right: cardRect.right - rect.right,
|
|
top: rect.top - bodyRect.top, bottom: cardRect.bottom - rect.bottom,
|
|
padding: getComputedStyle(body).padding, border: getComputedStyle(surface).borderWidth,
|
|
unfilledWidth: grid && scrollRegion ? scrollRegion.clientWidth - grid.getBoundingClientRect().width : 0
|
|
};
|
|
});
|
|
expect(geometry.padding).toBe("0px");
|
|
expect(geometry.border).toBe("0px");
|
|
expect(geometry.unfilledWidth).toBeLessThanOrEqual(1);
|
|
for (const edge of [geometry.left, geometry.right, geometry.top, geometry.bottom]) expect(Math.abs(edge)).toBeLessThanOrEqual(1);
|
|
}
|
|
|
|
for (const width of [1280, 390, 320]) {
|
|
test(`table-only cards use their full interior without negative margins at ${width}px`, async ({ page }) => {
|
|
const errors: string[] = [];
|
|
page.on("pageerror", (error) => errors.push(error.message));
|
|
await page.setViewportSize({ width, height: 900 });
|
|
await page.goto("/?data-grid-layout&table-cards&language=en&theme=light");
|
|
for (const id of tableOnlyCards) await expectFlush(page.getByTestId(id));
|
|
for (const id of ["mixed-content", "loading-mixed-content"]) {
|
|
const body = page.getByTestId(id).locator(".card-body");
|
|
await expect(body).toHaveCSS("padding", "22px 24px");
|
|
await expect(body.locator(".data-grid-shell")).toHaveCSS("border-width", "1px");
|
|
}
|
|
const context = page.getByTestId("table-with-context");
|
|
await expect(context.locator(".card-body")).toHaveCSS("padding", "0px");
|
|
await expect(context.locator(".content-section")).toHaveCSS("padding", "18px");
|
|
const contextBounds = await context.boundingBox();
|
|
const contextGrid = await context.locator(".data-grid-shell").boundingBox();
|
|
expect(contextGrid!.x - contextBounds!.x).toBeCloseTo(1, 0);
|
|
expect(contextBounds!.width - contextGrid!.width).toBeCloseTo(2, 0);
|
|
await expect(page.getByTestId("standalone-table").locator(".data-grid-shell")).toHaveCSS("border-width", "1px");
|
|
expect(await page.evaluate(() => document.documentElement.scrollWidth <= innerWidth + 1)).toBe(true);
|
|
expect(errors).toEqual([]);
|
|
});
|
|
}
|
|
|
|
test("loading overlays and collapse do not change table insets or lose row actions", async ({ page }) => {
|
|
await page.setViewportSize({ width: 390, height: 900 });
|
|
await page.goto("/?data-grid-layout&table-cards&language=en&theme=light");
|
|
const before = await page.getByTestId("loading-table").boundingBox();
|
|
await page.getByRole("button", { name: "Toggle loading", exact: true }).click();
|
|
for (const id of ["loading-table", "loading-admin-table", "loading-connection-table", "explicit-table"]) {
|
|
const card = page.getByTestId(id);
|
|
await expectFlush(card);
|
|
const frame = await card.locator(".loading-frame").boundingBox();
|
|
const overlay = await card.locator(".loading-frame-overlay").boundingBox();
|
|
expect(overlay).toEqual(frame);
|
|
await expect(card.locator(".loading-frame")).toHaveAttribute("aria-busy", "true");
|
|
}
|
|
expect(await page.getByTestId("loading-table").boundingBox()).toEqual(before);
|
|
await page.getByRole("button", { name: "Toggle loading", exact: true }).click();
|
|
const collapsible = page.getByTestId("collapsible-table");
|
|
await collapsible.locator(".card-collapse-toggle").click();
|
|
await expect(collapsible.locator(".data-grid-shell")).toHaveCount(0);
|
|
await collapsible.locator(".card-collapse-toggle").click();
|
|
await expectFlush(collapsible);
|
|
const direct = page.getByTestId("direct-table");
|
|
const scroller = direct.locator(".data-grid-scroll-region");
|
|
expect(await scroller.evaluate((element) => element.scrollWidth > element.clientWidth)).toBe(true);
|
|
await scroller.evaluate((element) => { element.scrollLeft = element.scrollWidth; });
|
|
const action = direct.getByRole("button", { name: "Inspect Alpha", exact: true });
|
|
await action.click();
|
|
await expect(page.getByTestId("card-table-inspected")).toHaveText("Alpha");
|
|
});
|