Compare commits
1
Commits
v2026.11.12.2
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3de96f9d7b |
@@ -15,7 +15,7 @@ function subscribeCompact(listener: () => void) {
|
||||
media.addEventListener("change", listener);
|
||||
return () => media.removeEventListener("change", listener);
|
||||
}
|
||||
const rowClass = "min-h-8 gap-2 text-xs active:bg-accent";
|
||||
const rowClass = "min-h-8 gap-2 text-xs transition-none active:bg-accent";
|
||||
|
||||
export function PresentationHistoryMenu({ entries, selectedId, mergedEntry, mergedEntries, onSelect }: PresentationHistoryControls) {
|
||||
const [open, setOpen] = useState(false);
|
||||
|
||||
@@ -6,6 +6,40 @@ test.beforeEach(async ({ page }) => {
|
||||
await prepareWorkbench(page);
|
||||
});
|
||||
|
||||
for (const width of [1440, 1024, 375, 320]) {
|
||||
test(`header hides and restores the expanded timeline at ${width}px`, async ({ page }, testInfo) => {
|
||||
await page.setViewportSize({ width, height: 900 });
|
||||
await page.goto("/", { waitUntil: "domcontentloaded" });
|
||||
const header = page.locator(".workbench-top-bar");
|
||||
const timeline = page.getByRole("region", {
|
||||
name: width >= 1024 ? "运行时间轴" : "移动端运行时间轴摘要", exact: true
|
||||
});
|
||||
const hide = header.getByRole("button", { name: "隐藏运行时间轴", exact: true });
|
||||
await expect(timeline).toBeVisible();
|
||||
await expect(hide).toHaveAttribute("aria-pressed", "true");
|
||||
const bounds = (await hide.boundingBox())!;
|
||||
expect(bounds.x).toBeGreaterThanOrEqual(0);
|
||||
expect(bounds.x + bounds.width).toBeLessThanOrEqual(width);
|
||||
if (width >= 1024) await timeline.getByRole("button", { name: "展开时间轴", exact: true }).click();
|
||||
else {
|
||||
await timeline.getByRole("button", { name: "打开完整运行时间轴", exact: true }).click();
|
||||
await expect(page.getByRole("region", { name: "运行时间轴抽屉", exact: true })).toBeVisible();
|
||||
}
|
||||
await hide.click();
|
||||
await expect(timeline).toBeHidden();
|
||||
await expect(page.getByRole("region", { name: "运行时间轴抽屉", exact: true })).toBeHidden();
|
||||
const show = header.getByRole("button", { name: "显示运行时间轴", exact: true });
|
||||
await expect(show).toHaveAttribute("aria-pressed", "false");
|
||||
await show.click();
|
||||
await expect(timeline).toBeVisible();
|
||||
await expect(hide).toHaveAttribute("aria-pressed", "true");
|
||||
if (width >= 1024) await expect(timeline.getByRole("button", { name: "收起时间轴", exact: true })).toBeVisible();
|
||||
await testInfo.attach(`header-timeline-${width}`, {
|
||||
body: await header.screenshot(), contentType: "image/png"
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
test("desktop controls share focus, hover, press and open states", async ({ page }) => {
|
||||
await page.setViewportSize({ width: 1440, height: 900 });
|
||||
await page.goto("/", { waitUntil: "domcontentloaded" });
|
||||
|
||||
@@ -1,9 +1,25 @@
|
||||
import { expect, test, type Page, type TestInfo } from "@playwright/test";
|
||||
import { expect, test, type Locator, type Page, type TestInfo } from "@playwright/test";
|
||||
import { investigationFixture, mockInvestigationPresentation, selectInvestigation, showInvestigationMap } from "./support/mock-investigation-presentation";
|
||||
import { readThemeColor } from "./support/theme-colors";
|
||||
|
||||
const chart = (id: string, title: string) => ({ action: "open_chart", chart_id: id, evidence_refs: ["synthetic:reading"],
|
||||
chart: { title, chart_type: "line", x_data: ["08:00", "08:15"], series: [{ name: "压力(m)", data: [30, 28] }] } });
|
||||
|
||||
async function sampleFastHoverBackground(items: Locator[]) {
|
||||
const samples: Array<{ actual: string; expected: string }> = [];
|
||||
for (let repeat = 0; repeat < 3; repeat++) {
|
||||
for (const item of items) {
|
||||
const expected = await readThemeColor(item, "--action-selection-soft");
|
||||
await item.hover();
|
||||
const actual = await item.evaluate((node) => new Promise<string>((resolve) => {
|
||||
requestAnimationFrame(() => resolve(getComputedStyle(node).backgroundColor));
|
||||
}));
|
||||
samples.push({ actual, expected });
|
||||
}
|
||||
}
|
||||
return samples;
|
||||
}
|
||||
|
||||
async function captureMenus(page: Page, testInfo: TestInfo, name: string) {
|
||||
for (const menu of await page.getByRole("menu").all()) {
|
||||
await menu.evaluate((node) => Promise.all(node.getAnimations().map((animation) => animation.finished.catch(() => undefined))));
|
||||
@@ -56,8 +72,18 @@ test("hover keeps an expanded category stable across its title, arrow and origin
|
||||
const arrow = root.getByRole("menuitem", { name: "展开图表步骤", exact: true });
|
||||
const title = root.getByRole("menuitem", { name: "图表", exact: true });
|
||||
const steps = page.getByRole("menu", { name: "图表展示步骤", exact: true });
|
||||
const firstLevel = await sampleFastHoverBackground([title, root.getByRole("menuitem", { name: "覆盖层", exact: true })]);
|
||||
await arrow.hover();
|
||||
await expect(steps).toBeVisible();
|
||||
const secondLevel = await sampleFastHoverBackground([
|
||||
steps.getByRole("menuitem", { name: "1. 测点 P1 压力趋势", exact: true }),
|
||||
steps.getByRole("menuitem", { name: "2. 测点 P2 压力趋势", exact: true })
|
||||
]);
|
||||
const backgrounds = [...firstLevel, ...secondLevel];
|
||||
await testInfo.attach("fast-hover-backgrounds", { body: JSON.stringify({ firstLevel, secondLevel }), contentType: "application/json" });
|
||||
expect(backgrounds).toHaveLength(12);
|
||||
expect(backgrounds.every((sample) => sample.expected !== "rgba(0, 0, 0, 0)")).toBe(true);
|
||||
expect(backgrounds.map((sample) => sample.actual)).toEqual(backgrounds.map((sample) => sample.expected));
|
||||
await page.evaluate(() => {
|
||||
const changes: string[] = [];
|
||||
const observer = new MutationObserver((records) => {
|
||||
|
||||
Reference in New Issue
Block a user