Skip to main content
Glama
integration.test.jsβ€’14.8 kB
"use strict"; /** * Integration Tests * * @semantic-intent End-to-end tests verifying all layers work together * Tests the complete dependency graph from presentation to infrastructure */ Object.defineProperty(exports, "__esModule", { value: true }); const vitest_1 = require("vitest"); const MCPServer_1 = require("./presentation/mcp/MCPServer"); const AnalyzeSchemaUseCase_1 = require("./application/use-cases/AnalyzeSchemaUseCase"); const GetRelationshipsUseCase_1 = require("./application/use-cases/GetRelationshipsUseCase"); const ValidateSchemaUseCase_1 = require("./application/use-cases/ValidateSchemaUseCase"); const SuggestOptimizationsUseCase_1 = require("./application/use-cases/SuggestOptimizationsUseCase"); const SchemaAnalyzer_1 = require("./domain/services/SchemaAnalyzer"); const RelationshipAnalyzer_1 = require("./domain/services/RelationshipAnalyzer"); const OptimizationService_1 = require("./domain/services/OptimizationService"); const DatabaseConfig_1 = require("./infrastructure/config/DatabaseConfig"); const Environment_1 = require("./domain/value-objects/Environment"); const DatabaseSchema_1 = require("./domain/entities/DatabaseSchema"); const TableInfo_1 = require("./domain/entities/TableInfo"); (0, vitest_1.describe)('Integration Tests', () => { let mcpServer; let mockRepository; let mockCache; let databaseConfig; (0, vitest_1.beforeEach)(() => { // Mock infrastructure adapters (to avoid real HTTP calls) mockRepository = { fetchDatabaseSchema: vitest_1.vi.fn().mockResolvedValue({ name: 'test_db', environment: Environment_1.Environment.DEVELOPMENT, tables: [], fetchedAt: new Date(), }), fetchTableDetails: vitest_1.vi.fn(), fetchIndexInformation: vitest_1.vi.fn(), executeSQLQuery: vitest_1.vi.fn(), }; mockCache = { get: vitest_1.vi.fn().mockResolvedValue(undefined), set: vitest_1.vi.fn().mockResolvedValue(undefined), delete: vitest_1.vi.fn(), clear: vitest_1.vi.fn(), has: vitest_1.vi.fn(), }; const databases = new Map(); databases.set(Environment_1.Environment.DEVELOPMENT, { id: 'dev-db-123', name: 'test_dev' }); databases.set(Environment_1.Environment.STAGING, { id: 'staging-db-456', name: 'test_staging' }); databases.set(Environment_1.Environment.PRODUCTION, { id: 'prod-db-789', name: 'test_prod' }); databaseConfig = new DatabaseConfig_1.DatabaseConfig(databases); // Domain layer const schemaAnalyzer = new SchemaAnalyzer_1.SchemaAnalyzer(); const relationshipAnalyzer = new RelationshipAnalyzer_1.RelationshipAnalyzer(); const optimizationService = new OptimizationService_1.OptimizationService(); // Application layer const analyzeSchemaUseCase = new AnalyzeSchemaUseCase_1.AnalyzeSchemaUseCase(mockRepository, schemaAnalyzer, databaseConfig, mockCache); const getRelationshipsUseCase = new GetRelationshipsUseCase_1.GetRelationshipsUseCase(mockRepository, relationshipAnalyzer, databaseConfig, mockCache); const validateSchemaUseCase = new ValidateSchemaUseCase_1.ValidateSchemaUseCase(mockRepository, schemaAnalyzer, databaseConfig, mockCache); const suggestOptimizationsUseCase = new SuggestOptimizationsUseCase_1.SuggestOptimizationsUseCase(mockRepository, optimizationService, relationshipAnalyzer, databaseConfig, mockCache); // Presentation layer mcpServer = new MCPServer_1.D1DatabaseMCPServer(analyzeSchemaUseCase, getRelationshipsUseCase, validateSchemaUseCase, suggestOptimizationsUseCase); vitest_1.vi.clearAllMocks(); }); (0, vitest_1.describe)('Full Stack Integration', () => { (0, vitest_1.it)('should wire all dependencies correctly', () => { (0, vitest_1.expect)(mcpServer).toBeDefined(); (0, vitest_1.expect)(Object.isFrozen(mcpServer)).toBe(true); }); (0, vitest_1.it)('should successfully execute analyze schema through all layers', async () => { // Mock repository response vitest_1.vi.spyOn(mockRepository, 'fetchDatabaseSchema').mockResolvedValue({ name: 'test_dev', environment: Environment_1.Environment.DEVELOPMENT, tables: [], fetchedAt: new Date(), }); const result = await mcpServer.handleAnalyzeSchema({ environment: 'development', includeSamples: false, }); (0, vitest_1.expect)(result.content).toHaveLength(1); (0, vitest_1.expect)(result.content[0].type).toBe('text'); const parsed = JSON.parse(result.content[0].text); (0, vitest_1.expect)(parsed.databaseName).toBe('test_dev'); (0, vitest_1.expect)(parsed.environment).toBe('development'); }); (0, vitest_1.it)('should successfully execute get relationships through all layers', async () => { vitest_1.vi.spyOn(mockRepository, 'fetchDatabaseSchema').mockResolvedValue({ name: 'test_dev', environment: Environment_1.Environment.DEVELOPMENT, tables: [], fetchedAt: new Date(), }); const result = await mcpServer.handleGetRelationships({ environment: 'development', }); (0, vitest_1.expect)(result.content).toHaveLength(1); const parsed = JSON.parse(result.content[0].text); (0, vitest_1.expect)(parsed.databaseName).toBe('test_dev'); (0, vitest_1.expect)(parsed.relationships).toBeDefined(); }); (0, vitest_1.it)('should successfully execute validate schema through all layers', async () => { vitest_1.vi.spyOn(mockRepository, 'fetchDatabaseSchema').mockResolvedValue({ name: 'test_dev', environment: Environment_1.Environment.DEVELOPMENT, tables: [], fetchedAt: new Date(), }); const result = await mcpServer.handleValidateSchema({ environment: 'development', }); (0, vitest_1.expect)(result.content).toHaveLength(1); const parsed = JSON.parse(result.content[0].text); (0, vitest_1.expect)(parsed.isValid).toBeDefined(); (0, vitest_1.expect)(parsed.issues).toBeDefined(); }); (0, vitest_1.it)('should successfully execute suggest optimizations through all layers', async () => { vitest_1.vi.spyOn(mockRepository, 'fetchDatabaseSchema').mockResolvedValue({ name: 'test_dev', environment: Environment_1.Environment.DEVELOPMENT, tables: [], fetchedAt: new Date(), }); const result = await mcpServer.handleSuggestOptimizations({ environment: 'development', }); (0, vitest_1.expect)(result.content).toHaveLength(1); const parsed = JSON.parse(result.content[0].text); (0, vitest_1.expect)(parsed.optimizations).toBeDefined(); (0, vitest_1.expect)(parsed.optimizationCount).toBeDefined(); }); }); (0, vitest_1.describe)('Cache Integration', () => { (0, vitest_1.it)('should cache schema across multiple use case calls', async () => { const mockSchema = { name: 'test_dev', environment: Environment_1.Environment.DEVELOPMENT, tables: [], fetchedAt: new Date(), }; // Set up cache mock to return undefined first time, then cached value let cacheValue = undefined; mockCache.get.mockImplementation(async () => cacheValue); mockCache.set.mockImplementation(async (key, value) => { cacheValue = value; }); const fetchSpy = vitest_1.vi.spyOn(mockRepository, 'fetchDatabaseSchema').mockResolvedValue(mockSchema); // First call - should fetch await mcpServer.handleAnalyzeSchema({ environment: 'development', includeSamples: false, }); (0, vitest_1.expect)(fetchSpy).toHaveBeenCalledTimes(1); // Second call - should use cache await mcpServer.handleAnalyzeSchema({ environment: 'development', includeSamples: false, }); // Should still be 1 (cached) (0, vitest_1.expect)(fetchSpy).toHaveBeenCalledTimes(1); }); (0, vitest_1.it)('should share cache between different use cases', async () => { const mockSchema = { name: 'test_dev', environment: Environment_1.Environment.DEVELOPMENT, tables: [], fetchedAt: new Date(), }; // Set up cache mock to simulate real caching let cacheValue = undefined; mockCache.get.mockImplementation(async () => cacheValue); mockCache.set.mockImplementation(async (key, value) => { cacheValue = value; }); const fetchSpy = vitest_1.vi.spyOn(mockRepository, 'fetchDatabaseSchema').mockResolvedValue(mockSchema); // Call analyze schema await mcpServer.handleAnalyzeSchema({ environment: 'development', includeSamples: false, }); (0, vitest_1.expect)(fetchSpy).toHaveBeenCalledTimes(1); // Call validate schema - should use same cache await mcpServer.handleValidateSchema({ environment: 'development', }); // Should still be 1 (cached) (0, vitest_1.expect)(fetchSpy).toHaveBeenCalledTimes(1); }); }); (0, vitest_1.describe)('Environment Configuration', () => { (0, vitest_1.it)('should route to correct database based on environment', async () => { const mockSchema = { name: 'test_prod', environment: Environment_1.Environment.PRODUCTION, tables: [], fetchedAt: new Date(), }; const fetchSpy = vitest_1.vi.spyOn(mockRepository, 'fetchDatabaseSchema').mockResolvedValue(mockSchema); await mcpServer.handleAnalyzeSchema({ environment: 'production', includeSamples: false, }); (0, vitest_1.expect)(fetchSpy).toHaveBeenCalledWith('prod-db-789'); }); (0, vitest_1.it)('should handle all three environments correctly', async () => { const fetchSpy = vitest_1.vi.spyOn(mockRepository, 'fetchDatabaseSchema').mockImplementation(async (dbId) => { const envMap = { 'dev-db-123': Environment_1.Environment.DEVELOPMENT, 'staging-db-456': Environment_1.Environment.STAGING, 'prod-db-789': Environment_1.Environment.PRODUCTION, }; const dummyColumn = { name: 'id', type: 'INTEGER', isPrimaryKey: true, isNullable: false, defaultValue: null }; const dummyTable = new TableInfo_1.TableInfo('test_table', 'table', [dummyColumn], [], []); return new DatabaseSchema_1.DatabaseSchema('test', envMap[dbId], [dummyTable], new Date()); }); await mcpServer.handleAnalyzeSchema({ environment: 'development', includeSamples: false }); (0, vitest_1.expect)(fetchSpy).toHaveBeenCalledWith('dev-db-123'); await mcpServer.handleAnalyzeSchema({ environment: 'staging', includeSamples: false }); (0, vitest_1.expect)(fetchSpy).toHaveBeenCalledWith('staging-db-456'); await mcpServer.handleAnalyzeSchema({ environment: 'production', includeSamples: false }); (0, vitest_1.expect)(fetchSpy).toHaveBeenCalledWith('prod-db-789'); }); }); (0, vitest_1.describe)('Error Propagation', () => { (0, vitest_1.it)('should propagate repository errors through all layers', async () => { vitest_1.vi.spyOn(mockRepository, 'fetchDatabaseSchema').mockRejectedValue(new Error('Database connection failed')); await (0, vitest_1.expect)(mcpServer.handleAnalyzeSchema({ environment: 'development', includeSamples: false, })).rejects.toThrow('Database connection failed'); }); (0, vitest_1.it)('should handle invalid environment gracefully', async () => { await (0, vitest_1.expect)(mcpServer.handleAnalyzeSchema({ environment: 'invalid', includeSamples: false, })).rejects.toThrow(); }); }); (0, vitest_1.describe)('Dependency Injection', () => { (0, vitest_1.it)('should use injected cache provider', async () => { const setSpy = vitest_1.vi.spyOn(mockCache, 'set'); const getSpy = vitest_1.vi.spyOn(mockCache, 'get'); vitest_1.vi.spyOn(mockRepository, 'fetchDatabaseSchema').mockResolvedValue({ name: 'test', environment: Environment_1.Environment.DEVELOPMENT, tables: [], fetchedAt: new Date(), }); await mcpServer.handleAnalyzeSchema({ environment: 'development', includeSamples: false, }); (0, vitest_1.expect)(getSpy).toHaveBeenCalled(); (0, vitest_1.expect)(setSpy).toHaveBeenCalled(); }); (0, vitest_1.it)('should use injected repository', async () => { const fetchSpy = vitest_1.vi.spyOn(mockRepository, 'fetchDatabaseSchema').mockResolvedValue({ name: 'test', environment: Environment_1.Environment.DEVELOPMENT, tables: [], fetchedAt: new Date(), }); await mcpServer.handleAnalyzeSchema({ environment: 'development', includeSamples: false, }); (0, vitest_1.expect)(fetchSpy).toHaveBeenCalled(); }); }); (0, vitest_1.describe)('Lifecycle', () => { (0, vitest_1.it)('should have start method', () => { (0, vitest_1.expect)(typeof mcpServer.start).toBe('function'); }); (0, vitest_1.it)('should have stop method', () => { (0, vitest_1.expect)(typeof mcpServer.stop).toBe('function'); }); }); }); //# sourceMappingURL=integration.test.js.map

Latest Blog Posts

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/semanticintent/semantic-d1-mcp'

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