ai-chatbot/tests/flow-board/special-layouts.spec.ts

124 lines
5.1 KiB
TypeScript

import { expect, test } from "@playwright/test";
import JSZip from "jszip";
test("special layouts change geometry and connectors, edit normally and round-trip their 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: "结构试验",
relationships: [{ end1Id: "a", end2Id: "b", title: "关联" }],
rootTopic: {
id: "root",
title: "中心主题",
structureClass: "org.xmind.ui.fishbone.leftHeaded",
children: {
attached: [
{
id: "a",
title: "分支一",
children: {
attached: [
{ id: "a1", title: "细分任务一" },
{ id: "a2", title: "细分任务二" },
],
},
},
{ id: "b", title: "分支二" },
{ id: "c", title: "分支三" },
{ id: "d", 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");
await expect(page.locator('[plait-arrow-line="true"]')).toHaveCount(1);
await expect(canvas.locator('[data-special-axis="fishbone"]')).toHaveCount(1);
await expect(
canvas.locator('[data-special-connector="fishbone"]')
).toHaveCount(4);
await page.getByRole("button", { name: "适应画布", exact: true }).click();
const rect = async (title: string) =>
(await canvas.getByText(title, { exact: true }).boundingBox())!;
const center = await rect("中心主题");
const a = await rect("分支一");
const b = await rect("分支二");
const c = await rect("分支三");
expect(a.y + a.height).toBeLessThan(center.y);
expect(b.y).toBeGreaterThan(center.y + center.height);
expect(c.x).toBeGreaterThan(a.x + a.width);
await canvas.getByText("中心主题", { exact: true }).click();
await expect(
page.getByRole("button", { name: "鱼骨图", exact: true })
).toHaveAttribute("aria-pressed", "true");
await page.screenshot({
path: test.info().outputPath("fishbone-preview.png"),
animations: "disabled",
});
await page.getByRole("button", { name: "水平时间轴", exact: true }).click();
await expect(canvas.locator('[data-special-axis="timeline"]')).toHaveCount(1);
await expect(
canvas.locator('[data-special-connector="timeline"] circle')
).toHaveCount(4);
await expect(canvas.locator('[data-special-axis="fishbone"]')).toHaveCount(0);
await page.getByRole("button", { name: "撤销", exact: true }).click();
await expect(canvas.locator('[data-special-axis="fishbone"]')).toHaveCount(1);
await page.getByRole("button", { name: "重做", exact: true }).click();
await expect(canvas.locator('[data-special-axis="timeline"]')).toHaveCount(1);
await canvas.getByText("分支二", { exact: true }).dblclick();
await page.keyboard.press("ControlOrMeta+A");
await page.keyboard.insertText("已编辑的时间节点");
await page
.locator(".flow-board-canvas-shell")
.click({ position: { x: 80, y: 80 } });
await expect(
canvas.getByText("已编辑的时间节点", { exact: true })
).toBeVisible();
await canvas.getByText("分支三", { exact: true }).click();
await page.getByRole("button", { name: "子主题", exact: true }).click();
await expect(canvas.locator('[contenteditable="true"]')).toBeFocused();
await page.keyboard.press("ControlOrMeta+A");
await page.keyboard.insertText("新增时间任务");
await page
.locator(".flow-board-canvas-shell")
.click({ position: { x: 80, y: 80 } });
await expect(canvas.getByText("新增时间任务", { exact: true })).toBeVisible();
await canvas.getByText("中心主题", { exact: true }).click();
await page.getByRole("button", { name: "括号图", exact: true }).click();
await expect(
canvas.locator('[data-special-structure="brace"] path')
).toHaveCount(3);
await expect(canvas.locator("[data-special-axis]")).toHaveCount(0);
await page.screenshot({
path: test.info().outputPath("brace-preview.png"),
animations: "disabled",
});
const downloading = page.waitForEvent("download");
await page.getByRole("button", { name: "导出 XMind", exact: true }).click();
const download = await downloading;
const stream = await download.createReadStream();
const chunks = [];
for await (const chunk of stream!) chunks.push(chunk);
const exported = await JSZip.loadAsync(Buffer.concat(chunks));
const content = JSON.parse(
await exported.file("content.json")!.async("string")
);
expect(content[0].rootTopic.structureClass).toBe("org.xmind.ui.brace.right");
await page.getByRole("button", { name: "向右逻辑", exact: true }).click();
await expect(canvas.locator("[data-special-structure]")).toHaveCount(0);
expect(errors).toEqual([]);
});