Files
next-tjwater-frontend/tests/browser/base-layer-focus.e2e.ts
T
jiang 0ae0a41e61
Generic Container CI/CD / test-build-publish (push) Successful in 2m7s
Frontend CI/CD / build-test-publish-and-deploy (push) Successful in 2m8s
feat(charts): manage investigation charts in a scrolling workspace
2026-11-10 17:56:23 +08:00

88 lines
4.8 KiB
TypeScript

import { expect, test, type Page } from "@playwright/test";
import { mockAgentApi } from "./support/mock-agent-api";
import { mockWorkbenchContext } from "./support/mock-workbench-context";
import { expectThemeColor } from "./support/theme-colors";
test.beforeEach(async ({ page }) => {
await page.emulateMedia({ reducedMotion: "reduce" });
await mockWorkbenchContext(page);
await mockAgentApi(page);
await page.goto("/", { waitUntil: "domcontentloaded" });
});
for (const width of [320, 375, 1440]) {
test(`layer panel basemap selection has one border and no persistent outer ring at ${width}px`, async ({ page }) => {
await page.setViewportSize({ width, height: 1000 });
await page.getByRole("button", { name: /图层:管理地图图层/ }).click();
const panel = page.getByRole("region", { name: "图层", exact: true });
const card = panel.getByRole("button", { name: "无底图", exact: true });
await expect(card).toHaveAttribute("aria-pressed", "true");
await expectThemeColor(card, "border-color", "--action-blue");
await expect(card).toHaveCSS("border-width", "1px");
await expect(card).toHaveCSS("box-shadow", "none");
await card.click();
await expect(card).toHaveCSS("outline-style", "none");
const restingBox = await card.boundingBox();
await page.keyboard.press("Tab");
await card.focus();
await expect(card).toHaveCSS("outline-width", "1px");
await expect(card).toHaveCSS("outline-offset", "-1px");
await expectThemeColor(card, "outline-color", "--action-focus-ring");
expect(await card.boundingBox()).toEqual(restingBox);
await page.keyboard.press("Enter");
await expect(card).toHaveAttribute("aria-pressed", "true");
await panel.screenshot({ path: `test-results/form-focus/layer-panel-${width}.png` });
});
}
test("standalone basemap controls share the same pointer and keyboard boundary", async ({ page }) => {
await renderControls(page);
for (const label of ["面板底图", "浮动底图"]) {
const control = page.getByRole("region", { name: label, exact: true });
if (label === "浮动底图") await control.getByRole("button", { name: "浮动底图:当前 浅色" }).hover();
const selected = control.getByRole("button", { name: "浅色", exact: true });
await expect(selected).toHaveCSS("border-width", "1px");
await expectThemeColor(selected, "border-color", "--action-blue");
const restingShadow = await selected.evaluate((element) => getComputedStyle(element).boxShadow);
expect(restingShadow).not.toMatch(/0px 0px 0px [12]px/);
await selected.click();
await expect(selected).toHaveCSS("outline-style", "none");
await page.keyboard.press("Tab");
await selected.focus();
await expect(selected).toHaveCSS("outline-width", "1px");
await expect(selected).toHaveCSS("outline-offset", "-1px");
await expect(selected).toHaveCSS("box-shadow", restingShadow);
const next = control.getByRole("button", { name: "影像", exact: true });
await next.focus();
await page.keyboard.press("Enter");
await expect(next).toHaveAttribute("aria-pressed", "true");
await expect(selected).toHaveAttribute("aria-pressed", "false");
await control.screenshot({ path: `test-results/form-focus/${label}.png` });
}
});
async function renderControls(page: Page) {
await page.evaluate(async () => {
const entry = await fetch("/src/main.tsx").then((response) => response.text());
const reactPath = entry.match(/["']([^"']*\/react\.js(?:\?[^"']*)?)["']/)?.[1];
const domPath = entry.match(/["']([^"']*\/react-dom_client\.js(?:\?[^"']*)?)["']/)?.[1];
if (!reactPath || !domPath) throw new Error("App React dependency URLs not found");
const paths = [reactPath, domPath, "/src/features/map/core/components/base-layers-control.tsx"];
const [react, dom, controls] = await Promise.all(paths.map((path) => import(path)));
const h = react.default.createElement;
function Examples() {
const [panelId, setPanelId] = react.default.useState("light");
const [floatingId, setFloatingId] = react.default.useState("light");
const options = [{ id: "light", label: "浅色" }, { id: "satellite", label: "影像" }];
return h(react.default.Fragment, null,
h(controls.BaseLayersControl, { title: "面板底图", variant: "panel", options, activeLayerId: panelId, onSelectLayer: setPanelId }),
h(controls.BaseLayersControl, { title: "浮动底图", options, activeLayerId: floatingId, onSelectLayer: setFloatingId })
);
}
const container = document.createElement("div");
container.style.cssText = "position:fixed;z-index:40;top:80px;right:40px;padding:24px;background:var(--surface-reading);display:grid;gap:32px";
document.body.append(container);
dom.default.createRoot(container).render(h(Examples));
});
}