Files

112 lines
3.7 KiB
TypeScript

import { expect, test, type Locator } from "playwright/test";
test("agent header reveals the shell acrylic without nesting another filter", async ({ page }) => {
await page.goto("/", { waitUntil: "domcontentloaded" });
await page.waitForTimeout(250);
const topBar = page.locator("header.acrylic-navigation");
const agentPanel = page.locator('aside[aria-label="Agent 命令面板"]');
const agentHeader = agentPanel.locator(".agent-panel-header");
await expect(topBar).toBeVisible();
await expect(agentPanel).toBeVisible();
await expect(agentHeader).toBeVisible();
await expectAcrylicSurface(topBar);
await expectAcrylicSurface(agentPanel);
await expectTransparentAcrylicContext(agentHeader);
await expectLightweightContextSurfaces(agentPanel.locator(".agent-panel-conversation"));
await expectSolidInternalSurfaces(agentPanel.locator(".agent-panel-band"));
});
async function expectAcrylicSurface(shell: Locator) {
const composition = await shell.evaluate((element) => {
const style = getComputedStyle(element);
const filteredDescendants: string[] = [];
for (const descendant of element.querySelectorAll("*")) {
if (getComputedStyle(descendant).backdropFilter !== "none") {
filteredDescendants.push(descendant.className);
}
}
return {
backdropFilter: style.backdropFilter,
backgroundColor: style.backgroundColor,
filteredDescendants,
transform: style.transform,
willChange: style.willChange
};
});
expect(composition.backdropFilter).toContain("blur(");
expect(getAlpha(composition.backgroundColor)).toBeLessThan(1);
expect(composition.filteredDescendants).toEqual([]);
expect(composition.transform).toBe("none");
expect(composition.willChange).toBe("auto");
}
function getAlpha(color: string) {
const match = color.match(/^rgba\([^,]+,[^,]+,[^,]+,\s*([\d.]+)\)$/);
return match ? Number(match[1]) : 1;
}
async function expectTransparentAcrylicContext(header: Locator) {
const style = await header.evaluate((element) => {
const computedStyle = getComputedStyle(element);
return {
backdropFilter: computedStyle.backdropFilter,
backgroundColor: computedStyle.backgroundColor,
className: element.className,
webkitBackdropFilter: computedStyle.getPropertyValue("-webkit-backdrop-filter")
};
});
expect(style.backdropFilter).toBe("none");
expect(style.backgroundColor).toBe("rgba(0, 0, 0, 0)");
expect(["", "none"]).toContain(style.webkitBackdropFilter);
expect(String(style.className)).not.toContain("acrylic-");
}
async function expectLightweightContextSurfaces(surfaces: Locator) {
const surfaceStyles = await surfaces.evaluateAll((elements) =>
elements.map((element) => {
const style = getComputedStyle(element);
return {
backdropFilter: style.backdropFilter,
backgroundColor: style.backgroundColor
};
})
);
expect(surfaceStyles.length).toBeGreaterThan(0);
for (const style of surfaceStyles) {
expect(style.backdropFilter).toBe("none");
expect(getAlpha(style.backgroundColor)).toBeLessThanOrEqual(0.12);
}
}
async function expectSolidInternalSurfaces(surfaces: Locator) {
const surfaceStyles = await surfaces.evaluateAll((elements) =>
elements.map((element) => {
const style = getComputedStyle(element);
return {
backdropFilter: style.backdropFilter,
className: element.className,
webkitBackdropFilter: style.getPropertyValue("-webkit-backdrop-filter")
};
})
);
expect(surfaceStyles.length).toBeGreaterThan(0);
for (const style of surfaceStyles) {
expect(style.backdropFilter).toBe("none");
expect(["", "none"]).toContain(style.webkitBackdropFilter);
expect(String(style.className)).not.toContain("acrylic-");
}
}