import { Graph, Node, ReflectionNode, RewritingNode } from '../src/index.js'; describe('Graph with reflection and rewriting nodes', () => { let graph; beforeEach(() => { graph = new Graph(); }); test('can add generic, reflection, and rewriting nodes', () => { const n1 = new Node('n1'); const r1 = new ReflectionNode('r1'); const w1 = new RewritingNode('w1'); graph.addNode(n1); graph.addNode(r1); graph.addNode(w1); expect(graph.getNode('n1')).toBe(n1); expect(graph.getNode('r1')).toBe(r1); expect(graph.getNode('w1')).toBe(w1); }); test('adding duplicate node id throws error', () => { const n1 = new Node('dup'); graph.addNode(n1); expect(() => graph.addNode(new Node('dup'))).toThrow(/already exists/); }); test('can add edges between any node types', () => { const n1 = new Node('n1'); const r1 = new ReflectionNode('r1'); const w1 = new RewritingNode('w1'); graph.addNode(n1); graph.addNode(r1); graph.addNode(w1); graph.addEdge('n1', 'r1'); graph.addEdge('r1', 'w1'); graph.addEdge('w1', 'n1'); const visited = []; graph.traverse('n1', (node) => visited.push(node.id)); expect(visited.sort()).toEqual(['n1', 'r1', 'w1']); }); test('removeNode removes node and its edges', () => { const n1 = new Node('n1'); const r1 = new ReflectionNode('r1'); graph.addNode(n1); graph.addNode(r1); graph.addEdge('n1', 'r1'); graph.addEdge('r1', 'n1'); graph.removeNode('r1'); expect(graph.getNode('r1')).toBeUndefined(); expect(() => graph.traverse('n1', () => {})).not.toThrow(); // n1 should have no outgoing edges now const visited = []; graph.traverse('n1', (node) => visited.push(node.id)); expect(visited).toEqual(['n1']); }); test('traverse handles disconnected graph', () => { const n1 = new Node('n1'); const r1 = new ReflectionNode('r1'); const w1 = new RewritingNode('w1'); graph.addNode(n1); graph.addNode(r1); graph.addNode(w1); graph.addEdge('n1', 'r1'); const visited = []; graph.traverse('n1', (node) => visited.push(node.id)); expect(visited).toEqual(['n1', 'r1']); // w1 is disconnected expect(() => graph.traverse('w1', (node) => visited.push(node.id))).not.toThrow(); }); });