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.
111 lines
4.1 KiB
TypeScript
111 lines
4.1 KiB
TypeScript
import { chooseXmindLayout, clickXmindAction, openXmindStructures } from "./editor-actions";
|
|
import { expect, test } from "@playwright/test";
|
|
import JSZip from "jszip";
|
|
|
|
test("tree table aligns hierarchy cells, edits topics and preserves its XMind structure", async ({
|
|
page,
|
|
}) => {
|
|
const errors: string[] = [];
|
|
page.on("pageerror", (error) => errors.push(error.message));
|
|
await page.goto("/dev/flow-board-preview", { waitUntil: "commit" });
|
|
const zip = new JSZip();
|
|
zip.file(
|
|
"content.json",
|
|
JSON.stringify([
|
|
{
|
|
title: "树形表格",
|
|
rootTopic: {
|
|
id: "root",
|
|
title: "项目清单",
|
|
structureClass: "org.xmind.ui.treetable.toptitle",
|
|
children: {
|
|
attached: [
|
|
{
|
|
id: "a",
|
|
title: "产品",
|
|
children: {
|
|
attached: [
|
|
{ id: "a1", title: "需求分析" },
|
|
{ id: "a2", title: "原型设计" },
|
|
],
|
|
},
|
|
},
|
|
{ id: "b", title: "研发" },
|
|
{ id: "c", title: "发布" },
|
|
],
|
|
},
|
|
},
|
|
},
|
|
])
|
|
);
|
|
await page.locator("input[accept*=xmind]").setInputFiles({
|
|
name: "树形表格.xmind",
|
|
mimeType: "application/octet-stream",
|
|
buffer: await zip.generateAsync({ type: "nodebuffer" }),
|
|
});
|
|
|
|
const canvas = page.locator(".drawnix");
|
|
const table = canvas.locator('[data-special-table="treeTable"]');
|
|
await expect(table).toBeVisible();
|
|
await expect(table.locator("[data-special-table-cell]")).toHaveCount(6);
|
|
await clickXmindAction(page, "适应画布");
|
|
const box = async (title: string) =>
|
|
(await canvas.getByText(title, { exact: true }).boundingBox())!;
|
|
const root = await box("项目清单");
|
|
const product = await box("产品");
|
|
const requirement = await box("需求分析");
|
|
const prototype = await box("原型设计");
|
|
const development = await box("研发");
|
|
expect(root.y + root.height).toBeLessThan(product.y);
|
|
expect(requirement.x).toBeGreaterThan(product.x + product.width);
|
|
expect(prototype.x).toBe(requirement.x);
|
|
expect(development.y).toBeGreaterThan(prototype.y);
|
|
|
|
await canvas.getByText("研发", { exact: true }).click();
|
|
await page.getByRole("button", { name: "子主题", exact: true }).click();
|
|
await expect(canvas.locator('[contenteditable="true"]')).toBeFocused();
|
|
await page.keyboard.insertText("接口联调");
|
|
await page
|
|
.locator(".flow-board-canvas-shell")
|
|
.click({ position: { x: 100, y: 100 } });
|
|
await expect(canvas.getByText("接口联调", { exact: true })).toBeVisible();
|
|
await expect(table.locator("[data-special-table-cell]")).toHaveCount(7);
|
|
|
|
await canvas.getByText("项目清单", { exact: true }).click();
|
|
await openXmindStructures(page);
|
|
await expect(
|
|
page.getByRole("complementary", { name: "格式面板" }).getByLabel("树形表格", { exact: true })
|
|
).toHaveAttribute("aria-pressed", "true");
|
|
await chooseXmindLayout(page, "向右逻辑");
|
|
await expect(table).toHaveCount(0);
|
|
await clickXmindAction(page, "撤销");
|
|
await expect(table).toBeVisible();
|
|
|
|
const downloading = page.waitForEvent("download");
|
|
await page.getByRole("button", { name: "导出 XMind", exact: true }).click();
|
|
const stream = await (await downloading).createReadStream();
|
|
const chunks = [];
|
|
for await (const chunk of stream!) chunks.push(chunk);
|
|
const buffer = Buffer.concat(chunks);
|
|
const exported = await JSZip.loadAsync(buffer);
|
|
const content = JSON.parse(
|
|
await exported.file("content.json")!.async("string")
|
|
);
|
|
expect(content[0].rootTopic.structureClass).toBe(
|
|
"org.xmind.ui.treetable.toptitle"
|
|
);
|
|
await page.locator("input[accept*=xmind]").setInputFiles({
|
|
name: "树形表格往返.xmind",
|
|
mimeType: "application/octet-stream",
|
|
buffer,
|
|
});
|
|
await expect(table).toBeVisible();
|
|
await expect(canvas.getByText("接口联调", { exact: true })).toBeVisible();
|
|
await clickXmindAction(page, "适应画布");
|
|
await page.screenshot({
|
|
path: test.info().outputPath("tree-table-preview.png"),
|
|
animations: "disabled",
|
|
});
|
|
expect(errors).toEqual([]);
|
|
});
|