mcp-local-dev

by txbm
import { jest, describe, it, expect, beforeEach, afterEach } from '@jest/globals'; import { SummarizationService } from '../../services/summarization.js'; import { SummarizationModel, ModelConfig } from '../../types/models.js'; class MockModel implements SummarizationModel { private initialized = false; private shouldFail: boolean; constructor(shouldFail = false) { this.shouldFail = shouldFail; } async initialize(config: ModelConfig): Promise<void> { if (this.shouldFail) { throw new Error('Mock initialization failed'); } this.initialized = true; } async summarize(content: string, type: string): Promise<string> { if (!this.initialized) { throw new Error('Model not initialized'); } if (this.shouldFail) { throw new Error('Mock summarization failed'); } return `Summary of ${type}: ${content.substring(0, 50)}...`; } async cleanup(): Promise<void> { this.initialized = false; } } describe('SummarizationService', () => { let service: SummarizationService; let model: MockModel; beforeEach(() => { model = new MockModel(); service = new SummarizationService(model, { model: { apiKey: 'test-key' }, charThreshold: 100, cacheMaxAge: 1000 // 1 second for testing }); }); afterEach(async () => { await service.cleanup(); }); describe('initialization', () => { it('should initialize successfully', async () => { await expect(service.initialize()).resolves.toBeUndefined(); }); it('should handle initialization failure', async () => { const failingModel = new MockModel(true); const failingService = new SummarizationService(failingModel, { model: { apiKey: 'test-key' } }); await expect(failingService.initialize()).rejects.toThrow('Mock initialization failed'); await failingService.cleanup(); }); }); describe('content summarization', () => { beforeEach(async () => { await service.initialize(); }); it('should return original content when below threshold', async () => { const content = 'Short content'; const result = await service.maybeSummarize(content, 'text'); expect(result).toEqual({ text: content, isSummarized: false }); }); it('should summarize content when above threshold', async () => { const content = 'A'.repeat(150); // Content longer than threshold const result = await service.maybeSummarize(content, 'text'); expect(result.isSummarized).toBe(true); expect(result.id).toBeDefined(); expect(result.text).toMatch(/^Summary of text:/); }); it('should handle summarization failure', async () => { const failModel = new MockModel(); const failService = new SummarizationService(failModel, { model: { apiKey: 'test-key' }, charThreshold: 100 }); await failService.initialize(); const mockSummarize = jest.spyOn(failModel, 'summarize') .mockRejectedValueOnce(new Error('Mock summarization failed')); try { const content = 'A'.repeat(150); await expect(failService.maybeSummarize(content, 'text')) .rejects.toThrow('Mock summarization failed'); } finally { mockSummarize.mockRestore(); await failService.cleanup(); } }); }); describe('content cache', () => { beforeEach(async () => { jest.useFakeTimers(); await service.initialize(); }); afterEach(async () => { jest.runOnlyPendingTimers(); jest.useRealTimers(); }); it('should store and retrieve content', async () => { const content = 'A'.repeat(150); const result = await service.maybeSummarize(content, 'text'); expect(result.id).toBeDefined(); const retrieved = service.getFullContent(result.id!); expect(retrieved).toBe(content); }); it('should return null for non-existent content', () => { const retrieved = service.getFullContent('non-existent-id'); expect(retrieved).toBeNull(); }); it('should clean up expired cache entries', async () => { const content = 'A'.repeat(150); const result = await service.maybeSummarize(content, 'text'); // Use runAllTimers to handle any pending promises await jest.runAllTimersAsync(); // Advance time past cache expiration jest.advanceTimersByTime(1100); await jest.runAllTimersAsync(); const retrieved = service.getFullContent(result.id!); expect(retrieved).toBeNull(); }); it('should throw error for invalid cache age configuration', async () => { await expect(() => new SummarizationService(model, { model: { apiKey: 'test-key' }, cacheMaxAge: -1 })).toThrow('Cache max age must be a positive number'); await expect(() => new SummarizationService(model, { model: { apiKey: 'test-key' }, cacheMaxAge: 0 })).toThrow('Cache max age must be a positive number'); }); }); describe('cleanup', () => { it('should clean up resources', async () => { await service.initialize(); const content = 'A'.repeat(150); const result = await service.maybeSummarize(content, 'text'); await service.cleanup(); // Cache should be cleared const retrieved = service.getFullContent(result.id!); expect(retrieved).toBeNull(); }); }); });