Add native-style menus, search and presentation controls, typography resources, and Xmind import/export styling support. Bundle canvas styles for preview and production, show marquee borders and selection fills, and align editor density with the project UI. Include interaction regression coverage and client comparison notes.
108 lines
4.6 KiB
TypeScript
108 lines
4.6 KiB
TypeScript
import { chooseXmindLayout, clickXmindAction, clickXmindSheet } from "./editor-actions";
|
|
import { expect, type Locator, type Page, test } from "@playwright/test";
|
|
|
|
async function importMap(page: Page) {
|
|
// Exercise the actual Markdown importer with a test-only cloud response.
|
|
await page.route("**/api/flow-board/files", async (route) => {
|
|
await route.fulfill({
|
|
json: {
|
|
data: {
|
|
...route.request().postDataJSON(),
|
|
id: "test-map",
|
|
createdAt: new Date().toISOString(),
|
|
updatedAt: new Date().toISOString(),
|
|
},
|
|
},
|
|
});
|
|
});
|
|
await page.goto("/dev/flow-board-preview", { waitUntil: "commit" });
|
|
await page.locator("input[type=file][accept*=md]").setInputFiles({
|
|
name: "项目计划.md",
|
|
mimeType: "text/markdown",
|
|
buffer: Buffer.from(
|
|
"# 项目计划\n## 产品调研\n### 用户访谈\n### 竞品分析\n## 设计方案\n### 视觉设计\n### 交互设计\n## 开发实现\n### 前端开发\n### 质量验证"
|
|
),
|
|
});
|
|
await expect(page.getByText("用户访谈", { exact: true })).toBeVisible();
|
|
}
|
|
|
|
function bounds(locator: Locator) {
|
|
return locator.evaluate((element) => {
|
|
const box = (element as unknown as SVGGraphicsElement).getBBox();
|
|
return { x: box.x, y: box.y, width: box.width, height: box.height };
|
|
});
|
|
}
|
|
|
|
test("annotations follow layout and collapse, persist across sheets, and undo with deleted topics", async ({
|
|
page,
|
|
}) => {
|
|
const errors: string[] = [];
|
|
page.on("pageerror", (error) => errors.push(error.message));
|
|
await importMap(page);
|
|
await page.getByText("用户访谈", { exact: true }).click();
|
|
await page.getByRole("button", { name: "联系", exact: true }).click();
|
|
await expect(
|
|
page.getByRole("status").filter({ hasText: "点击另一个主题" })
|
|
).toBeVisible();
|
|
await page.getByText("视觉设计", { exact: true }).click();
|
|
await page.getByLabel("联系文字", { exact: true }).fill("调研驱动设计");
|
|
const relationText = page
|
|
.locator(".drawnix")
|
|
.getByText("调研驱动设计", { exact: true });
|
|
await expect(relationText).toBeVisible();
|
|
await expect(page.locator("[plait-arrow-line=true]")).toHaveCount(1);
|
|
|
|
await page.getByText("产品调研", { exact: true }).click();
|
|
await page.getByRole("button", { name: "外框", exact: true }).click();
|
|
await page.getByLabel("外框留白").selectOption("24");
|
|
const boundary = page.locator("[plait-geometry=true]");
|
|
const originalBounds = await bounds(boundary);
|
|
await page.locator(".drawnix").getByText("项目计划", { exact: true }).click();
|
|
await chooseXmindLayout(page, "向下逻辑");
|
|
await expect.poll(() => bounds(boundary)).not.toEqual(originalBounds);
|
|
await chooseXmindLayout(page, "向右逻辑");
|
|
await expect.poll(() => bounds(boundary)).toEqual(originalBounds);
|
|
|
|
await page.getByText("产品调研", { exact: true }).click();
|
|
const expanded = await bounds(boundary);
|
|
await page.keyboard.press("ControlOrMeta+/");
|
|
await expect(page.getByText("用户访谈", { exact: true })).toHaveCount(0);
|
|
await expect
|
|
.poll(async () => (await bounds(boundary)).width)
|
|
.toBeLessThan(expanded.width);
|
|
await expect(relationText).toBeVisible();
|
|
await page.keyboard.press("ControlOrMeta+/");
|
|
await expect(page.getByText("用户访谈", { exact: true })).toBeVisible();
|
|
await expect.poll(() => bounds(boundary)).toEqual(expanded);
|
|
|
|
await page.getByRole("button", { name: "新增画布", exact: true }).click();
|
|
await expect(relationText).toHaveCount(0);
|
|
await clickXmindSheet(page, "画布 1");
|
|
await expect(relationText).toBeVisible();
|
|
await expect(boundary).toHaveCount(1);
|
|
await page.getByText("视觉设计", { exact: true }).click();
|
|
await page.keyboard.press("Backspace");
|
|
await expect(relationText).toHaveCount(0);
|
|
await clickXmindAction(page, "撤销");
|
|
await expect(relationText).toBeVisible();
|
|
await clickXmindAction(page, "重做");
|
|
await expect(relationText).toHaveCount(0);
|
|
expect(errors).toEqual([]);
|
|
});
|
|
|
|
test("summary uses selected branches and relationship creation can be cancelled", async ({
|
|
page,
|
|
}) => {
|
|
await importMap(page);
|
|
await page.getByText("开发实现", { exact: true }).click();
|
|
await page.getByRole("button", { name: "概要", exact: true }).click();
|
|
await expect(
|
|
page.locator(".drawnix").getByText("摘要", { exact: true })
|
|
).toBeVisible();
|
|
await page.getByText("用户访谈", { exact: true }).click();
|
|
await page.getByRole("button", { name: "联系", exact: true }).click();
|
|
await page.keyboard.press("Escape");
|
|
await page.getByText("视觉设计", { exact: true }).click();
|
|
await expect(page.locator("[plait-arrow-line=true]")).toHaveCount(0);
|
|
});
|