UNPKG

@emmahyde/thinking-patterns

Version:

MCP server combining systematic thinking, mental models, debugging approaches, and stochastic algorithms for comprehensive cognitive pattern support

664 lines (663 loc) 29.4 kB
import { VisualReasoningServer } from '../../src/servers/VisualReasoningServer.js'; describe('VisualReasoningServer', () => { let server; beforeEach(() => { server = new VisualReasoningServer(); }); describe('process', () => { it('should process valid visual reasoning data correctly', () => { const input = { operation: 'create', diagramId: 'graph-001', diagramType: 'graph', iteration: 1, nextOperationNeeded: true }; const result = server.process(input); expect(result.operation).toBe('create'); expect(result.diagramId).toBe('graph-001'); expect(result.diagramType).toBe('graph'); expect(result.iteration).toBe(1); expect(result.nextOperationNeeded).toBe(true); expect(result.status).toBe('success'); expect(result.elementCount).toBe(0); expect(result.hasObservation).toBe(false); expect(result.hasInsight).toBe(false); expect(result.hasHypothesis).toBe(false); expect(result.hasTransformationType).toBe(false); expect(result.timestamp).toBeDefined(); }); it('should process graph diagram with nodes and edges', () => { const input = { operation: 'create', diagramId: 'network-graph', diagramType: 'graph', iteration: 1, nextOperationNeeded: true, elements: [ { id: 'node-1', type: 'node', label: 'Start Node', properties: { color: 'blue', size: 'large' } }, { id: 'node-2', type: 'node', label: 'End Node', properties: { color: 'red', size: 'medium' } }, { id: 'edge-1', type: 'edge', source: 'node-1', target: 'node-2', properties: { weight: 0.8, directed: true } } ], observation: 'Network shows clear flow from start to end', insight: 'Simple directed graph with weighted connection' }; const result = server.process(input); expect(result.diagramType).toBe('graph'); expect(result.elementCount).toBe(3); expect(result.elements).toHaveLength(3); expect(result.hasObservation).toBe(true); expect(result.hasInsight).toBe(true); expect(result.observation).toBe('Network shows clear flow from start to end'); expect(result.insight).toBe('Simple directed graph with weighted connection'); expect(result.elements?.[0].type).toBe('node'); expect(result.elements?.[2].source).toBe('node-1'); expect(result.elements?.[2].target).toBe('node-2'); }); it('should process flowchart diagram with decision nodes', () => { const input = { operation: 'update', diagramId: 'process-flow', diagramType: 'flowchart', iteration: 3, nextOperationNeeded: false, elements: [ { id: 'start', type: 'node', label: 'Start Process', properties: { shape: 'oval', color: 'green' } }, { id: 'decision', type: 'node', label: 'Check Condition?', properties: { shape: 'diamond', color: 'yellow' } } ], observation: 'Flowchart represents a binary decision process', insight: 'Decision point creates two parallel execution paths', hypothesis: 'Adding error handling nodes would improve robustness' }; const result = server.process(input); expect(result.diagramType).toBe('flowchart'); expect(result.operation).toBe('update'); expect(result.elementCount).toBe(2); expect(result.hasObservation).toBe(true); expect(result.hasInsight).toBe(true); expect(result.hasHypothesis).toBe(true); expect(result.hypothesis).toBe('Adding error handling nodes would improve robustness'); }); it('should process state diagram with transitions', () => { const input = { operation: 'transform', diagramId: 'state-machine', diagramType: 'state-diagram', iteration: 2, nextOperationNeeded: true, transformationType: 'regroup', elements: [ { id: 'idle', type: 'node', label: 'Idle State', properties: { initial: true, color: 'gray' } }, { id: 'processing', type: 'node', label: 'Processing State', properties: { active: true, color: 'orange' } }, { id: 'completed', type: 'node', label: 'Completed State', properties: { final: true, color: 'green' } }, { id: 'transition-1', type: 'edge', source: 'idle', target: 'processing', label: 'start', properties: { trigger: 'user_input' } }, { id: 'transition-2', type: 'edge', source: 'processing', target: 'completed', label: 'finish', properties: { trigger: 'process_complete' } } ], observation: 'State machine shows linear progression', insight: 'Missing error states and rollback transitions' }; const result = server.process(input); expect(result.diagramType).toBe('state-diagram'); expect(result.operation).toBe('transform'); expect(result.hasTransformationType).toBe(true); expect(result.transformationType).toBe('regroup'); expect(result.elementCount).toBe(5); expect(result.insight).toBe('Missing error states and rollback transitions'); }); it('should process concept map with hierarchical relationships', () => { const input = { operation: 'create', diagramId: 'concept-hierarchy', diagramType: 'concept-map', iteration: 1, nextOperationNeeded: true, elements: [ { id: 'root-concept', type: 'node', label: 'Machine Learning', properties: { level: 0, category: 'root' } }, { id: 'supervised', type: 'node', label: 'Supervised Learning', properties: { level: 1, category: 'subconcept' } }, { id: 'unsupervised', type: 'node', label: 'Unsupervised Learning', properties: { level: 1, category: 'subconcept' } }, { id: 'container-learning', type: 'container', label: 'Learning Types', contains: ['supervised', 'unsupervised'], properties: { groupType: 'category' } } ], observation: 'Concept map organizes ML concepts hierarchically', insight: 'Clear separation between supervised and unsupervised approaches' }; const result = server.process(input); expect(result.diagramType).toBe('concept-map'); expect(result.elementCount).toBe(4); expect(result.elements?.[3].type).toBe('container'); expect(result.elements?.[3].contains).toEqual(['supervised', 'unsupervised']); }); it('should process tree diagram with branching structure', () => { const input = { operation: 'observe', diagramId: 'decision-tree', diagramType: 'tree-diagram', iteration: 1, nextOperationNeeded: false, elements: [ { id: 'root', type: 'node', label: 'Root Decision', properties: { depth: 0, children: 2 } }, { id: 'left-branch', type: 'node', label: 'Left Branch', properties: { depth: 1, parent: 'root' } }, { id: 'right-branch', type: 'node', label: 'Right Branch', properties: { depth: 1, parent: 'root' } }, { id: 'annotation-1', type: 'annotation', label: 'Decision criterion: value > threshold', properties: { target: 'root', position: 'top' } } ], observation: 'Binary tree structure with clear branching logic', hypothesis: 'Tree depth could be optimized for better performance' }; const result = server.process(input); expect(result.diagramType).toBe('tree-diagram'); expect(result.operation).toBe('observe'); expect(result.elementCount).toBe(4); expect(result.elements?.[3].type).toBe('annotation'); expect(result.hasHypothesis).toBe(true); }); it('should process custom diagram type', () => { const input = { operation: 'create', diagramId: 'custom-visualization', diagramType: 'custom', iteration: 1, nextOperationNeeded: true, elements: [ { id: 'custom-element', type: 'node', label: 'Custom Element', properties: { customProperty: 'value', visualization: 'special' } } ], observation: 'Custom diagram allows for specialized visualizations' }; const result = server.process(input); expect(result.diagramType).toBe('custom'); expect(result.elementCount).toBe(1); expect(result.hasObservation).toBe(true); }); it('should handle all operation types', () => { const operations = ['create', 'update', 'delete', 'transform', 'observe']; operations.forEach((operation, index) => { const input = { operation: operation, diagramId: `diagram-${index}`, diagramType: 'graph', iteration: 1, nextOperationNeeded: true }; const result = server.process(input); expect(result.operation).toBe(operation); expect(result.status).toBe('success'); }); }); it('should handle all diagram types', () => { const diagramTypes = ['graph', 'flowchart', 'state-diagram', 'concept-map', 'tree-diagram', 'custom']; diagramTypes.forEach((type, index) => { const input = { operation: 'create', diagramId: `${type}-diagram`, diagramType: type, iteration: 1, nextOperationNeeded: false }; const result = server.process(input); expect(result.diagramType).toBe(type); expect(result.status).toBe('success'); }); }); it('should handle all transformation types', () => { const transformations = ['rotate', 'move', 'resize', 'recolor', 'regroup']; transformations.forEach((transformation, index) => { const input = { operation: 'transform', diagramId: `transform-${index}`, diagramType: 'graph', iteration: 1, nextOperationNeeded: true, transformationType: transformation }; const result = server.process(input); expect(result.transformationType).toBe(transformation); expect(result.hasTransformationType).toBe(true); }); }); it('should handle all element types', () => { const elementTypes = ['node', 'edge', 'container', 'annotation']; const elements = elementTypes.map((type, index) => ({ id: `element-${index}`, type: type, label: `${type} element`, properties: { elementType: type } })); const input = { operation: 'create', diagramId: 'multi-element-diagram', diagramType: 'graph', iteration: 1, nextOperationNeeded: false, elements: elements }; const result = server.process(input); expect(result.elementCount).toBe(4); elementTypes.forEach((type, index) => { expect(result.elements?.[index].type).toBe(type); }); }); it('should handle complex graph with multiple relationships', () => { const input = { operation: 'update', diagramId: 'complex-network', diagramType: 'graph', iteration: 5, nextOperationNeeded: true, transformationType: 'regroup', elements: [ { id: 'cluster-1', type: 'container', label: 'Cluster A', contains: ['node-1', 'node-2', 'node-3'], properties: { clusterType: 'functional', color: 'lightblue' } }, { id: 'cluster-2', type: 'container', label: 'Cluster B', contains: ['node-4', 'node-5'], properties: { clusterType: 'organizational', color: 'lightgreen' } }, { id: 'node-1', type: 'node', label: 'Service A', properties: { importance: 'high', connections: 5 } }, { id: 'node-2', type: 'node', label: 'Service B', properties: { importance: 'medium', connections: 3 } }, { id: 'cross-cluster-edge', type: 'edge', source: 'node-1', target: 'node-4', label: 'Cross-cluster dependency', properties: { weight: 0.9, critical: true } } ], observation: 'Network shows clear clustering with cross-cluster dependencies', insight: 'High-importance nodes create bottlenecks in the system', hypothesis: 'Reducing cross-cluster dependencies would improve modularity' }; const result = server.process(input); expect(result.elementCount).toBe(5); expect(result.hasTransformationType).toBe(true); expect(result.hasObservation).toBe(true); expect(result.hasInsight).toBe(true); expect(result.hasHypothesis).toBe(true); expect(result.elements?.[0].contains).toHaveLength(3); expect(result.elements?.[1].contains).toHaveLength(2); }); it('should handle delete operations', () => { const input = { operation: 'delete', diagramId: 'diagram-to-modify', diagramType: 'flowchart', iteration: 2, nextOperationNeeded: true, elements: [ { id: 'remaining-node', type: 'node', label: 'Node to keep', properties: { status: 'active' } } ], observation: 'Removed redundant nodes from flowchart', insight: 'Simplified structure improves clarity' }; const result = server.process(input); expect(result.operation).toBe('delete'); expect(result.elementCount).toBe(1); expect(result.observation).toBe('Removed redundant nodes from flowchart'); }); it('should handle transformation with move operation', () => { const input = { operation: 'transform', diagramId: 'layout-optimization', diagramType: 'graph', iteration: 3, nextOperationNeeded: false, transformationType: 'move', elements: [ { id: 'moved-node', type: 'node', label: 'Repositioned Node', properties: { x: 100, y: 200, previousX: 50, previousY: 150 } } ], observation: 'Node repositioning improves visual balance', insight: 'Spatial arrangement affects diagram readability' }; const result = server.process(input); expect(result.transformationType).toBe('move'); expect(result.hasTransformationType).toBe(true); expect(result.insight).toBe('Spatial arrangement affects diagram readability'); }); it('should handle resize transformation', () => { const input = { operation: 'transform', diagramId: 'size-adjustment', diagramType: 'concept-map', iteration: 1, nextOperationNeeded: true, transformationType: 'resize', elements: [ { id: 'resized-concept', type: 'node', label: 'Important Concept', properties: { size: 'large', previousSize: 'medium', emphasis: true } } ], observation: 'Increased size of key concept for emphasis', hypothesis: 'Size variations help establish visual hierarchy' }; const result = server.process(input); expect(result.transformationType).toBe('resize'); expect(result.hasHypothesis).toBe(true); }); it('should handle recolor transformation', () => { const input = { operation: 'transform', diagramId: 'color-coding', diagramType: 'flowchart', iteration: 2, nextOperationNeeded: false, transformationType: 'recolor', elements: [ { id: 'error-node', type: 'node', label: 'Error Handler', properties: { color: 'red', previousColor: 'blue', category: 'error' } }, { id: 'success-node', type: 'node', label: 'Success Path', properties: { color: 'green', previousColor: 'blue', category: 'success' } } ], observation: 'Color coding distinguishes different node types', insight: 'Visual categorization improves diagram comprehension' }; const result = server.process(input); expect(result.transformationType).toBe('recolor'); expect(result.elementCount).toBe(2); expect(result.insight).toBe('Visual categorization improves diagram comprehension'); }); it('should handle rotate transformation', () => { const input = { operation: 'transform', diagramId: 'orientation-change', diagramType: 'tree-diagram', iteration: 1, nextOperationNeeded: true, transformationType: 'rotate', observation: 'Rotated tree to horizontal layout', insight: 'Horizontal layout better utilizes screen space' }; const result = server.process(input); expect(result.transformationType).toBe('rotate'); expect(result.observation).toBe('Rotated tree to horizontal layout'); }); it('should handle high iteration numbers', () => { const input = { operation: 'update', diagramId: 'iterative-design', diagramType: 'graph', iteration: 50, nextOperationNeeded: false, observation: 'Diagram has undergone extensive iterative refinement' }; const result = server.process(input); expect(result.iteration).toBe(50); expect(result.nextOperationNeeded).toBe(false); }); it('should handle elements with complex properties', () => { const input = { operation: 'create', diagramId: 'complex-properties', diagramType: 'graph', iteration: 1, nextOperationNeeded: true, elements: [ { id: 'complex-node', type: 'node', label: 'Node with Complex Properties', properties: { metadata: { created: '2024-01-01', author: 'system', version: '1.0' }, styling: { color: '#FF5733', borderWidth: 2, shape: 'ellipse' }, behavior: { clickable: true, draggable: false, resizable: true }, data: { value: 42, category: 'important', tags: ['primary', 'featured'] } } } ] }; const result = server.process(input); expect(result.elementCount).toBe(1); expect(result.elements?.[0].properties).toBeDefined(); expect(typeof result.elements?.[0].properties).toBe('object'); }); it('should handle minimal diagram with no optional fields', () => { const input = { operation: 'create', diagramId: 'minimal-diagram', diagramType: 'graph', iteration: 1, nextOperationNeeded: false }; const result = server.process(input); expect(result.elementCount).toBe(0); expect(result.hasObservation).toBe(false); expect(result.hasInsight).toBe(false); expect(result.hasHypothesis).toBe(false); expect(result.hasTransformationType).toBe(false); expect(result.elements).toBeUndefined(); }); it('should handle observation-only input', () => { const input = { operation: 'observe', diagramId: 'observation-focus', diagramType: 'flowchart', iteration: 1, nextOperationNeeded: true, observation: 'Process flow shows potential optimization opportunities' }; const result = server.process(input); expect(result.hasObservation).toBe(true); expect(result.hasInsight).toBe(false); expect(result.hasHypothesis).toBe(false); expect(result.observation).toBe('Process flow shows potential optimization opportunities'); }); it('should handle insight-only input', () => { const input = { operation: 'observe', diagramId: 'insight-focus', diagramType: 'concept-map', iteration: 2, nextOperationNeeded: false, insight: 'Concept relationships reveal hidden dependencies' }; const result = server.process(input); expect(result.hasObservation).toBe(false); expect(result.hasInsight).toBe(true); expect(result.hasHypothesis).toBe(false); expect(result.insight).toBe('Concept relationships reveal hidden dependencies'); }); it('should handle hypothesis-only input', () => { const input = { operation: 'observe', diagramId: 'hypothesis-focus', diagramType: 'state-diagram', iteration: 1, nextOperationNeeded: true, hypothesis: 'Adding intermediate states would improve user experience' }; const result = server.process(input); expect(result.hasObservation).toBe(false); expect(result.hasInsight).toBe(false); expect(result.hasHypothesis).toBe(true); expect(result.hypothesis).toBe('Adding intermediate states would improve user experience'); }); it('should handle comprehensive visual analysis', () => { const input = { operation: 'transform', diagramId: 'comprehensive-analysis', diagramType: 'graph', iteration: 10, nextOperationNeeded: false, transformationType: 'regroup', elements: [ { id: 'central-hub', type: 'node', label: 'Central Hub', properties: { centrality: 0.95, degree: 15, importance: 'critical' } }, { id: 'peripheral-cluster', type: 'container', label: 'Peripheral Nodes', contains: ['node-a', 'node-b', 'node-c'], properties: { clusterCoefficient: 0.8, density: 'high' } } ], observation: 'Network exhibits hub-and-spoke topology with peripheral clustering', insight: 'Central hub creates potential single point of failure', hypothesis: 'Introducing redundant pathways would improve network resilience' }; const result = server.process(input); expect(result.hasObservation).toBe(true); expect(result.hasInsight).toBe(true); expect(result.hasHypothesis).toBe(true); expect(result.hasTransformationType).toBe(true); expect(result.elementCount).toBe(2); expect(result.iteration).toBe(10); expect(result.nextOperationNeeded).toBe(false); }); }); });