feat: solution for 'Повторный экзамен: Граф с рефлексией и доработкой'
This commit is contained in:
+67
-50
@@ -1,64 +1,81 @@
|
||||
const Graph = require('../src/graph');
|
||||
import { Graph, Node, ReflectionNode, RewritingNode } from '../src/index.js';
|
||||
|
||||
describe('Graph', () => {
|
||||
test('should add reflection node and evaluate correctly', () => {
|
||||
const g = new Graph();
|
||||
g.addNode('A', 'reflection');
|
||||
const outputs = g.evaluate('A', 42);
|
||||
expect(outputs['A']).toBe(42);
|
||||
describe('Graph with reflection and rewriting nodes', () => {
|
||||
let graph;
|
||||
|
||||
beforeEach(() => {
|
||||
graph = new Graph();
|
||||
});
|
||||
|
||||
test('should add rewrite node and evaluate correctly', () => {
|
||||
const g = new Graph();
|
||||
g.addNode('B', 'rewrite');
|
||||
const outputs = g.evaluate('B', 'hello');
|
||||
expect(outputs['B']).toBe('HELLO');
|
||||
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('should propagate through connected nodes', () => {
|
||||
const g = new Graph();
|
||||
g.addNode('A', 'reflection');
|
||||
g.addNode('B', 'rewrite');
|
||||
g.addEdge('A', 'B');
|
||||
const outputs = g.evaluate('A', 'test');
|
||||
expect(outputs['A']).toBe('test');
|
||||
expect(outputs['B']).toBe('TEST');
|
||||
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('should throw error on unknown node type', () => {
|
||||
const g = new Graph();
|
||||
expect(() => g.addNode('C', 'unknown')).toThrow();
|
||||
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('should throw error on duplicate node name', () => {
|
||||
const g = new Graph();
|
||||
g.addNode('D', 'reflection');
|
||||
expect(() => g.addNode('D', 'rewrite')).toThrow();
|
||||
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('should throw error on edge to non-existent node', () => {
|
||||
const g = new Graph();
|
||||
g.addNode('E', 'reflection');
|
||||
expect(() => g.addEdge('E', 'F')).toThrow();
|
||||
});
|
||||
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');
|
||||
|
||||
test('should support custom transform function', () => {
|
||||
const g = new Graph();
|
||||
g.addNode('G', 'rewrite', { transform: (x) => x * 2 });
|
||||
const outputs = g.evaluate('G', 5);
|
||||
expect(outputs['G']).toBe(10);
|
||||
});
|
||||
|
||||
test('should handle multiple outputs', () => {
|
||||
const g = new Graph();
|
||||
g.addNode('A', 'reflection');
|
||||
g.addNode('B', 'rewrite');
|
||||
g.addNode('C', 'rewrite');
|
||||
g.addEdge('A', 'B');
|
||||
g.addEdge('A', 'C');
|
||||
const outputs = g.evaluate('A', 'multi');
|
||||
expect(outputs['A']).toBe('multi');
|
||||
expect(outputs['B']).toBe('MULTI');
|
||||
expect(outputs['C']).toBe('MULTI');
|
||||
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();
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user