Fix documented known issues in tests

- Refactor `popover.spec.ts` to use shared helper functions in `helpers/popoverUtils.ts`, resolving potential ReferenceErrors.
- Add `ensureTestAssets` check to E2E tests (`ui-modals.spec.ts`, `popover.spec.ts`) to verify `css/tailwind.generated.css` exists before running, preventing confusing 404 errors.
- Fix visual regression instability in `kitchen-sink.spec.ts` by enforcing explicit viewport dimensions and resetting body margins in injected styles.
- Update `KNOWN_ISSUES.md` to remove the resolved issues.

Co-authored-by: PR0M3TH3AN <[email protected]>
This commit is contained in:
google-labs-jules[bot]andPR0M3TH3AN committed 2026-02-04 21:04:07 +00:00
1 parent e88f6a3cba
commit d8a9e5940f
7 files changed
+129 -94

No files matched your search

+107
View File
@@ -0,0 +1,107 @@
import type { Locator } from "@playwright/test";
export interface PopoverMetrics {
rect: {
top: number;
left: number;
right: number;
bottom: number;
width: number;
height: number;
};
triggerRect?: {
top: number;
left: number;
right: number;
bottom: number;
width: number;
height: number;
};
viewport: { width: number; height: number };
placement: string;
state: string;
popoverMaxWidth: string;
tokenMaxWidth: string;
}
export async function getPanelMetrics(locator: Locator): Promise<PopoverMetrics> {
return locator.evaluate((node) => {
const rect = node.getBoundingClientRect();
const viewportWidth = window.innerWidth;
const viewportHeight = window.innerHeight;
const tokenValue = window
.getComputedStyle(document.documentElement)
.getPropertyValue("--popover-inline-safe-max")
.trim();
const popoverMaxWidth = window
.getComputedStyle(node)
.getPropertyValue("--popover-max-width")
.trim();
return {
rect: {
top: rect.top,
left: rect.left,
right: rect.right,
bottom: rect.bottom,
width: rect.width,
height: rect.height,
},
viewport: { width: viewportWidth, height: viewportHeight },
placement: (node as HTMLElement).dataset.popoverPlacement || "",
state: (node as HTMLElement).dataset.popoverState || "",
popoverMaxWidth,
tokenMaxWidth: tokenValue,
};
});
}
export async function getPanelWithTriggerMetrics(panel: Locator, trigger: Locator): Promise<PopoverMetrics> {
const triggerHandle = await trigger.elementHandle();
if (!triggerHandle) {
throw new Error("Trigger element is not attached");
}
try {
return await panel.evaluate((node, triggerElement) => {
const rect = node.getBoundingClientRect();
const triggerRect = triggerElement.getBoundingClientRect();
const viewportWidth = window.innerWidth;
const viewportHeight = window.innerHeight;
const tokenValue = window
.getComputedStyle(document.documentElement)
.getPropertyValue("--popover-inline-safe-max")
.trim();
const popoverMaxWidth = window
.getComputedStyle(node)
.getPropertyValue("--popover-max-width")
.trim();
return {
rect: {
top: rect.top,
left: rect.left,
right: rect.right,
bottom: rect.bottom,
width: rect.width,
height: rect.height,
},
triggerRect: {
top: triggerRect.top,
left: triggerRect.left,
right: triggerRect.right,
bottom: triggerRect.bottom,
width: triggerRect.width,
height: triggerRect.height,
},
viewport: { width: viewportWidth, height: viewportHeight },
placement: (node as HTMLElement).dataset.popoverPlacement || "",
state: (node as HTMLElement).dataset.popoverState || "",
popoverMaxWidth,
tokenMaxWidth: tokenValue,
};
}, triggerHandle);
} finally {
await triggerHandle.dispose();
}
}
+9
View File
@@ -1,5 +1,14 @@
import type { Page } from "@playwright/test";
export async function ensureTestAssets(page: Page): Promise<void> {
const cssResponse = await page.request.head("/css/tailwind.generated.css");
if (!cssResponse.ok()) {
throw new Error(
"Test asset check failed: css/tailwind.generated.css is missing (404). Run `npm run build:css` before testing.",
);
}
}
export async function applyReducedMotion(page: Page): Promise<void> {
await page.emulateMedia({ reducedMotion: "reduce" });
await page.addStyleTag({
+7 -83
View File
@@ -1,93 +1,15 @@
import { expect, test } from "@playwright/test";
import type { Locator } from "@playwright/test";
import {
getPanelMetrics,
getPanelWithTriggerMetrics,
} from "./helpers/popoverUtils";
import {
applyReducedMotion,
ensureTestAssets,
failOnConsoleErrors,
waitForRAF,
} from "./helpers/uiTestUtils";
async function getPanelMetrics(locator: Locator) {
return locator.evaluate((node) => {
const rect = node.getBoundingClientRect();
const viewportWidth = window.innerWidth;
const viewportHeight = window.innerHeight;
const tokenValue = window
.getComputedStyle(document.documentElement)
.getPropertyValue("--popover-inline-safe-max")
.trim();
const popoverMaxWidth = window
.getComputedStyle(node)
.getPropertyValue("--popover-max-width")
.trim();
return {
rect: {
top: rect.top,
left: rect.left,
right: rect.right,
bottom: rect.bottom,
width: rect.width,
height: rect.height,
},
viewport: { width: viewportWidth, height: viewportHeight },
placement: node.dataset.popoverPlacement || "",
state: node.dataset.popoverState || "",
popoverMaxWidth,
tokenMaxWidth: tokenValue,
};
});
}
async function getPanelWithTriggerMetrics(panel: Locator, trigger: Locator) {
const triggerHandle = await trigger.elementHandle();
if (!triggerHandle) {
throw new Error("Trigger element is not attached");
}
try {
return await panel.evaluate((node, triggerElement) => {
const rect = node.getBoundingClientRect();
const triggerRect = triggerElement.getBoundingClientRect();
const viewportWidth = window.innerWidth;
const viewportHeight = window.innerHeight;
const tokenValue = window
.getComputedStyle(document.documentElement)
.getPropertyValue("--popover-inline-safe-max")
.trim();
const popoverMaxWidth = window
.getComputedStyle(node)
.getPropertyValue("--popover-max-width")
.trim();
return {
rect: {
top: rect.top,
left: rect.left,
right: rect.right,
bottom: rect.bottom,
width: rect.width,
height: rect.height,
},
triggerRect: {
top: triggerRect.top,
left: triggerRect.left,
right: triggerRect.right,
bottom: triggerRect.bottom,
width: triggerRect.width,
height: triggerRect.height,
},
viewport: { width: viewportWidth, height: viewportHeight },
placement: node.dataset.popoverPlacement || "",
state: node.dataset.popoverState || "",
popoverMaxWidth,
tokenMaxWidth: tokenValue,
};
}, triggerHandle);
} finally {
await triggerHandle.dispose();
}
}
function assertWithinViewport(metrics: {
rect: { top: number; left: number; right: number; bottom: number };
viewport: { width: number; height: number };
@@ -101,6 +23,7 @@ function assertWithinViewport(metrics: {
test.describe("popover layout scenarios", () => {
test.beforeEach(async ({ page }) => {
await ensureTestAssets(page);
await applyReducedMotion(page);
failOnConsoleErrors(page);
await page.goto("/docs/popover-scenarios.html", { waitUntil: "networkidle" });
@@ -198,6 +121,7 @@ test.describe("popover layout scenarios", () => {
test.describe("popover demo alignments", () => {
test.beforeEach(async ({ page }) => {
await ensureTestAssets(page);
await applyReducedMotion(page);
failOnConsoleErrors(page);
await page.goto("/views/dev/popover-demo.html", { waitUntil: "networkidle" });
+3
View File
@@ -1,6 +1,7 @@
import { expect, test } from "@playwright/test";
import {
applyReducedMotion,
ensureTestAssets,
failOnConsoleErrors,
forceOpenModal,
} from "./helpers/uiTestUtils";
@@ -19,6 +20,7 @@ test.describe("login modal flows", () => {
});
test.beforeEach(async ({ page }) => {
await ensureTestAssets(page);
await applyReducedMotion(page);
failOnConsoleErrors(page);
await page.goto("/components/login-modal.html", { waitUntil: "networkidle" });
@@ -202,6 +204,7 @@ test.describe("component modal pages", () => {
for (const pageName of modalPages) {
test(`closes ${pageName} modal`, async ({ page }) => {
await ensureTestAssets(page);
await applyReducedMotion(page);
failOnConsoleErrors(page);
await page.goto(`/components/${pageName}.html`, {