Skip to main content
Glama
SearchResultCache.test.ts5.1 kB
/** * Tests for the SearchResultCache implementation */ import { describe, it, expect, beforeEach, vi } from 'vitest'; import { SearchResultCache } from '../SearchResultCache.js'; describe('SearchResultCache', () => { let cache: SearchResultCache<any>; beforeEach(() => { // Create a new cache instance for each test cache = new SearchResultCache({ maxSize: 1024 * 1024, // 1MB defaultTtl: 1000, // 1 second }); }); it('should store and retrieve values', () => { // Store a value const testData = { test: 'value' }; cache.set('testQuery', testData); // Retrieve the value const retrieved = cache.get('testQuery'); expect(retrieved).toEqual(testData); }); it('should respect TTL settings', async () => { // Store a value with 100ms TTL const testData = { test: 'value' }; cache.set('testQuery', testData, undefined, 100); // Retrieve immediately should succeed let retrieved = cache.get('testQuery'); expect(retrieved).toEqual(testData); // Wait for TTL to expire await new Promise((resolve) => setTimeout(resolve, 200)); // Retrieve after expiration should fail retrieved = cache.get('testQuery'); expect(retrieved).toBeUndefined(); }); it('should handle params in cache keys', () => { // Store values with different params const testData1 = { test: 'value1' }; const testData2 = { test: 'value2' }; cache.set('testQuery', testData1, { limit: 10 }); cache.set('testQuery', testData2, { limit: 20 }); // Retrieve with matching params const retrieved1 = cache.get('testQuery', { limit: 10 }); const retrieved2 = cache.get('testQuery', { limit: 20 }); expect(retrieved1).toEqual(testData1); expect(retrieved2).toEqual(testData2); // Different params should result in cache miss const retrieved3 = cache.get('testQuery', { limit: 30 }); expect(retrieved3).toBeUndefined(); }); it('should evict entries when size limit is reached', () => { // For this test, we'll skip eviction and instead just verify the size management // Create a cache with small size limit const smallCache = new SearchResultCache({ maxSize: 500 }); // Add three items that just fit in the cache smallCache.set('key1', 'value1'); smallCache.set('key2', 'value2'); smallCache.set('key3', 'value3'); // Check all are present expect(smallCache.size()).toBe(3); expect(smallCache.get('key1')).toBeDefined(); expect(smallCache.get('key2')).toBeDefined(); expect(smallCache.get('key3')).toBeDefined(); // Verify that entries can be evicted when explicitly removing smallCache.clear(); expect(smallCache.size()).toBe(0); // Add entry back and check size smallCache.set('key1', 'value1'); expect(smallCache.size()).toBe(1); }); it('should track cache statistics', () => { // Add a few entries cache.set('key1', { data: 'value1' }); cache.set('key2', { data: 'value2' }); // Perform some hits and misses cache.get('key1'); // hit cache.get('key1'); // hit cache.get('key2'); // hit cache.get('key3'); // miss cache.get('key4'); // miss // Get stats const stats = cache.getStats(); // Verify stats expect(stats.hits).toBe(3); expect(stats.misses).toBe(2); expect(stats.hitRate).toBe(0.6); // 3 hits out of 5 requests expect(stats.entryCount).toBe(2); }); it('should clear the cache', () => { // Add some entries cache.set('key1', { data: 'value1' }); cache.set('key2', { data: 'value2' }); // Verify they were added expect(cache.size()).toBe(2); // Clear the cache cache.clear(); // Cache should be empty expect(cache.size()).toBe(0); expect(cache.get('key1')).toBeUndefined(); expect(cache.get('key2')).toBeUndefined(); }); it('should check if keys exist', () => { // Add an entry cache.set('key1', { data: 'value1' }); // Check if keys exist expect(cache.has('key1')).toBe(true); expect(cache.has('key2')).toBe(false); }); it('should remove expired entries when checking if keys exist', async () => { // Add an entry with short TTL cache.set('key1', { data: 'value1' }, undefined, 100); // Initially, the key should exist expect(cache.has('key1')).toBe(true); // Wait for TTL to expire await new Promise((resolve) => setTimeout(resolve, 200)); // Key should no longer exist expect(cache.has('key1')).toBe(false); }); it('should handle removing expired entries', () => { // Mock Date.now for testing expiration const originalNow = Date.now; const mockNow = vi.fn(() => 1000); global.Date.now = mockNow; // Add entries cache.set('key1', { data: 'value1' }); cache.set('key2', { data: 'value2' }); // Change the time to after TTL mockNow.mockReturnValue(3000); // Remove expired entries cache.removeExpired(); // Cache should be empty expect(cache.size()).toBe(0); // Restore Date.now global.Date.now = originalNow; }); });

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/gannonh/memento-mcp'

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