UNPKG

deepsource-mcp-server

Version:
260 lines (203 loc) 9.3 kB
/** * @fileoverview Tests for repository factory */ import { describe, it, expect, beforeEach } from 'vitest'; import { RepositoryFactory, createRepositoryFactory, createRepositories, } from '../repository.factory.js'; // Mock logger vi.mock('../../../utils/logging/logger.js', () => ({ createLogger: vi.fn(() => ({ debug: vi.fn(), info: vi.fn(), warn: vi.fn(), error: vi.fn(), })), })); describe('RepositoryFactory', () => { const mockConfig = { apiKey: 'test-api-key', baseUrl: 'https://test.deepsource.io', }; beforeEach(() => { vi.clearAllMocks(); }); describe('constructor', () => { it('should create factory with required config', () => { const factory = new RepositoryFactory({ apiKey: 'test-key' }); expect(factory).toBeInstanceOf(RepositoryFactory); expect(factory.getConfig()).toEqual({ apiKey: 'test-key' }); }); it('should create factory with full config', () => { const factory = new RepositoryFactory(mockConfig); expect(factory).toBeInstanceOf(RepositoryFactory); expect(factory.getConfig()).toEqual(mockConfig); }); }); describe('createRepositories', () => { it('should create all repository instances', () => { const factory = new RepositoryFactory(mockConfig); const repositories = factory.createRepositories(); expect(repositories).toHaveProperty('projectRepository'); expect(repositories).toHaveProperty('analysisRunRepository'); expect(repositories).toHaveProperty('qualityMetricsRepository'); expect(repositories).toHaveProperty('complianceReportRepository'); // Verify all repositories are defined expect(repositories.projectRepository).toBeDefined(); expect(repositories.analysisRunRepository).toBeDefined(); expect(repositories.qualityMetricsRepository).toBeDefined(); expect(repositories.complianceReportRepository).toBeDefined(); }); it('should return cached instances on subsequent calls', () => { const factory = new RepositoryFactory(mockConfig); const firstCall = factory.createRepositories(); const secondCall = factory.createRepositories(); // Should return the same object reference expect(firstCall).toBe(secondCall); }); it('should create new instances after cache clear', () => { const factory = new RepositoryFactory(mockConfig); const firstCall = factory.createRepositories(); factory.clearCache(); const secondCall = factory.createRepositories(); // Should return different object references expect(firstCall).not.toBe(secondCall); }); }); describe('individual repository creation methods', () => { it('should create project repository', () => { const factory = new RepositoryFactory(mockConfig); const repository = factory.createProjectRepository(); expect(repository).toBeDefined(); expect(repository).toHaveProperty('findByKey'); }); it('should create analysis run repository', () => { const factory = new RepositoryFactory(mockConfig); const repository = factory.createAnalysisRunRepository(); expect(repository).toBeDefined(); expect(repository).toHaveProperty('findById'); }); it('should create quality metrics repository', () => { const factory = new RepositoryFactory(mockConfig); const repository = factory.createQualityMetricsRepository(); expect(repository).toBeDefined(); expect(repository).toHaveProperty('findByProjectAndMetric'); }); it('should create compliance report repository', () => { const factory = new RepositoryFactory(mockConfig); const repository = factory.createComplianceReportRepository(); expect(repository).toBeDefined(); expect(repository).toHaveProperty('findByProjectAndType'); }); }); describe('clearCache', () => { it('should clear cached instances', () => { const factory = new RepositoryFactory(mockConfig); // Create and cache instances const firstRepos = factory.createRepositories(); // Clear cache factory.clearCache(); // Create new instances const secondRepos = factory.createRepositories(); // Should be different instances expect(firstRepos).not.toBe(secondRepos); }); it('should allow multiple cache clears', () => { const factory = new RepositoryFactory(mockConfig); factory.createRepositories(); factory.clearCache(); factory.clearCache(); // Should not throw const repos = factory.createRepositories(); expect(repos).toBeDefined(); }); }); describe('getConfig', () => { it('should return a copy of the configuration', () => { const factory = new RepositoryFactory(mockConfig); const config = factory.getConfig(); expect(config).toEqual(mockConfig); expect(config).not.toBe(mockConfig); // Should be a copy // Verify it's a defensive copy config.apiKey = 'modified'; expect(factory.getConfig().apiKey).toBe('test-api-key'); }); it('should preserve optional fields', () => { const configWithOptional = { apiKey: 'test-key', baseUrl: 'https://custom.url', }; const factory = new RepositoryFactory(configWithOptional); const config = factory.getConfig(); expect(config).toEqual(configWithOptional); }); }); describe('convenience functions', () => { it('createRepositoryFactory should create a factory instance', () => { const factory = createRepositoryFactory(mockConfig); expect(factory).toBeInstanceOf(RepositoryFactory); expect(factory.getConfig()).toEqual(mockConfig); }); it('createRepositories should create all repositories immediately', () => { const repositories = createRepositories(mockConfig); expect(repositories).toHaveProperty('projectRepository'); expect(repositories).toHaveProperty('analysisRunRepository'); expect(repositories).toHaveProperty('qualityMetricsRepository'); expect(repositories).toHaveProperty('complianceReportRepository'); // Verify all are defined expect(repositories.projectRepository).toBeDefined(); expect(repositories.analysisRunRepository).toBeDefined(); expect(repositories.qualityMetricsRepository).toBeDefined(); expect(repositories.complianceReportRepository).toBeDefined(); }); }); describe('edge cases', () => { it('should handle missing baseUrl in config', () => { const minimalConfig = { apiKey: 'test-key' }; const factory = new RepositoryFactory(minimalConfig); const repositories = factory.createRepositories(); expect(repositories).toBeDefined(); expect(factory.getConfig()).toEqual(minimalConfig); }); it('should create independent instances for different factories', () => { const factory1 = new RepositoryFactory({ apiKey: 'key1' }); const factory2 = new RepositoryFactory({ apiKey: 'key2' }); const repos1 = factory1.createRepositories(); const repos2 = factory2.createRepositories(); // Should be different instances expect(repos1).not.toBe(repos2); // Should have different configurations expect(factory1.getConfig().apiKey).toBe('key1'); expect(factory2.getConfig().apiKey).toBe('key2'); }); it('should propagate errors when apiKey is invalid', () => { const factory = new RepositoryFactory({ apiKey: '' }); // Should throw when trying to create repositories with empty API key expect(() => factory.createRepositories()).toThrow('DeepSource API key is required'); }); }); describe('repository interface compliance', () => { it('should create repositories that implement required methods', () => { const factory = new RepositoryFactory(mockConfig); const repositories = factory.createRepositories(); // Project repository interface check expect(typeof repositories.projectRepository.findByKey).toBe('function'); expect(typeof repositories.projectRepository.findAll).toBe('function'); expect(typeof repositories.projectRepository.save).toBe('function'); expect(typeof repositories.projectRepository.delete).toBe('function'); // AnalysisRun repository interface check expect(typeof repositories.analysisRunRepository.findById).toBe('function'); expect(typeof repositories.analysisRunRepository.findByProject).toBe('function'); expect(typeof repositories.analysisRunRepository.findByCommit).toBe('function'); // QualityMetrics repository interface check expect(typeof repositories.qualityMetricsRepository.findById).toBe('function'); expect(typeof repositories.qualityMetricsRepository.findByProject).toBe('function'); expect(typeof repositories.qualityMetricsRepository.findByProjectAndMetric).toBe('function'); // ComplianceReport repository interface check expect(typeof repositories.complianceReportRepository.findById).toBe('function'); expect(typeof repositories.complianceReportRepository.findByProjectAndType).toBe('function'); expect(typeof repositories.complianceReportRepository.findLatest).toBe('function'); }); }); });