140 lines
3.0 KiB
TypeScript
140 lines
3.0 KiB
TypeScript
import type { PlaitElement } from "@plait/core";
|
|
import { expect, test } from "@playwright/test";
|
|
import { normalizeFlowBoardSnapshot } from "@/app/api/flow-board/_utils";
|
|
import {
|
|
getBoundaryPoints,
|
|
getRelationshipPoints,
|
|
isMindAnnotation,
|
|
validateTopicRange,
|
|
} from "@/lib/flow-board/mind-annotations";
|
|
|
|
test("summaries and boundaries reject gaps, unrelated parents, and opposite root sides", () => {
|
|
expect(
|
|
validateTopicRange(
|
|
[
|
|
[0, 0],
|
|
[0, 1],
|
|
],
|
|
3
|
|
)
|
|
).toBeNull();
|
|
expect(
|
|
validateTopicRange([
|
|
[0, 0],
|
|
[0, 2],
|
|
])
|
|
).not.toBeNull();
|
|
expect(
|
|
validateTopicRange([
|
|
[0, 0],
|
|
[1, 1],
|
|
])
|
|
).not.toBeNull();
|
|
expect(
|
|
validateTopicRange(
|
|
[
|
|
[0, 1],
|
|
[0, 2],
|
|
],
|
|
2
|
|
)
|
|
).not.toBeNull();
|
|
expect(
|
|
validateTopicRange(
|
|
[
|
|
[0, 2],
|
|
[0, 3],
|
|
],
|
|
2
|
|
)
|
|
).toBeNull();
|
|
});
|
|
|
|
test("boundary encloses every expanded descendant and respects padding", () => {
|
|
expect(
|
|
getBoundaryPoints(
|
|
[
|
|
{ x: 100, y: 50, width: 80, height: 30 },
|
|
{ x: 260, y: -20, width: 100, height: 32 },
|
|
{ x: 260, y: 100, width: 120, height: 32 },
|
|
],
|
|
24
|
|
)
|
|
).toEqual([
|
|
[76, -44],
|
|
[404, 156],
|
|
]);
|
|
expect(getBoundaryPoints([])).toBeNull();
|
|
});
|
|
|
|
test("relationship curves route outside aligned topics in horizontal and vertical layouts", () => {
|
|
const source = { x: 0, y: 0, width: 100, height: 40 };
|
|
expect(
|
|
getRelationshipPoints(source, { x: 300, y: 0, width: 80, height: 40 })
|
|
).toEqual([
|
|
[50, 0],
|
|
[195, -72],
|
|
[340, 0],
|
|
]);
|
|
expect(
|
|
getRelationshipPoints(source, { x: 0, y: 200, width: 100, height: 40 })
|
|
).toEqual([
|
|
[100, 20],
|
|
[172, 120],
|
|
[100, 220],
|
|
]);
|
|
expect(
|
|
getRelationshipPoints(source, { x: -300, y: 0, width: 80, height: 40 })
|
|
).toEqual([
|
|
[50, 0],
|
|
[-105, -72],
|
|
[-260, 0],
|
|
]);
|
|
});
|
|
|
|
test("sheet snapshots preserve topic bindings and edited annotation styles", () => {
|
|
const children = [
|
|
{
|
|
id: "relation",
|
|
type: "arrow-line",
|
|
points: [
|
|
[10, 20],
|
|
[30, 40],
|
|
],
|
|
strokeColor: "#112233",
|
|
strokeWidth: 3,
|
|
mindAnnotation: {
|
|
kind: "relationship",
|
|
sourceId: "research",
|
|
targetId: "design",
|
|
},
|
|
},
|
|
{
|
|
id: "boundary",
|
|
type: "geometry",
|
|
points: [
|
|
[0, 0],
|
|
[100, 100],
|
|
],
|
|
mindAnnotation: { kind: "boundary", topicIds: ["research"], padding: 24 },
|
|
},
|
|
];
|
|
const restored = normalizeFlowBoardSnapshot(
|
|
JSON.parse(
|
|
JSON.stringify({
|
|
activeSheetId: "plan",
|
|
sheets: [
|
|
{ id: "plan", title: "计划", children },
|
|
{ id: "empty", title: "空白", children: [] },
|
|
],
|
|
})
|
|
)
|
|
);
|
|
expect(restored.children).toEqual(children);
|
|
expect(restored.sheets?.[1].children).toEqual([]);
|
|
expect((restored.children as PlaitElement[]).every(isMindAnnotation)).toBe(
|
|
true
|
|
);
|
|
expect(isMindAnnotation({ id: "old-arrow", type: "arrow-line" })).toBe(false);
|
|
});
|