import { describe, expect, it } from "vitest"; import type { PhyFile } from "../src/domain/phy"; import { addComponentToParent, addKeyToParent, cloneNodesWithNewIds, createVariantGroupInParent, duplicateNode, insertNodes, } from "../src/domain/phyCommands"; const ids = (() => { let n = 0; return () => `0000000${++n}-0000-4000-8000-000000000000`; })(); const file: PhyFile = { version: "0.1.0", metadata: {}, profiles: [{ id: "p", name: "P", unitSize: { x: 1, y: 1 } }], root: [ { type: "cluster", id: "cl-parent", name: "P", transform: { x: 0, y: 0, rotation: 0 }, children: [] }, ], }; describe("PHY parent insertion and duplication", () => { it("adds keys and components to root, clusters, or variants", () => { let p = addKeyToParent(file, "cl-parent", { x: 2, y: 3, rotation: 0 }, { w: 1, h: 1 }, "p", ids); expect( p.root[0]!.type === "cluster" && (p.root[0]! as import("../src/domain/phy").ClusterNode).children[0]?.type, ).toBe("key"); p = addComponentToParent(p, "cl-parent", { x: 0, y: 0, rotation: 0 }, "@led", ids); expect( p.root[0]!.type === "cluster" && (p.root[0]! as import("../src/domain/phy").ClusterNode).children[1]?.type, ).toBe("component"); }); it("inserts a copied node batch into a selected container", () => { const node = { type: "key" as const, id: "key-source", profile: "p", transform: { x: 1, y: 1, rotation: 0 }, size: { w: 1, h: 1 }, }; const p = insertNodes(file, "cl-parent", [node]); expect( p.root[0]!.type === "cluster" && (p.root[0]! as import("../src/domain/phy").ClusterNode).children, ).toHaveLength(1); }); it("renews IDs and remaps a duplicated group's internal default", () => { const base: PhyFile = { ...file, root: [ { type: "variantGroup", id: "vg-source", name: "VG", transform: { x: 0, y: 0, rotation: 0 }, default: "v-one", children: [ { type: "variant", id: "v-one", name: "One", children: [] }, { type: "variant", id: "v-two", name: "Two", children: [] }, ], }, ], }; const q = duplicateNode(base, "vg-source", ids); const copy = q.root[1]; expect(copy?.type).toBe("variantGroup"); if (copy?.type === "variantGroup") { expect(copy.id).not.toBe("vg-source"); expect(copy.default).not.toBe("v-one"); expect(copy.children.map((v) => v.id)).not.toContain("v-one"); expect(copy.default).toBe(copy.children[0]!.id); } }); it("remaps defaults for variant groups nested inside a copied cluster", () => { const nested: PhyFile["root"][number] = { type: "cluster", id: "outer", transform: { x: 0, y: 0, rotation: 0 }, children: [ { type: "variantGroup", id: "vg-inner", name: "Inner", transform: { x: 1, y: 2, rotation: 0 }, default: "v-inner-a", children: [ { type: "variant", id: "v-inner-a", name: "A", children: [] }, { type: "variant", id: "v-inner-b", name: "B", children: [] }, ], }, ], }; const copy = cloneNodesWithNewIds([nested], ids)[0]; expect(copy?.type).toBe("cluster"); if (copy?.type === "cluster") { const group = copy.children[0]; expect(group?.type).toBe("variantGroup"); if (group?.type === "variantGroup") { expect(group.default).toBe(group.children[0]!.id); expect(group.default).not.toBe("v-inner-a"); } } }); it("creates a variant group inside a cluster or a variant", () => { const variants: Parameters[4] = [{ name: "A" }, { name: "B" }]; let p = createVariantGroupInParent(file, "cl-parent", "G", { x: 0, y: 0, rotation: 0 }, variants, ids); const parent = p.root[0] as import("../src/domain/phy").ClusterNode; expect(p.root).toHaveLength(1); expect(parent.children.map((n) => n.type)).toEqual(["variantGroup"]); const group = parent.children[0] as import("../src/domain/phy").VariantGroupNode; p = createVariantGroupInParent( p, group.children[1]!.id, "Inner", { x: 0, y: 0, rotation: 0 }, variants, ids, ); const updated = (p.root[0] as import("../src/domain/phy").ClusterNode).children[0] as typeof group; expect(updated.children[1]!.children.map((n) => n.type)).toEqual(["variantGroup"]); }); });