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); });