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.

245 lines (205 loc) 9.35 kB
import { UXDesignerAgent } from '../ux-designer'; 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 = {}; describe('UXDesignerAgent', () => { let agent; beforeEach(() => { jest.clearAllMocks(); agent = new UXDesignerAgent(mockKnowledgeGraph, mockWorkflow); jest.spyOn(console, 'log').mockImplementation(() => {}); jest.spyOn(console, 'warn').mockImplementation(() => {}); }); afterEach(() => { console.log.mockRestore(); console.warn.mockRestore(); }); // --- Tests for existing methods --- it('should conduct user research and add to KG', async () => { const type = 'persona'; const parameters = { name: 'Admin User', goals: ['Manage system'] }; mockKnowledgeGraph.addNode.mockResolvedValue(undefined); const research = await agent.conductUserResearch(type, parameters); expect(research).toBeDefined(); expect(research.id).toMatch(/^research_/); expect(research.type).toBe(type); expect(research.data).toEqual(parameters); expect(mockKnowledgeGraph.addNode).toHaveBeenCalledWith({ id: `research:${research.id}`, type: 'user_research', data: research }); }); it('should create a wireframe and add to KG', async () => { const name = 'Login Page'; const description = 'Wireframe for the main login screen'; mockKnowledgeGraph.addNode.mockResolvedValue(undefined); const wireframe = await agent.createWireframe(name, description); expect(wireframe).toBeDefined(); expect(wireframe.id).toMatch(/^wireframe_/); expect(wireframe.name).toBe(name); expect(wireframe.description).toBe(description); expect(wireframe.components).toEqual([]); expect(wireframe.interactions).toEqual([]); expect(mockKnowledgeGraph.addNode).toHaveBeenCalledWith({ id: `wireframe:${wireframe.id}`, type: 'wireframe', data: wireframe }); }); it('should add a component to a wireframe', async () => { const wireframeId = 'wireframe_123'; const mockWireframeNode = { id: `wireframe:${wireframeId}`, type: 'wireframe', data: { id: wireframeId, components: [], interactions: [] } }; const component = { id: 'comp_a', type: 'button', position: { x: 10, y: 10 }, size: { width: 50, height: 20 }, props: { label: 'Submit' } }; mockKnowledgeGraph.findNodes.mockResolvedValue([mockWireframeNode]); mockKnowledgeGraph.updateContext.mockResolvedValue(undefined); await agent.addComponentToWireframe(wireframeId, component); expect(mockKnowledgeGraph.findNodes).toHaveBeenCalledWith({ type: 'wireframe', id: `wireframe:${wireframeId}` }); expect(mockWireframeNode.data.components).toContain(component); expect(mockKnowledgeGraph.updateContext).toHaveBeenCalledWith({ id: mockWireframeNode.id, data: mockWireframeNode.data }); }); it('should add an interaction to a wireframe', async () => { const wireframeId = 'wireframe_456'; const mockWireframeNode = { id: `wireframe:${wireframeId}`, type: 'wireframe', data: { id: wireframeId, components: [], interactions: [] } }; const interaction = { sourceId: 'comp_a', targetId: 'comp_b', type: 'click', description: 'Navigates to next screen' }; mockKnowledgeGraph.findNodes.mockResolvedValue([mockWireframeNode]); mockKnowledgeGraph.updateContext.mockResolvedValue(undefined); await agent.addInteractionToWireframe(wireframeId, interaction); expect(mockWireframeNode.data.interactions).toContain(interaction); expect(mockKnowledgeGraph.updateContext).toHaveBeenCalledWith({ id: mockWireframeNode.id, data: mockWireframeNode.data }); }); it('should validate a valid wireframe', async () => { const wireframeId = 'wireframe_valid'; const mockWireframeNode = { id: `wireframe:${wireframeId}`, type: 'wireframe', data: { id: wireframeId, components: [ { id: 'comp_a', type: 'input', position: { x: 0, y: 0 }, size: { width: 100, height: 30 }, props: {} }, { id: 'comp_b', type: 'button', position: { x: 0, y: 40 }, size: { width: 100, height: 30 }, props: {} } ], interactions: [ { sourceId: 'comp_b', targetId: 'comp_a', type: 'click', description: 'Focus input' } ] } }; mockKnowledgeGraph.findNodes.mockResolvedValue([mockWireframeNode]); const result = await agent.validateWireframe(wireframeId); expect(result.valid).toBe(true); expect(result.errors).toEqual([]); }); it('should find validation errors in an invalid wireframe', async () => { const wireframeId = 'wireframe_invalid'; const mockWireframeNode = { id: `wireframe:${wireframeId}`, type: 'wireframe', data: { id: wireframeId, components: [ { id: 'comp_a', type: 'input' /* Missing position/size */ }, ], interactions: [ { sourceId: 'comp_a', targetId: 'comp_nonexistent', type: 'click' } ] } }; mockKnowledgeGraph.findNodes.mockResolvedValue([mockWireframeNode]); const result = await agent.validateWireframe(wireframeId); expect(result.valid).toBe(false); expect(result.errors).toHaveLength(2); expect(result.errors).toContain('Component comp_a missing position or size'); expect(result.errors).toContain('Interaction references non-existent component: comp_a -> comp_nonexistent'); }); // --- Tests for new UX research methods --- it('should create a journey map', async () => { const name = 'User Signup Journey'; const personaId = 'persona:new_user'; const stages = [{ name: 'Discovery', actions: ['Search online'] }, { name: 'Signup', actions: ['Fill form'] }]; const mockPersonaNode = { id: personaId, type: 'user_persona' }; // Simulate persona exists mockKnowledgeGraph.findNodes.mockResolvedValue([mockPersonaNode]); // Find persona mockKnowledgeGraph.addNode.mockResolvedValue(undefined); const journeyMap = await agent.createJourneyMap(name, personaId, stages); expect(journeyMap).toBeDefined(); expect(journeyMap.id).toMatch(/^journeyMap:user-signup-journey_/); expect(journeyMap.name).toBe(name); expect(journeyMap.personaId).toBe(personaId); expect(journeyMap.stages).toEqual(stages); expect(mockKnowledgeGraph.findNodes).toHaveBeenCalledWith({ id: personaId, type: 'user_persona' }); expect(mockKnowledgeGraph.addNode).toHaveBeenCalledWith({ id: journeyMap.id, type: 'journey_map', data: expect.objectContaining({ name, personaId, stages }), edges: [{ target: personaId, relationship: 'describes_journey_of' }] }); }); it('should create a journey map even if persona not found (with warning)', async () => { const name = 'Guest Checkout'; const personaId = 'persona:nonexistent'; const stages = [{ name: 'Add to Cart' }]; mockKnowledgeGraph.findNodes.mockResolvedValue([]); // Persona not found mockKnowledgeGraph.addNode.mockResolvedValue(undefined); const journeyMap = await agent.createJourneyMap(name, personaId, stages); expect(journeyMap).toBeDefined(); expect(journeyMap.id).toMatch(/^journeyMap:guest-checkout_/); expect(console.warn).toHaveBeenCalledWith(`Persona ${personaId} not found for journey map ${name}. Creating map anyway.`); expect(mockKnowledgeGraph.addNode).toHaveBeenCalledWith(expect.objectContaining({ id: journeyMap.id, type: 'journey_map', edges: [] // No edge added if persona not found })); }); it('should create a site map', async () => { const name = 'Product Docs v2'; const structure = { name: 'Home', path: '/', children: [{ name: 'API', path: '/api' }] }; mockKnowledgeGraph.addNode.mockResolvedValue(undefined); const siteMap = await agent.createSiteMap(name, structure); expect(siteMap).toBeDefined(); expect(siteMap.id).toMatch(/^siteMap:product-docs-v2_/); expect(siteMap.name).toBe(name); expect(siteMap.structure).toEqual(structure); expect(siteMap.version).toBe(1); expect(mockKnowledgeGraph.addNode).toHaveBeenCalledWith({ id: siteMap.id, type: 'site_map', data: expect.objectContaining({ name, structure }) }); }); it('should create an OOUX template', async () => { const name = 'E-commerce Product'; const objects = [{ name: 'Product', attributes: ['name', 'price'] }]; const ctas = [{ name: 'AddToCart', object: 'Product' }]; mockKnowledgeGraph.addNode.mockResolvedValue(undefined); const oouxTemplate = await agent.createOOUXTemplate(name, objects, ctas); expect(oouxTemplate).toBeDefined(); expect(oouxTemplate.id).toMatch(/^oouxTemplate:e-commerce-product_/); expect(oouxTemplate.name).toBe(name); expect(oouxTemplate.objects).toEqual(objects); expect(oouxTemplate.ctas).toEqual(ctas); expect(mockKnowledgeGraph.addNode).toHaveBeenCalledWith({ id: oouxTemplate.id, type: 'ooux_template', data: expect.objectContaining({ name, objects, ctas }) }); }); });