Spaces:
Sleeping
Sleeping
| import { describe, it, expect } from "vitest"; | |
| import { wouldCreateCycle } from "./would-create-cycle"; | |
| import { Connection, Edge } from "@xyflow/react"; | |
| describe("wouldCreateCycle", () => { | |
| // Helper function to create a connection | |
| const createConnection = (source: string, target: string): Connection => ({ | |
| source, | |
| target, | |
| sourceHandle: null, | |
| targetHandle: null, | |
| }); | |
| // Helper function to create an edge | |
| const createEdge = (id: string, source: string, target: string): Edge => ({ | |
| id, | |
| source, | |
| target, | |
| sourceHandle: null, | |
| targetHandle: null, | |
| }); | |
| it("should return false for empty graph", () => { | |
| const connection = createConnection("A", "B"); | |
| const existingEdges: Edge[] = []; | |
| const result = wouldCreateCycle(connection, existingEdges); | |
| expect(result).toBe(false); | |
| }); | |
| it("should return false for simple linear connection", () => { | |
| const connection = createConnection("B", "C"); | |
| const existingEdges = [createEdge("1", "A", "B")]; | |
| const result = wouldCreateCycle(connection, existingEdges); | |
| expect(result).toBe(false); | |
| }); | |
| it("should return true for direct cycle (A -> B -> A)", () => { | |
| const connection = createConnection("B", "A"); | |
| const existingEdges = [createEdge("1", "A", "B")]; | |
| const result = wouldCreateCycle(connection, existingEdges); | |
| expect(result).toBe(true); | |
| }); | |
| it("should return true for indirect cycle (A -> B -> C -> A)", () => { | |
| const connection = createConnection("C", "A"); | |
| const existingEdges = [ | |
| createEdge("1", "A", "B"), | |
| createEdge("2", "B", "C"), | |
| ]; | |
| const result = wouldCreateCycle(connection, existingEdges); | |
| expect(result).toBe(true); | |
| }); | |
| it("should return true for complex cycle", () => { | |
| const connection = createConnection("D", "B"); | |
| const existingEdges = [ | |
| createEdge("1", "A", "B"), | |
| createEdge("2", "B", "C"), | |
| createEdge("3", "C", "D"), | |
| createEdge("4", "A", "E"), | |
| createEdge("5", "E", "F"), | |
| ]; | |
| const result = wouldCreateCycle(connection, existingEdges); | |
| expect(result).toBe(true); | |
| }); | |
| it("should return false for branching without cycles", () => { | |
| const connection = createConnection("D", "E"); | |
| const existingEdges = [ | |
| createEdge("1", "A", "B"), | |
| createEdge("2", "A", "C"), | |
| createEdge("3", "B", "D"), | |
| createEdge("4", "C", "D"), | |
| ]; | |
| const result = wouldCreateCycle(connection, existingEdges); | |
| expect(result).toBe(false); | |
| }); | |
| it("should return false for disconnected components", () => { | |
| const connection = createConnection("D", "E"); | |
| const existingEdges = [ | |
| createEdge("1", "A", "B"), | |
| createEdge("2", "B", "C"), | |
| createEdge("3", "X", "Y"), | |
| createEdge("4", "Y", "Z"), | |
| ]; | |
| const result = wouldCreateCycle(connection, existingEdges); | |
| expect(result).toBe(false); | |
| }); | |
| it("should handle self-loop correctly", () => { | |
| const connection = createConnection("A", "A"); | |
| const existingEdges: Edge[] = []; | |
| const result = wouldCreateCycle(connection, existingEdges); | |
| expect(result).toBe(true); | |
| }); | |
| it("should return false when connection source or target is missing", () => { | |
| const connectionWithoutSource = { | |
| source: null, | |
| target: "B", | |
| sourceHandle: null, | |
| targetHandle: null, | |
| } as unknown as Connection; | |
| const connectionWithoutTarget = { | |
| source: "A", | |
| target: null, | |
| sourceHandle: null, | |
| targetHandle: null, | |
| } as unknown as Connection; | |
| const existingEdges = [createEdge("1", "A", "B")]; | |
| expect(wouldCreateCycle(connectionWithoutSource, existingEdges)).toBe( | |
| false, | |
| ); | |
| expect(wouldCreateCycle(connectionWithoutTarget, existingEdges)).toBe( | |
| false, | |
| ); | |
| }); | |
| it("should detect cycle in diamond shape graph", () => { | |
| const connection = createConnection("D", "A"); | |
| const existingEdges = [ | |
| createEdge("1", "A", "B"), | |
| createEdge("2", "A", "C"), | |
| createEdge("3", "B", "D"), | |
| createEdge("4", "C", "D"), | |
| ]; | |
| const result = wouldCreateCycle(connection, existingEdges); | |
| expect(result).toBe(true); | |
| }); | |
| it("should handle large graph with multiple paths without cycle", () => { | |
| const connection = createConnection("F", "G"); | |
| const existingEdges = [ | |
| createEdge("1", "A", "B"), | |
| createEdge("2", "A", "C"), | |
| createEdge("3", "B", "D"), | |
| createEdge("4", "C", "D"), | |
| createEdge("5", "D", "E"), | |
| createEdge("6", "E", "F"), | |
| createEdge("7", "B", "H"), | |
| createEdge("8", "H", "I"), | |
| ]; | |
| const result = wouldCreateCycle(connection, existingEdges); | |
| expect(result).toBe(false); | |
| }); | |
| it("should handle connection between existing isolated nodes", () => { | |
| const connection = createConnection("X", "Y"); | |
| const existingEdges = [ | |
| createEdge("1", "A", "B"), | |
| createEdge("2", "B", "C"), | |
| ]; | |
| const result = wouldCreateCycle(connection, existingEdges); | |
| expect(result).toBe(false); | |
| }); | |
| it("should detect long cycle path", () => { | |
| const connection = createConnection("E", "A"); | |
| const existingEdges = [ | |
| createEdge("1", "A", "B"), | |
| createEdge("2", "B", "C"), | |
| createEdge("3", "C", "D"), | |
| createEdge("4", "D", "E"), | |
| ]; | |
| const result = wouldCreateCycle(connection, existingEdges); | |
| expect(result).toBe(true); | |
| }); | |
| it("should return false for single node graph", () => { | |
| const connection = createConnection("A", "B"); | |
| const existingEdges: Edge[] = []; | |
| const result = wouldCreateCycle(connection, existingEdges); | |
| expect(result).toBe(false); | |
| }); | |
| it("should handle multiple incoming edges to same node", () => { | |
| const connection = createConnection("D", "A"); | |
| const existingEdges = [ | |
| createEdge("1", "A", "D"), | |
| createEdge("2", "B", "D"), | |
| createEdge("3", "C", "D"), | |
| ]; | |
| const result = wouldCreateCycle(connection, existingEdges); | |
| expect(result).toBe(true); | |
| }); | |
| }); | |