Skip to main content
Glama

mcp-adr-analysis-server

by tosin2013
deployment-guidance-tool.test.ts21.4 kB
/** * Unit tests for deployment-guidance-tool.ts * Tests the generateDeploymentGuidance function with comprehensive scenarios */ import { jest } from '@jest/globals'; import { McpAdrError } from '../../src/types/index.js'; // Pragmatic mocking approach to avoid TypeScript complexity jest.unstable_mockModule('../../src/utils/adr-discovery.js', () => ({ discoverAdrsInDirectory: jest.fn(), })); const { generateDeploymentGuidance } = await import('../../src/tools/deployment-guidance-tool.js'); const { discoverAdrsInDirectory } = await import('../../src/utils/adr-discovery.js'); describe('deployment-guidance-tool', () => { describe('generateDeploymentGuidance', () => { beforeEach(() => { jest.clearAllMocks(); }); describe('basic functionality', () => { it('should generate deployment guidance with default parameters', async () => { const mockAdrs = [ { title: 'Use Docker for Containerization', filename: 'ADR-001-docker.md', status: 'Accepted', content: 'We will use Docker containers for consistent deployment across environments.', date: '2024-01-01', path: '/test/ADR-001-docker.md', }, ]; ( discoverAdrsInDirectory as jest.MockedFunction<typeof discoverAdrsInDirectory> ).mockResolvedValue({ adrs: mockAdrs, summary: { byStatus: { Accepted: 1 }, byCategory: {} }, directory: 'docs/adrs', totalAdrs: 1, recommendations: [], } as any); const result = await generateDeploymentGuidance({}); expect(discoverAdrsInDirectory).toHaveBeenCalledWith('docs/adrs', true, process.cwd()); expect(result).toHaveProperty('content'); expect(Array.isArray(result.content)).toBe(true); expect(result.content[0]).toHaveProperty('type', 'text'); expect(result.content[0].text).toContain('Deployment Guidance Generation'); expect(result.content[0].text).toContain('Found 1 ADRs'); expect(result.content[0].text).toContain('**Target Environment**: production'); expect(result.content[0].text).toContain('Use Docker for Containerization'); }); it('should handle custom ADR directory and project path', async () => { const mockAdrs = [ { title: 'Database Selection', filename: 'ADR-002-database.md', status: 'Accepted', content: 'We will use PostgreSQL as our primary database.', date: '2024-01-01', path: '/test/ADR-002-database.md', }, ]; ( discoverAdrsInDirectory as jest.MockedFunction<typeof discoverAdrsInDirectory> ).mockResolvedValue({ adrs: mockAdrs, summary: { byStatus: { Accepted: 1 }, byCategory: {} }, directory: 'custom/adrs', totalAdrs: 1, recommendations: [], } as any); const result = await generateDeploymentGuidance({ adrDirectory: 'custom/adrs', projectPath: '/custom/project', }); expect(discoverAdrsInDirectory).toHaveBeenCalledWith( 'custom/adrs', true, '/custom/project' ); expect(result.content[0].text).toContain('**ADR Directory**: custom/adrs'); expect(result.content[0].text).toContain('Database Selection'); }); it('should handle different environments', async () => { const mockAdrs = [ { title: 'Load Balancer Configuration', filename: 'ADR-003-loadbalancer.md', status: 'Accepted', content: 'We will use Nginx as our load balancer for high availability.', date: '2024-01-01', path: '/test/ADR-003-loadbalancer.md', }, ]; ( discoverAdrsInDirectory as jest.MockedFunction<typeof discoverAdrsInDirectory> ).mockResolvedValue({ adrs: mockAdrs, summary: { byStatus: { Accepted: 1 }, byCategory: {} }, directory: 'docs/adrs', totalAdrs: 1, recommendations: [], } as any); const result = await generateDeploymentGuidance({ environment: 'staging', }); expect(result.content[0].text).toContain('**Target Environment**: staging'); expect(result.content[0].text).toContain('Testing**: Staging-specific configurations'); expect(result.content[0].text).toContain('Load Balancer Configuration'); }); it('should handle development environment specifics', async () => { const mockAdrs = [ { title: 'Development Setup', filename: 'ADR-004-dev.md', status: 'Accepted', content: 'Development environment will use hot-reload and local services.', date: '2024-01-01', path: '/test/ADR-004-dev.md', }, ]; ( discoverAdrsInDirectory as jest.MockedFunction<typeof discoverAdrsInDirectory> ).mockResolvedValue({ adrs: mockAdrs, summary: { byStatus: { Accepted: 1 }, byCategory: {} }, directory: 'docs/adrs', totalAdrs: 1, recommendations: [], } as any); const result = await generateDeploymentGuidance({ environment: 'development', }); expect(result.content[0].text).toContain('**Target Environment**: development'); expect(result.content[0].text).toContain( 'Development**: Hot-reload, debugging, local services' ); expect(result.content[0].text).toContain('Development Setup'); }); }); describe('configuration options', () => { it('should handle all configuration flags enabled', async () => { const mockAdrs = [ { title: 'Complete Infrastructure', filename: 'ADR-005-infra.md', status: 'Accepted', content: 'Complete infrastructure setup with monitoring, security, and rollback procedures.', date: '2024-01-01', path: '/test/ADR-005-infra.md', }, ]; ( discoverAdrsInDirectory as jest.MockedFunction<typeof discoverAdrsInDirectory> ).mockResolvedValue({ adrs: mockAdrs, summary: { byStatus: { Accepted: 1 }, byCategory: {} }, directory: 'docs/adrs', totalAdrs: 1, recommendations: [], } as any); const result = await generateDeploymentGuidance({ includeScripts: true, includeConfigs: true, includeValidation: true, includeRollback: true, generateFiles: true, }); expect(result.content[0].text).toContain('**Include Scripts**: true'); expect(result.content[0].text).toContain('**Include Configs**: true'); expect(result.content[0].text).toContain('**Include Validation**: true'); expect(result.content[0].text).toContain('**Include Rollback**: true'); expect(result.content[0].text).toContain('File Generation Mode'); expect(result.content[0].text).toContain('Script Generation'); expect(result.content[0].text).toContain('Validation & Health Checks'); expect(result.content[0].text).toContain('Rollback Procedures'); }); it('should handle configuration flags disabled', async () => { const mockAdrs = [ { title: 'Minimal Setup', filename: 'ADR-006-minimal.md', status: 'Accepted', content: 'Minimal deployment setup without additional scripts or validation.', date: '2024-01-01', path: '/test/ADR-006-minimal.md', }, ]; ( discoverAdrsInDirectory as jest.MockedFunction<typeof discoverAdrsInDirectory> ).mockResolvedValue({ adrs: mockAdrs, summary: { byStatus: { Accepted: 1 }, byCategory: {} }, directory: 'docs/adrs', totalAdrs: 1, recommendations: [], } as any); const result = await generateDeploymentGuidance({ includeScripts: false, includeConfigs: false, includeValidation: false, includeRollback: false, generateFiles: false, }); expect(result.content[0].text).toContain('**Include Scripts**: false'); expect(result.content[0].text).toContain('**Include Configs**: false'); expect(result.content[0].text).toContain('**Include Validation**: false'); expect(result.content[0].text).toContain('**Include Rollback**: false'); expect(result.content[0].text).not.toContain('Script Generation'); expect(result.content[0].text).not.toContain('Validation & Health Checks'); expect(result.content[0].text).not.toContain('Rollback Procedures'); expect(result.content[0].text).not.toContain('File Generation Mode'); }); it('should handle technology filter', async () => { const mockAdrs = [ { title: 'Technology Stack', filename: 'ADR-007-tech.md', status: 'Accepted', content: 'Using Node.js, PostgreSQL, and Docker for our technology stack.', date: '2024-01-01', path: '/test/ADR-007-tech.md', }, ]; ( discoverAdrsInDirectory as jest.MockedFunction<typeof discoverAdrsInDirectory> ).mockResolvedValue({ adrs: mockAdrs, summary: { byStatus: { Accepted: 1 }, byCategory: {} }, directory: 'docs/adrs', totalAdrs: 1, recommendations: [], } as any); const result = await generateDeploymentGuidance({ technologyFilter: ['Node.js', 'PostgreSQL', 'Docker'], }); expect(result.content[0].text).toContain('Technology Filter'); expect(result.content[0].text).toContain( 'Focus only on these technologies: Node.js, PostgreSQL, Docker' ); expect(result.content[0].text).toContain('Technology Stack'); }); it('should handle custom requirements', async () => { const mockAdrs = [ { title: 'Security Requirements', filename: 'ADR-008-security.md', status: 'Accepted', content: 'Security requirements including TLS, authentication, and monitoring.', date: '2024-01-01', path: '/test/ADR-008-security.md', }, ]; ( discoverAdrsInDirectory as jest.MockedFunction<typeof discoverAdrsInDirectory> ).mockResolvedValue({ adrs: mockAdrs, summary: { byStatus: { Accepted: 1 }, byCategory: {} }, directory: 'docs/adrs', totalAdrs: 1, recommendations: [], } as any); const result = await generateDeploymentGuidance({ customRequirements: ['GDPR compliance', 'High availability', 'Automated backups'], }); expect(result.content[0].text).toContain('Custom Requirements'); expect(result.content[0].text).toContain('- GDPR compliance'); expect(result.content[0].text).toContain('- High availability'); expect(result.content[0].text).toContain('- Automated backups'); expect(result.content[0].text).toContain('Security Requirements'); }); }); describe('no ADRs found scenario', () => { it('should provide helpful guidance when no ADRs are found', async () => { ( discoverAdrsInDirectory as jest.MockedFunction<typeof discoverAdrsInDirectory> ).mockResolvedValue({ adrs: [], summary: { byStatus: {}, byCategory: {} }, directory: 'custom/adrs', totalAdrs: 0, recommendations: [], } as any); const result = await generateDeploymentGuidance({ adrDirectory: 'custom/adrs', projectPath: '/test/project', }); expect(result.content[0].text).toContain('No ADRs Found for Deployment Guidance'); expect(result.content[0].text).toContain('**ADR Directory**: custom/adrs'); expect(result.content[0].text).toContain('**Project Path**: /test/project'); expect(result.content[0].text).toContain('Recommendations'); expect(result.content[0].text).toContain('Create ADRs with deployment-relevant decisions'); expect(result.content[0].text).toContain('Example ADR for Deployment'); expect(result.content[0].text).toContain('Use Docker for Containerization'); }); it('should use default paths when no ADRs found', async () => { ( discoverAdrsInDirectory as jest.MockedFunction<typeof discoverAdrsInDirectory> ).mockResolvedValue({ adrs: [], summary: { byStatus: {}, byCategory: {} }, directory: 'docs/adrs', totalAdrs: 0, recommendations: [], } as any); const result = await generateDeploymentGuidance({}); expect(result.content[0].text).toContain('**ADR Directory**: docs/adrs'); expect(result.content[0].text).toContain(`**Project Path**: ${process.cwd()}`); }); }); describe('error handling', () => { it('should throw McpAdrError when ADR discovery fails', async () => { const discoveryError = new Error('Failed to access directory'); ( discoverAdrsInDirectory as jest.MockedFunction<typeof discoverAdrsInDirectory> ).mockRejectedValue(discoveryError); await expect(generateDeploymentGuidance({})).rejects.toThrow(McpAdrError); await expect(generateDeploymentGuidance({})).rejects.toThrow( 'Deployment guidance generation failed: Failed to access directory' ); }); it('should handle non-Error exceptions', async () => { ( discoverAdrsInDirectory as jest.MockedFunction<typeof discoverAdrsInDirectory> ).mockRejectedValue('String error'); await expect(generateDeploymentGuidance({})).rejects.toThrow(McpAdrError); await expect(generateDeploymentGuidance({})).rejects.toThrow( 'Deployment guidance generation failed: String error' ); }); it('should handle undefined error', async () => { ( discoverAdrsInDirectory as jest.MockedFunction<typeof discoverAdrsInDirectory> ).mockRejectedValue(undefined); await expect(generateDeploymentGuidance({})).rejects.toThrow(McpAdrError); await expect(generateDeploymentGuidance({})).rejects.toThrow( 'Deployment guidance generation failed: undefined' ); }); }); describe('comprehensive scenarios', () => { it('should generate comprehensive production deployment guidance', async () => { const mockAdrs = [ { title: 'Production Architecture', filename: 'ADR-016-prod.md', status: 'Accepted', content: 'Production setup with Docker, PostgreSQL, Redis, Nginx, and monitoring.', date: '2024-01-01', path: '/test/ADR-016-prod.md', }, ]; ( discoverAdrsInDirectory as jest.MockedFunction<typeof discoverAdrsInDirectory> ).mockResolvedValue({ adrs: mockAdrs, summary: { byStatus: { Accepted: 1 }, byCategory: {} }, directory: 'docs/adrs', totalAdrs: 1, recommendations: [], } as any); const result = await generateDeploymentGuidance({ environment: 'production', format: 'all', includeScripts: true, includeConfigs: true, includeValidation: true, includeRollback: true, generateFiles: true, technologyFilter: ['Docker', 'PostgreSQL', 'Nginx'], customRequirements: ['High availability', 'Security compliance'], }); const content = result.content[0].text; // Verify all production-specific elements expect(content).toContain('**Target Environment**: production'); expect(content).toContain('Security**: TLS certificates, secure connections'); expect(content).toContain('Performance**: Load balancing, caching'); expect(content).toContain('Reliability**: Backup procedures, monitoring'); expect(content).toContain('Technology Filter'); expect(content).toContain('Docker, PostgreSQL, Nginx'); expect(content).toContain('Custom Requirements'); expect(content).toContain('High availability'); expect(content).toContain('Security compliance'); expect(content).toContain('File Generation Mode'); expect(content).toContain('Production Architecture'); }); it('should handle complex project structure', async () => { const mockAdrs = [ { title: 'Microservices Architecture', filename: 'ADR-017-microservices.md', status: 'Accepted', content: 'Adopting microservices architecture with service mesh and API gateway.', date: '2024-01-01', path: '/test/ADR-017-microservices.md', }, { title: 'Database Per Service', filename: 'ADR-018-db-per-service.md', status: 'Accepted', content: 'Each microservice will have its own database for data isolation.', date: '2024-01-01', path: '/test/ADR-018-db-per-service.md', }, ]; ( discoverAdrsInDirectory as jest.MockedFunction<typeof discoverAdrsInDirectory> ).mockResolvedValue({ adrs: mockAdrs, summary: { byStatus: { Accepted: 2 }, byCategory: {} }, directory: 'docs/adrs', totalAdrs: 2, recommendations: [], } as any); const result = await generateDeploymentGuidance({ projectPath: '/complex/microservices/project', environment: 'staging', }); expect(result.content[0].text).toContain('Found 2 ADRs'); expect(result.content[0].text).toContain('Microservices Architecture'); expect(result.content[0].text).toContain('Database Per Service'); expect(result.content[0].text).toContain('Testing**: Staging-specific configurations'); }); }); describe('output structure validation', () => { it('should always return proper content structure', async () => { const mockAdrs = [ { title: 'Structure Test', filename: 'ADR-019-structure.md', status: 'Accepted', content: 'Testing output structure consistency.', date: '2024-01-01', path: '/test/ADR-019-structure.md', }, ]; ( discoverAdrsInDirectory as jest.MockedFunction<typeof discoverAdrsInDirectory> ).mockResolvedValue({ adrs: mockAdrs, summary: { byStatus: { Accepted: 1 }, byCategory: {} }, directory: 'docs/adrs', totalAdrs: 1, recommendations: [], } as any); const result = await generateDeploymentGuidance({}); // Verify structure expect(result).toHaveProperty('content'); expect(Array.isArray(result.content)).toBe(true); expect(result.content).toHaveLength(1); expect(result.content[0]).toHaveProperty('type', 'text'); expect(result.content[0]).toHaveProperty('text'); expect(typeof result.content[0].text).toBe('string'); expect(result.content[0].text.length).toBeGreaterThan(0); }); it('should include all required sections in guidance', async () => { const mockAdrs = [ { title: 'Complete Guidance Test', filename: 'ADR-020-complete.md', status: 'Accepted', content: 'Testing that all required sections are included in the guidance.', date: '2024-01-01', path: '/test/ADR-020-complete.md', }, ]; ( discoverAdrsInDirectory as jest.MockedFunction<typeof discoverAdrsInDirectory> ).mockResolvedValue({ adrs: mockAdrs, summary: { byStatus: { Accepted: 1 }, byCategory: {} }, directory: 'docs/adrs', totalAdrs: 1, recommendations: [], } as any); const result = await generateDeploymentGuidance({}); const content = result.content[0].text; // Verify required sections expect(content).toContain('Deployment Guidance Generation'); expect(content).toContain('Analysis Complete'); expect(content).toContain('AI Analysis Prompt'); expect(content).toContain('Instructions'); expect(content).toContain('Expected Output'); expect(content).toContain('ADR Sources'); expect(content).toContain('Prerequisites'); expect(content).toContain('Infrastructure Setup'); expect(content).toContain('Database Setup'); expect(content).toContain('Application Deployment'); expect(content).toContain('Health Checks & Verification'); expect(content).toContain('Troubleshooting'); }); }); }); });

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/mcp-adr-analysis-server'

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