UNPKG

task-master-neo-sdlc

Version:

Enhanced task management system with Neo SDLC agents and MCP tools for comprehensive, AI-driven software development lifecycle management.

249 lines (204 loc) 6.4 kB
import { KnowledgeGraph } from '../knowledge-graph.js'; describe('KnowledgeGraph', () => { let graph; beforeEach(() => { graph = new KnowledgeGraph(); }); describe('addNode', () => { it('should add a node with timestamp', () => { const node = { id: 'test-1', type: 'task', data: { title: 'Test Task' } }; graph.addNode(node); const result = graph.nodes.get('test-1'); expect(result).toBeDefined(); expect(result.type).toBe('task'); expect(result.created).toBeDefined(); expect(result.updated).toBeDefined(); }); it('should throw error for duplicate node id', () => { const node = { id: 'test-1', type: 'task' }; graph.addNode(node); expect(() => graph.addNode(node)).toThrow('Node already exists'); }); }); describe('addEdge', () => { beforeEach(() => { graph.addNode({ id: 'node1', type: 'task' }); graph.addNode({ id: 'node2', type: 'agent' }); }); it('should add edge between nodes', () => { const edge = { from: 'node1', to: 'node2', type: 'assigned' }; graph.addEdge(edge); const result = graph.edges.get('node1:assigned:node2'); expect(result).toBeDefined(); expect(result.type).toBe('assigned'); expect(result.created).toBeDefined(); }); it('should throw error for invalid node references', () => { const edge = { from: 'node1', to: 'invalid', type: 'assigned' }; expect(() => graph.addEdge(edge)).toThrow('Invalid node reference'); }); }); describe('updateContext', () => { it('should create or update node with context', async () => { const context = { id: 'workflow-1', type: 'workflow', status: 'active', metrics: { progress: 0.5 } }; await graph.updateContext(context); const node = graph.nodes.get('workflow-1'); expect(node).toBeDefined(); expect(node.data.status).toBe('active'); expect(node.data.metrics.progress).toBe(0.5); expect(node.updated).toBeDefined(); }); it('should update cache on context change', async () => { const context = { id: 'agent-1', type: 'agent', status: 'idle' }; await graph.updateContext(context); expect(graph.contextCache.get('agent-1')).toBeDefined(); await graph.updateContext({ ...context, status: 'active' }); const cached = graph.contextCache.get('agent-1'); expect(cached.status).toBe('active'); }); }); describe('getContext', () => { beforeEach(async () => { await graph.updateContext({ id: 'task-1', type: 'task', status: 'pending' }); await graph.updateContext({ id: 'agent-1', type: 'agent', capabilities: ['testing'] }); graph.addEdge({ from: 'task-1', to: 'agent-1', type: 'assigned' }); }); it('should return node context with connected nodes', async () => { const context = await graph.getContext('task-1'); expect(context.id).toBe('task-1'); expect(context.type).toBe('task'); expect(context.connected).toBeDefined(); expect(context.connected.assigned).toContainEqual( expect.objectContaining({ id: 'agent-1' }) ); }); it('should use cache when available', async () => { const firstCall = await graph.getContext('task-1'); const secondCall = await graph.getContext('task-1'); expect(secondCall).toEqual(firstCall); expect(graph.contextCache.has('task-1')).toBe(true); }); }); describe('findNodes', () => { beforeEach(async () => { await graph.updateContext({ id: 'task-1', type: 'task', priority: 'high' }); await graph.updateContext({ id: 'task-2', type: 'task', priority: 'medium' }); }); it('should find nodes by type and criteria', () => { const results = graph.findNodes('task', node => node.data.priority === 'high' ); expect(results).toHaveLength(1); expect(results[0].id).toBe('task-1'); }); it('should return empty array when no matches', () => { const results = graph.findNodes('task', node => node.data.priority === 'low' ); expect(results).toHaveLength(0); }); }); describe('validateContext', () => { it('should validate required fields by type', () => { const context = { id: 'workflow-1', type: 'workflow' }; const result = graph.validateContext(context); expect(result.valid).toBe(false); expect(result.errors).toContain('Missing required field: status'); }); it('should validate field types', () => { const context = { id: 'metrics-1', type: 'metrics', values: 'invalid' // Should be array }; const result = graph.validateContext(context); expect(result.valid).toBe(false); expect(result.errors).toContain('Invalid field type: values'); }); }); describe('analyzeContext', () => { beforeEach(async () => { await graph.updateContext({ id: 'agent-1', type: 'agent', metrics: { tasksCompleted: 10, successRate: 0.9 } }); for (let i = 1; i <= 3; i++) { await graph.updateContext({ id: `task-${i}`, type: 'task', status: 'completed' }); graph.addEdge({ from: `task-${i}`, to: 'agent-1', type: 'completed_by' }); } }); it('should analyze node relationships and metrics', async () => { const analysis = await graph.analyzeContext('agent-1'); expect(analysis.metrics).toBeDefined(); expect(analysis.relationships).toBeDefined(); expect(analysis.recommendations).toBeDefined(); expect(analysis.metrics.taskCount).toBe(3); expect(analysis.relationships.completed_by).toHaveLength(3); }); it('should provide type-specific insights', async () => { const analysis = await graph.analyzeContext('agent-1'); expect(analysis.insights).toContain( expect.stringContaining('success rate') ); }); }); });