import { describe, it, expect, beforeEach } from "vitest"; import { useGraphStore } from "./useGraphStore"; import type { Node, Edge } from "@xyflow/react"; const makeNode = (id: string, label = "Node"): Node => ({ id, type: "default", position: { x: 0, y: 0 }, data: { label }, }); const makeEdge = (id: string, source: string, target: string): Edge => ({ id, source, target, }); describe("useGraphStore", () => { beforeEach(() => { useGraphStore.setState({ nodes: [], edges: [], viewport: { x: 0, y: 0, zoom: 1 }, nodeCount: 0, zoomLevel: 100, }); }); describe("initializeFromGraphData", () => { it("should set nodes, edges, and nodeCount", () => { const nodes = [makeNode("n1"), makeNode("n2")]; const edges = [makeEdge("e1", "n1", "n2")]; useGraphStore.getState().initializeFromGraphData(nodes, edges); expect(useGraphStore.getState().nodes).toHaveLength(2); expect(useGraphStore.getState().edges).toHaveLength(1); expect(useGraphStore.getState().nodeCount).toBe(2); }); }); describe("setNodes", () => { it("should replace nodes and update nodeCount", () => { useGraphStore.getState().setNodes([makeNode("a"), makeNode("b"), makeNode("c")]); expect(useGraphStore.getState().nodes).toHaveLength(3); expect(useGraphStore.getState().nodeCount).toBe(3); }); it("should handle empty array", () => { useGraphStore.getState().setNodes([makeNode("x")]); useGraphStore.getState().setNodes([]); expect(useGraphStore.getState().nodes).toEqual([]); expect(useGraphStore.getState().nodeCount).toBe(0); }); }); describe("setEdges", () => { it("should replace edges", () => { const edges = [makeEdge("e1", "a", "b"), makeEdge("e2", "b", "c")]; useGraphStore.getState().setEdges(edges); expect(useGraphStore.getState().edges).toHaveLength(2); }); }); describe("onNodesChange", () => { it("should apply node position changes", () => { useGraphStore.getState().setNodes([makeNode("n1")]); useGraphStore.getState().onNodesChange([ { type: "position", id: "n1", position: { x: 100, y: 200 }, }, ]); const updatedNode = useGraphStore.getState().nodes[0]; expect(updatedNode!.position).toEqual({ x: 100, y: 200 }); }); it("should update nodeCount when nodes are removed", () => { useGraphStore.getState().setNodes([makeNode("n1"), makeNode("n2")]); expect(useGraphStore.getState().nodeCount).toBe(2); useGraphStore.getState().onNodesChange([ { type: "remove", id: "n1" }, ]); expect(useGraphStore.getState().nodeCount).toBe(1); }); }); describe("onEdgesChange", () => { it("should apply edge removal", () => { useGraphStore.getState().setEdges([makeEdge("e1", "a", "b")]); useGraphStore.getState().onEdgesChange([ { type: "remove", id: "e1" }, ]); expect(useGraphStore.getState().edges).toHaveLength(0); }); }); describe("onViewportChange", () => { it("should update viewport and zoomLevel", () => { useGraphStore.getState().onViewportChange({ x: 50, y: 50, zoom: 1.5 }); expect(useGraphStore.getState().viewport).toEqual({ x: 50, y: 50, zoom: 1.5 }); expect(useGraphStore.getState().zoomLevel).toBe(150); }); it("should round zoomLevel to nearest integer", () => { useGraphStore.getState().onViewportChange({ x: 0, y: 0, zoom: 0.333 }); expect(useGraphStore.getState().zoomLevel).toBe(33); }); it("should handle zoom at 100%", () => { useGraphStore.getState().onViewportChange({ x: 0, y: 0, zoom: 1.0 }); expect(useGraphStore.getState().zoomLevel).toBe(100); }); }); });