Skip to main content
Glama

documcp

by tosin2013
recommend-ssg.test.ts18.1 kB
/** * Test suite for SSG Recommendation Tool */ import { jest } from '@jest/globals'; import { recommendSSG } from '../../src/tools/recommend-ssg.js'; // Mock the memory initialization jest.mock('../../src/memory/index.js', () => ({ initializeMemory: jest.fn(), })); describe('recommendSSG', () => { let mockManager: any; beforeEach(() => { mockManager = { recall: jest.fn(), }; const { initializeMemory } = require('../../src/memory/index.js'); initializeMemory.mockResolvedValue(mockManager); }); afterEach(() => { jest.clearAllMocks(); }); describe('Input Validation', () => { it('should validate required analysisId parameter', async () => { await expect(recommendSSG({})).rejects.toThrow(); }); it('should validate analysisId as string', async () => { await expect(recommendSSG({ analysisId: 123 })).rejects.toThrow(); }); it('should accept valid preferences', async () => { mockManager.recall.mockResolvedValue(null); const result = await recommendSSG({ analysisId: 'test-id', preferences: { priority: 'simplicity', ecosystem: 'javascript', }, }); expect(result.content).toBeDefined(); }); it('should reject invalid priority preference', async () => { await expect( recommendSSG({ analysisId: 'test-id', preferences: { priority: 'invalid' }, }), ).rejects.toThrow(); }); it('should reject invalid ecosystem preference', async () => { await expect( recommendSSG({ analysisId: 'test-id', preferences: { ecosystem: 'invalid' }, }), ).rejects.toThrow(); }); }); describe('Memory Integration', () => { it('should retrieve analysis from memory when available', async () => { const mockAnalysis = { data: { content: [ { type: 'text', text: JSON.stringify({ repository: { language: 'JavaScript' }, complexity: 'low', size: 'small', }), }, ], }, }; mockManager.recall.mockResolvedValue(mockAnalysis); const result = await recommendSSG({ analysisId: 'test-id', }); expect(mockManager.recall).toHaveBeenCalledWith('test-id'); expect(result.content).toBeDefined(); }); it('should handle missing analysis gracefully', async () => { mockManager.recall.mockResolvedValue(null); const result = await recommendSSG({ analysisId: 'non-existent-id', }); expect(result.content).toBeDefined(); expect(result.content[0].type).toBe('text'); }); it('should handle analysis with direct data structure', async () => { const mockAnalysis = { data: { repository: { language: 'Python' }, complexity: 'medium', }, }; mockManager.recall.mockResolvedValue(mockAnalysis); const result = await recommendSSG({ analysisId: 'test-id', }); expect(result.content).toBeDefined(); }); it('should handle corrupted analysis data', async () => { const mockAnalysis = { data: { content: [ { type: 'text', text: 'invalid json', }, ], }, }; mockManager.recall.mockResolvedValue(mockAnalysis); const result = await recommendSSG({ analysisId: 'test-id', }); expect(result.content).toBeDefined(); }); }); describe('SSG Recommendations', () => { it('should recommend Jekyll for Ruby projects', async () => { const mockAnalysis = { data: { dependencies: { ecosystem: 'ruby', }, complexity: 'low', }, }; mockManager.recall.mockResolvedValue(mockAnalysis); const result = await recommendSSG({ analysisId: 'test-id', }); const recommendation = JSON.parse(result.content[0].text); expect(recommendation.recommended).toBe('jekyll'); }); it('should recommend Hugo for Go projects', async () => { const mockAnalysis = { data: { dependencies: { ecosystem: 'go', }, complexity: 'medium', }, }; mockManager.recall.mockResolvedValue(mockAnalysis); const result = await recommendSSG({ analysisId: 'test-id', }); const recommendation = JSON.parse(result.content[0].text); expect(recommendation.recommended).toBe('hugo'); }); it('should recommend Docusaurus for JavaScript projects', async () => { const mockAnalysis = { data: { dependencies: { ecosystem: 'javascript', }, documentation: { estimatedComplexity: 'complex', }, recommendations: { teamSize: 'large', }, }, }; mockManager.recall.mockResolvedValue(mockAnalysis); const result = await recommendSSG({ analysisId: 'test-id', }); const recommendation = JSON.parse(result.content[0].text); expect(recommendation.recommended).toBe('docusaurus'); }); it('should recommend MkDocs for Python projects', async () => { const mockAnalysis = { data: { dependencies: { ecosystem: 'python', }, complexity: 'medium', }, }; mockManager.recall.mockResolvedValue(mockAnalysis); const result = await recommendSSG({ analysisId: 'test-id', }); const recommendation = JSON.parse(result.content[0].text); expect(recommendation.recommended).toBe('mkdocs'); }); it('should recommend Eleventy for simple JavaScript projects with simplicity priority', async () => { const mockAnalysis = { data: { dependencies: { ecosystem: 'javascript', }, documentation: { estimatedComplexity: 'simple', }, recommendations: { teamSize: 'small', }, }, }; mockManager.recall.mockResolvedValue(mockAnalysis); const result = await recommendSSG({ analysisId: 'test-id', preferences: { priority: 'simplicity' }, }); const recommendation = JSON.parse(result.content[0].text); expect(recommendation.recommended).toBe('eleventy'); }); }); describe('Preference-based Recommendations', () => { it('should prioritize simplicity when requested', async () => { mockManager.recall.mockResolvedValue(null); const result = await recommendSSG({ analysisId: 'test-id', preferences: { priority: 'simplicity' }, }); const recommendation = JSON.parse(result.content[0].text); expect(['jekyll', 'eleventy']).toContain(recommendation.recommended); }); it('should consider ecosystem preferences', async () => { mockManager.recall.mockResolvedValue(null); const result = await recommendSSG({ analysisId: 'test-id', preferences: { ecosystem: 'javascript' }, }); const recommendation = JSON.parse(result.content[0].text); expect(['docusaurus', 'eleventy']).toContain(recommendation.recommended); }); it('should handle performance preference with fallback', async () => { mockManager.recall.mockResolvedValue(null); const result = await recommendSSG({ analysisId: 'test-id', preferences: { priority: 'performance' }, }); const recommendation = JSON.parse(result.content[0].text); expect(recommendation.recommended).toBe('docusaurus'); }); it('should handle features preference with fallback', async () => { mockManager.recall.mockResolvedValue(null); const result = await recommendSSG({ analysisId: 'test-id', preferences: { priority: 'features' }, }); const recommendation = JSON.parse(result.content[0].text); expect(recommendation.recommended).toBe('docusaurus'); }); }); describe('Scoring and Alternatives', () => { it('should provide confidence scores', async () => { mockManager.recall.mockResolvedValue({ data: { dependencies: { ecosystem: 'javascript', }, complexity: 'medium', }, }); const result = await recommendSSG({ analysisId: 'test-id', }); const recommendation = JSON.parse(result.content[0].text); expect(recommendation.confidence).toBeGreaterThan(0); expect(recommendation.confidence).toBeLessThanOrEqual(1); }); it('should provide alternative recommendations', async () => { mockManager.recall.mockResolvedValue({ data: { dependencies: { ecosystem: 'javascript', }, complexity: 'medium', }, }); const result = await recommendSSG({ analysisId: 'test-id', }); const recommendation = JSON.parse(result.content[0].text); expect(recommendation.alternatives).toBeDefined(); expect(Array.isArray(recommendation.alternatives)).toBe(true); expect(recommendation.alternatives.length).toBeGreaterThan(0); }); it('should include pros and cons for alternatives', async () => { mockManager.recall.mockResolvedValue({ data: { dependencies: { ecosystem: 'python', }, complexity: 'medium', }, }); const result = await recommendSSG({ analysisId: 'test-id', }); const recommendation = JSON.parse(result.content[0].text); const alternative = recommendation.alternatives[0]; expect(alternative.name).toBeDefined(); expect(alternative.score).toBeDefined(); expect(Array.isArray(alternative.pros)).toBe(true); expect(Array.isArray(alternative.cons)).toBe(true); }); it('should sort alternatives by score', async () => { mockManager.recall.mockResolvedValue({ data: { dependencies: { ecosystem: 'javascript', }, documentation: { estimatedComplexity: 'complex', }, }, }); const result = await recommendSSG({ analysisId: 'test-id', }); const recommendation = JSON.parse(result.content[0].text); const scores = recommendation.alternatives.map((alt: any) => alt.score); for (let i = 1; i < scores.length; i++) { expect(scores[i]).toBeLessThanOrEqual(scores[i - 1]); } }); }); describe('Complex Project Analysis', () => { it('should handle projects with React packages', async () => { mockManager.recall.mockResolvedValue({ data: { dependencies: { ecosystem: 'javascript', packages: ['react', 'next'], }, }, }); const result = await recommendSSG({ analysisId: 'test-id', }); const recommendation = JSON.parse(result.content[0].text); expect(recommendation.recommended).toBe('docusaurus'); expect(recommendation.reasoning.length).toBeGreaterThan(0); }); it('should consider project size in recommendations', async () => { mockManager.recall.mockResolvedValue({ data: { dependencies: { ecosystem: 'javascript', }, structure: { totalFiles: 150, // Large project }, documentation: { estimatedComplexity: 'complex', hasReadme: true, hasDocs: true, }, }, }); const result = await recommendSSG({ analysisId: 'test-id', }); const recommendation = JSON.parse(result.content[0].text); expect(recommendation.confidence).toBeGreaterThan(0.85); // Should have higher confidence with more data }); it('should handle missing ecosystem information', async () => { mockManager.recall.mockResolvedValue({ data: { dependencies: { ecosystem: 'unknown', }, documentation: { estimatedComplexity: 'moderate', }, }, }); const result = await recommendSSG({ analysisId: 'test-id', }); const recommendation = JSON.parse(result.content[0].text); expect(recommendation.recommended).toBeDefined(); }); it('should consider existing documentation structure', async () => { mockManager.recall.mockResolvedValue({ data: { dependencies: { ecosystem: 'javascript', }, documentation: { hasReadme: true, hasDocs: true, estimatedComplexity: 'moderate', }, }, }); const result = await recommendSSG({ analysisId: 'test-id', }); const recommendation = JSON.parse(result.content[0].text); expect(recommendation.confidence).toBeGreaterThan(0.85); // Higher confidence with documentation }); }); describe('Memory Error Handling', () => { it('should handle memory initialization failure', async () => { const { initializeMemory } = require('../../src/memory/index.js'); initializeMemory.mockRejectedValue(new Error('Memory failed')); const result = await recommendSSG({ analysisId: 'test-id', }); expect(result.content).toBeDefined(); expect(result.content[0].type).toBe('text'); }); it('should handle memory recall failure', async () => { mockManager.recall.mockRejectedValue(new Error('Recall failed')); const result = await recommendSSG({ analysisId: 'test-id', }); expect(result.content).toBeDefined(); }); it('should handle corrupted memory data', async () => { mockManager.recall.mockResolvedValue({ data: { content: [ { type: 'text', text: '{"invalid": json}', }, ], }, }); const result = await recommendSSG({ analysisId: 'test-id', }); expect(result.content).toBeDefined(); }); }); describe('Performance and Timing', () => { it('should complete recommendation in reasonable time', async () => { mockManager.recall.mockResolvedValue({ data: { repository: { language: 'JavaScript' }, complexity: 'medium', }, }); const start = Date.now(); await recommendSSG({ analysisId: 'test-id', }); const duration = Date.now() - start; expect(duration).toBeLessThan(5000); // Should complete within 5 seconds }); it('should include execution time in response', async () => { mockManager.recall.mockResolvedValue({ data: { repository: { language: 'JavaScript' }, }, }); const result = await recommendSSG({ analysisId: 'test-id', }); expect(result.content[1].text).toContain('Execution completed in'); }); }); describe('Edge Cases', () => { it('should handle null analysis data', async () => { mockManager.recall.mockResolvedValue({ data: null, }); const result = await recommendSSG({ analysisId: 'test-id', }); expect(result.content).toBeDefined(); }); it('should handle empty analysis data', async () => { mockManager.recall.mockResolvedValue({ data: {}, }); const result = await recommendSSG({ analysisId: 'test-id', }); expect(result.content).toBeDefined(); }); it('should handle analysis without dependency data', async () => { mockManager.recall.mockResolvedValue({ data: { documentation: { estimatedComplexity: 'moderate', }, }, }); const result = await recommendSSG({ analysisId: 'test-id', }); const recommendation = JSON.parse(result.content[0].text); expect(recommendation.recommended).toBeDefined(); }); it('should handle unknown programming languages', async () => { mockManager.recall.mockResolvedValue({ data: { dependencies: { ecosystem: 'unknown', }, documentation: { estimatedComplexity: 'moderate', }, }, }); const result = await recommendSSG({ analysisId: 'test-id', }); const recommendation = JSON.parse(result.content[0].text); expect(recommendation.recommended).toBeDefined(); }); }); describe('Response Format', () => { it('should return properly formatted MCP response', async () => { mockManager.recall.mockResolvedValue({ data: { repository: { language: 'JavaScript' }, }, }); const result = await recommendSSG({ analysisId: 'test-id', }); expect(result).toHaveProperty('content'); expect(Array.isArray(result.content)).toBe(true); expect(result.content[0]).toHaveProperty('type'); expect(result.content[0]).toHaveProperty('text'); }); it('should include all required recommendation fields', async () => { mockManager.recall.mockResolvedValue({ data: { repository: { language: 'Python' }, }, }); const result = await recommendSSG({ analysisId: 'test-id', }); const recommendation = JSON.parse(result.content[0].text); expect(recommendation).toHaveProperty('recommended'); expect(recommendation).toHaveProperty('confidence'); expect(recommendation).toHaveProperty('reasoning'); expect(recommendation).toHaveProperty('alternatives'); expect(result.content[1].text).toContain('Execution completed in'); }); }); });

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/tosin2013/documcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server