task-master-neo-sdlc
Version:
Enhanced task management system with Neo SDLC agents and MCP tools for comprehensive, AI-driven software development lifecycle management.
160 lines (131 loc) • 6.37 kB
JavaScript
import { KnowledgeBaseManagerAgent } from '../knowledge-base-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(),
addEdge: jest.fn()
};
const mockWorkflow = {};
describe('KnowledgeBaseManagerAgent', () => {
let agent;
beforeEach(() => {
jest.clearAllMocks();
agent = new KnowledgeBaseManagerAgent(mockKnowledgeGraph, mockWorkflow);
jest.spyOn(console, 'log').mockImplementation(() => {});
});
afterEach(() => {
console.log.mockRestore();
});
it('should create a knowledge base article', async () => {
const title = 'Setup Guide';
const content = '# How to set up the project...';
const tags = ['setup', 'guide'];
const relatedEntities = ['component:setup-wizard'];
mockKnowledgeGraph.addNode.mockResolvedValue(undefined);
const articleData = await agent.createArticle(title, content, tags, relatedEntities);
expect(articleData).toBeDefined();
expect(articleData.id).toMatch(/^kb_article:setup-guide_/);
expect(articleData.title).toBe(title);
expect(articleData.content).toBe(content);
expect(articleData.tags).toEqual(tags);
expect(articleData.version).toBe(1);
expect(mockKnowledgeGraph.addNode).toHaveBeenCalledWith({
id: articleData.id,
type: 'kb_article',
data: expect.objectContaining({ title, content, tags }),
edges: [{ target: 'component:setup-wizard', relationship: 'documents' }]
});
});
it('should update an existing knowledge base article', async () => {
const articleId = 'kb_article:api-docs_123';
const updates = { content: 'Updated API documentation.', tags: ['api', 'docs', 'v2'] };
const mockExistingNode = {
id: articleId,
type: 'kb_article',
data: { title: 'API Docs', content: 'Old content', tags: ['api'], version: 1 }
};
mockKnowledgeGraph.findNodes.mockResolvedValue([mockExistingNode]);
mockKnowledgeGraph.updateContext.mockResolvedValue(undefined);
const updatedData = await agent.updateArticle(articleId, updates);
expect(updatedData).toBeDefined();
expect(updatedData.content).toBe(updates.content);
expect(updatedData.tags).toEqual(updates.tags);
expect(updatedData.version).toBe(2);
expect(updatedData.updatedAt).not.toBe(mockExistingNode.data.updatedAt);
expect(mockKnowledgeGraph.findNodes).toHaveBeenCalledWith({ id: articleId, type: 'kb_article' });
expect(mockKnowledgeGraph.updateContext).toHaveBeenCalledWith({
id: articleId,
data: expect.objectContaining({ content: updates.content, tags: updates.tags, version: 2 })
});
});
it('should throw error if article not found during update', async () => {
const articleId = 'kb_article:nonexistent';
mockKnowledgeGraph.findNodes.mockResolvedValue([]); // Simulate not found
await expect(agent.updateArticle(articleId, { content: 'new' })).rejects.toThrow(
`Knowledge base article ${articleId} not found.`
);
});
it('should search articles by query (title/tag/content match)', async () => {
const mockArticles = [
{ id: 'kb:1', data: { title: 'Database Setup', tags: ['db', 'setup'], content: 'Guide...' } },
{ id: 'kb:2', data: { title: 'API Endpoints', tags: ['api'], content: 'List of endpoints...' } },
{ id: 'kb:3', data: { title: 'Frontend Components', tags: ['ui', 'react'], content: 'About the Button setup.' } }
];
mockKnowledgeGraph.findNodes.mockResolvedValue(mockArticles);
const results = await agent.searchArticles('setup');
expect(results).toBeDefined();
expect(results.length).toBe(2); // Matches title/tag in kb:1, content in kb:3
expect(results[0].title).toBe('Database Setup');
expect(results[1].title).toBe('Frontend Components');
expect(mockKnowledgeGraph.findNodes).toHaveBeenCalledWith({ type: 'kb_article' });
});
it('should search articles filtering by tags', async () => {
const mockArticles = [
{ id: 'kb:1', data: { title: 'DB Guide', tags: ['db', 'setup'], content: '...' } },
{ id: 'kb:2', data: { title: 'API Setup', tags: ['api', 'setup'], content: '...' } },
{ id: 'kb:3', data: { title: 'UI Setup', tags: ['ui'], content: '...' } }
];
mockKnowledgeGraph.findNodes.mockResolvedValue(mockArticles);
const results = await agent.searchArticles('setup', { tags: ['api'] });
expect(results.length).toBe(1); // Matches 'setup' in title/tag AND has 'api' tag
expect(results[0].title).toBe('API Setup');
});
it('should limit search results', async () => {
const mockArticles = Array.from({ length: 15 }, (_, i) => (
{ id: `kb:${i}`, data: { title: `Article ${i}`, tags: ['search'], content: 'Content search term' } }
));
mockKnowledgeGraph.findNodes.mockResolvedValue(mockArticles);
const results = await agent.searchArticles('search', { limit: 5 });
expect(results.length).toBe(5);
});
it('should link two articles', async () => {
const sourceId = 'kb_article:source_1';
const targetId = 'kb_article:target_2';
const relationship = 'explains';
// Mock findNodes to confirm articles exist
mockKnowledgeGraph.findNodes
.mockResolvedValueOnce([{ id: sourceId, type: 'kb_article' }]) // Find source
.mockResolvedValueOnce([{ id: targetId, type: 'kb_article' }]); // Find target
mockKnowledgeGraph.addEdge.mockResolvedValue(undefined);
await agent.linkArticles(sourceId, targetId, relationship);
expect(mockKnowledgeGraph.addEdge).toHaveBeenCalledWith({
source: sourceId,
target: targetId,
relationship
});
});
it('should throw error if article not found during linking', async () => {
const sourceId = 'kb_article:exists';
const targetId = 'kb_article:notfound';
mockKnowledgeGraph.findNodes
.mockResolvedValueOnce([{ id: sourceId, type: 'kb_article' }]) // Source exists
.mockResolvedValueOnce([]); // Target does not exist
await expect(agent.linkArticles(sourceId, targetId)).rejects.toThrow(
`One or both articles not found for linking: ${sourceId}, ${targetId}`
);
expect(mockKnowledgeGraph.addEdge).not.toHaveBeenCalled();
});
});