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.

169 lines (145 loc) 6.35 kB
import { TechnicalDebtManagerAgent } from '../technical-debt-manager'; import { KnowledgeGraph } from '../../knowledge-graph'; // Adjust path import { AgentWorkflowSystem } from '../../agent-workflow'; // Adjust path // Mocks const mockKnowledgeGraph = { addNode: jest.fn(), findNodes: jest.fn(), updateContext: jest.fn() }; const mockWorkflow = { createTask: jest.fn() // Mock if used }; describe('TechnicalDebtManagerAgent', () => { let agent; beforeEach(() => { jest.clearAllMocks(); agent = new TechnicalDebtManagerAgent(mockKnowledgeGraph, mockWorkflow); jest.spyOn(console, 'log').mockImplementation(() => {}); }); afterEach(() => { console.log.mockRestore(); }); it('should identify technical debt (placeholder)', async () => { const scope = { files: ['some/file.js'] }; mockKnowledgeGraph.addNode.mockResolvedValue(undefined); // Mock KG findNodes if querying for debt indicators const debtItems = await agent.identifyTechnicalDebt(scope); expect(debtItems).toBeDefined(); expect(debtItems.length).toBe(1); // Based on placeholder logic const item = debtItems[0]; expect(item.id).toMatch(/^techDebt_/); expect(item.status).toBe('identified'); expect(mockKnowledgeGraph.addNode).toHaveBeenCalledWith({ id: `technicalDebt:${item.id}`, type: 'technical_debt_item', data: item }); }); it('should prioritize technical debt by severity', async () => { const mockDebtNodes = [ { id: 'td:1', data: { id: '1', severity: 'low' } }, { id: 'td:2', data: { id: '2', severity: 'high' } }, { id: 'td:3', data: { id: '3', severity: 'medium' } } ]; mockKnowledgeGraph.findNodes.mockResolvedValue(mockDebtNodes); const prioritized = await agent.prioritizeDebt(); expect(prioritized).toBeDefined(); expect(prioritized.length).toBe(3); expect(prioritized[0].severity).toBe('high'); expect(prioritized[1].severity).toBe('medium'); expect(prioritized[2].severity).toBe('low'); expect(mockKnowledgeGraph.findNodes).toHaveBeenCalledWith({ type: 'technical_debt_item' }); }); it('should prioritize a subset of technical debt items', async () => { const itemIdsToPrioritize = ['itemA', 'itemC']; const mockDebtNodes = [ { id: 'technicalDebt:itemA', data: { id: 'itemA', severity: 'medium' } }, { id: 'technicalDebt:itemB', data: { id: 'itemB', severity: 'high' } }, // Should be filtered out { id: 'technicalDebt:itemC', data: { id: 'itemC', severity: 'low' } }, ]; mockKnowledgeGraph.findNodes.mockResolvedValue(mockDebtNodes); const prioritized = await agent.prioritizeDebt(itemIdsToPrioritize); expect(prioritized).toBeDefined(); expect(prioritized.length).toBe(2); expect(prioritized[0].id).toBe('itemA'); // Medium expect(prioritized[1].id).toBe('itemC'); // Low expect(mockKnowledgeGraph.findNodes).toHaveBeenCalledWith({ type: 'technical_debt_item' }); }); it('should plan debt resolution and create a task', async () => { const debtItemId = 'debt_xyz'; const mockDebtNode = { id: `technicalDebt:${debtItemId}`, type: 'technical_debt_item', data: { id: debtItemId, description: 'Complex function', location: { file: 'utils.js' }, status: 'identified' } }; mockKnowledgeGraph.findNodes.mockResolvedValue([mockDebtNode]); mockKnowledgeGraph.updateContext.mockResolvedValue(undefined); mockKnowledgeGraph.addNode.mockResolvedValue(undefined); const task = await agent.planDebtResolution(debtItemId); expect(task).toBeDefined(); expect(task.id).toMatch(/^refactorTask_/); expect(task.title).toContain(debtItemId); expect(task.relatedDebt).toBe(debtItemId); expect(task.status).toBe('pending'); expect(mockKnowledgeGraph.findNodes).toHaveBeenCalledWith({ id: `technicalDebt:${debtItemId}` }); // Check debt item status update expect(mockKnowledgeGraph.updateContext).toHaveBeenCalledWith({ id: mockDebtNode.id, data: expect.objectContaining({ status: 'planned' }) }); // Check task creation in KG expect(mockKnowledgeGraph.addNode).toHaveBeenCalledWith({ id: `task:${task.id}`, type: 'refactoring_task', data: task, edges: [{ target: mockDebtNode.id, relationship: 'addresses' }] }); // Optionally check workflow task creation // expect(mockWorkflow.createTask).toHaveBeenCalled(); }); it('should throw error if debt item not found during planning', async () => { mockKnowledgeGraph.findNodes.mockResolvedValue([]); // Simulate not found await expect(agent.planDebtResolution('nonexistent_debt')).rejects.toThrow( 'Technical debt item nonexistent_debt not found.' ); }); it('should update debt status', async () => { const debtItemId = 'debt_abc'; const newStatus = 'resolved'; const mockDebtNode = { id: `technicalDebt:${debtItemId}`, type: 'technical_debt_item', data: { id: debtItemId, status: 'in_progress' } }; mockKnowledgeGraph.findNodes.mockResolvedValue([mockDebtNode]); mockKnowledgeGraph.updateContext.mockResolvedValue(undefined); await agent.updateDebtStatus(debtItemId, newStatus); expect(mockKnowledgeGraph.findNodes).toHaveBeenCalledWith({ id: `technicalDebt:${debtItemId}` }); expect(mockKnowledgeGraph.updateContext).toHaveBeenCalledWith({ id: mockDebtNode.id, data: expect.objectContaining({ status: newStatus }) }); }); it('should throw error for invalid status update', async () => { const debtItemId = 'debt_123'; const invalidStatus = 'invalid_status'; const mockDebtNode = { id: `technicalDebt:${debtItemId}`, data: {} }; mockKnowledgeGraph.findNodes.mockResolvedValue([mockDebtNode]); await expect(agent.updateDebtStatus(debtItemId, invalidStatus)).rejects.toThrow( `Invalid status: ${invalidStatus}` ); expect(mockKnowledgeGraph.updateContext).not.toHaveBeenCalled(); }); it('should throw error if debt item not found during status update', async () => { mockKnowledgeGraph.findNodes.mockResolvedValue([]); await expect(agent.updateDebtStatus('not_found_debt', 'resolved')).rejects.toThrow( 'Technical debt item not_found_debt not found.' ); }); });