const { Graph } = require('../src'); describe('Graph', () => { let graph; beforeEach(() => { graph = new Graph(); }); test('adds nodes correctly', () => { graph.addNode('A', { value: 1 }); expect(graph.getNode('A')).toEqual({ value: 1 }); expect(() => graph.addNode('A')).toThrow(/already exists/); }); test('adds edges correctly, including self-referential', () => { graph.addNode('A'); graph.addNode('B'); const e1 = graph.addEdge('A', 'B', { weight: 5 }); const e2 = graph.addEdge('A', 'A', { weight: 3 }); // self-edge expect(graph.getEdge(e1)).toEqual({ from: 'A', to: 'B', data: { weight: 5 } }); expect(graph.getEdge(e2)).toEqual({ from: 'A', to: 'A', data: { weight: 3 } }); expect(() => graph.addEdge('X', 'A')).toThrow(/does not exist/); }); test('reflects an edge', () => { graph.addNode('X'); graph.addNode('Y'); const e = graph.addEdge('X', 'Y', { relation: 'friend' }); const rev = graph.reflect(e); expect(graph.getEdge(rev)).toEqual({ from: 'Y', to: 'X', data: { relation: 'friend' } }); }); test('refines a node', () => { graph.addNode('N', { type: 'original' }); graph.addNode('M'); graph.addEdge('N', 'M', { link: true }); const refined = graph.refineNode('N', { type: 'refined' }); expect(refined).toBe('N_refined'); expect(graph.getNode(refined)).toEqual({ type: 'refined' }); // Original node still exists expect(graph.getNode('N')).toEqual({ type: 'original' }); // Outgoing edge cloned const outgoing = graph.getAdjacency(refined); expect(outgoing.size).toBe(1); const clonedEdgeId = Array.from(outgoing)[0]; const clonedEdge = graph.getEdge(clonedEdgeId); expect(clonedEdge).toEqual({ from: refined, to: 'M', data: { link: true } }); }); test('refines an edge', () => { graph.addNode('P'); graph.addNode('Q'); const e = graph.addEdge('P', 'Q', { cost: 10 }); const refined = graph.refineEdge(e, { cost: 20 }); expect(refined).toBe(`${e}_refined`); expect(graph.getEdge(refined)).toEqual({ from: 'P', to: 'Q', data: { cost: 20 } }); // Original edge remains unchanged expect(graph.getEdge(e)).toEqual({ from: 'P', to: 'Q', data: { cost: 10 } }); }); test('handles complex operations', () => { graph.addNode('A'); graph.addNode('B'); graph.addNode('C'); const e1 = graph.addEdge('A', 'B', { weight: 1 }); const e2 = graph.addEdge('B', 'C', { weight: 2 }); const e3 = graph.addEdge('C', 'A', { weight: 3 }); // Reflect all edges const rev1 = graph.reflect(e1); const rev2 = graph.reflect(e2); const rev3 = graph.reflect(e3); // Refine node B const refinedB = graph.refineNode('B', { status: 'active' }); // Verify adjacency of refined node const adj = graph.getAdjacency(refinedB); expect(adj.size).toBe(2); // edges to C and A (original outgoing edges) }); });