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
JavaScript
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 })
});
});
});