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.

137 lines (114 loc) 6.34 kB
import { RequirementsValidatorAgent } from '../requirements-validator'; import { KnowledgeGraph } from '../../knowledge-graph'; // Adjust path import { AgentWorkflowSystem } from '../../agent-workflow'; // Adjust path // Mocks const mockKnowledgeGraph = { addNode: jest.fn(), findNodes: jest.fn(), findEdges: jest.fn() }; const mockWorkflow = {}; describe('RequirementsValidatorAgent', () => { let agent; beforeEach(() => { jest.clearAllMocks(); agent = new RequirementsValidatorAgent(mockKnowledgeGraph, mockWorkflow); jest.spyOn(console, 'log').mockImplementation(() => {}); }); afterEach(() => { console.log.mockRestore(); }); it('should validate against specific requirements and find compliance', async () => { const targetId = 'component:login-button'; const reqId1 = 'req:auth-001'; const reqId2 = 'req:ui-005'; const mockTargetNode = { id: targetId, data: { label: 'Login', usesOAuth: true } }; const mockReqNode1 = { id: reqId1, data: { id: reqId1, summary: 'Use OAuth', criteria: { keyword: 'OAuth' } } }; const mockReqNode2 = { id: reqId2, data: { id: reqId2, summary: 'Label must exist', criteria: { requiredProperty: 'label' } } }; mockKnowledgeGraph.findNodes .mockImplementationOnce(async ({ id }) => id === targetId ? [mockTargetNode] : []) // Find target .mockImplementationOnce(async ({ ids }) => { // Find requirements by ID const nodes = []; if (ids.includes(reqId1)) nodes.push(mockReqNode1); if (ids.includes(reqId2)) nodes.push(mockReqNode2); return nodes; }); mockKnowledgeGraph.addNode.mockResolvedValue(undefined); const report = await agent.validateAgainstRequirements(targetId, [reqId1, reqId2]); expect(report).toBeDefined(); expect(report.status).toBe('compliant'); expect(report.violations).toEqual([]); expect(report.requirementsChecked).toEqual([reqId1, reqId2]); expect(mockKnowledgeGraph.findNodes).toHaveBeenCalledWith({ id: targetId }); expect(mockKnowledgeGraph.findNodes).toHaveBeenCalledWith({ ids: [reqId1, reqId2], type: 'requirement' }); expect(mockKnowledgeGraph.addNode).toHaveBeenCalledWith(expect.objectContaining({ type: 'requirements_validation_report', data: expect.objectContaining({ status: 'compliant' }) })); }); it('should validate against associated requirements found via KG edges', async () => { const targetId = 'api_endpoint:POST:_api_users'; const reqId = 'req:data-010'; const mockTargetNode = { id: targetId, data: { usesEncryption: true } }; const mockReqNode = { id: reqId, data: { id: reqId, summary: 'Must use encryption', criteria: { keyword: 'Encryption' } } }; const mockEdge = { source: reqId, target: targetId, relationship: 'implements' }; mockKnowledgeGraph.findNodes .mockImplementationOnce(async ({ id }) => id === targetId ? [mockTargetNode] : []) // Find target .mockImplementationOnce(async ({ ids }) => ids.includes(reqId) ? [mockReqNode] : []); // Find requirements by ID from edge mockKnowledgeGraph.findEdges.mockResolvedValue([mockEdge]); // Find edge linking requirement mockKnowledgeGraph.addNode.mockResolvedValue(undefined); const report = await agent.validateAgainstRequirements(targetId); // No specific IDs passed expect(report.status).toBe('compliant'); expect(report.violations).toEqual([]); expect(report.requirementsChecked).toEqual([reqId]); expect(mockKnowledgeGraph.findEdges).toHaveBeenCalledWith({ target: targetId, relationship: 'implements' }); expect(mockKnowledgeGraph.findNodes).toHaveBeenCalledWith({ ids: [reqId], type: 'requirement' }); expect(mockKnowledgeGraph.addNode).toHaveBeenCalled(); }); it('should report violations when requirements are not met', async () => { const targetId = 'component:profile-form'; const reqId1 = 'req:ux-001'; // Missing property const reqId2 = 'req:sec-002'; // Missing keyword const mockTargetNode = { id: targetId, data: { fields: ['name'], usesTLS: false } }; // Missing 'email', no 'TLS' keyword const mockReqNode1 = { id: reqId1, data: { id: reqId1, criteria: { requiredProperty: 'email' } } }; const mockReqNode2 = { id: reqId2, data: { id: reqId2, criteria: { keyword: 'TLS' } } }; mockKnowledgeGraph.findNodes .mockResolvedValueOnce([mockTargetNode]) .mockResolvedValueOnce([mockReqNode1, mockReqNode2]); mockKnowledgeGraph.addNode.mockResolvedValue(undefined); const report = await agent.validateAgainstRequirements(targetId, [reqId1, reqId2]); expect(report.status).toBe('non-compliant'); expect(report.violations).toHaveLength(2); expect(report.violations).toContainEqual({ requirementId: reqId1, details: 'Missing required property: email' }); expect(report.violations).toContainEqual({ requirementId: reqId2, details: 'Implementation may not meet criteria keyword: TLS' }); expect(mockKnowledgeGraph.addNode).toHaveBeenCalledWith(expect.objectContaining({ data: expect.objectContaining({ status: 'non-compliant' }) })); }); it('should skip validation if no requirements are found or provided', async () => { const targetId = 'component:orphan'; const mockTargetNode = { id: targetId, data: {} }; mockKnowledgeGraph.findNodes.mockResolvedValueOnce([mockTargetNode]); mockKnowledgeGraph.findEdges.mockResolvedValue([]); // No edges linking requirements const report = await agent.validateAgainstRequirements(targetId); expect(report.status).toBe('skipped'); expect(report.violations).toEqual([]); expect(report.requirementsChecked).toEqual([]); expect(mockKnowledgeGraph.findEdges).toHaveBeenCalledWith({ target: targetId, relationship: 'implements' }); expect(mockKnowledgeGraph.addNode).not.toHaveBeenCalled(); // No report added if skipped }); it('should throw error if target entity is not found', async () => { const targetId = 'nonexistent:entity'; mockKnowledgeGraph.findNodes.mockResolvedValue([]); // Target not found await expect(agent.validateAgainstRequirements(targetId)).rejects.toThrow( `Target entity ${targetId} not found for validation.` ); expect(mockKnowledgeGraph.addNode).not.toHaveBeenCalled(); }); });