Skip to main content
Glama
vector-search-channel.test.ts.broken5.62 kB
/** * Vector Search Channel Tests * Single responsibility: Test vector similarity operations * Coverage target: 9.16% → 75% */ import { describe, it, expect, beforeEach, vi } from 'vitest'; import { Session } from 'neo4j-driver'; import { VectorSearchChannel } from '../../../../src/infrastructure/services/search/vector-search-channel'; // Mock dependencies vi.mock('../../../../src/infrastructure/utilities', () => ({ calculateEmbedding: vi.fn().mockResolvedValue([0.1, 0.2, 0.3]) })); describe('VectorSearchChannel - Semantic Search Engine', () => { let channel: VectorSearchChannel; let mockSession: Session; beforeEach(() => { mockSession = { run: vi.fn().mockResolvedValue({ records: [] }), close: vi.fn().mockResolvedValue(undefined) } as unknown as Session; channel = new VectorSearchChannel(mockSession); }); describe('GDS Support Detection', () => { it('should detect GDS availability', async () => { // Mock GDS success (mockSession.run as any).mockResolvedValueOnce({ records: [] }); const result = await channel.search('test', 10, 0.5); expect(mockSession.run).toHaveBeenCalledWith( expect.stringContaining('gds.similarity.cosine'), expect.any(Object) ); }); it('should fallback to in-memory when GDS unavailable', async () => { // Mock GDS failure, then return memory data (mockSession.run as any) .mockRejectedValueOnce(new Error('GDS not available')) .mockResolvedValueOnce({ records: [{ get: vi.fn().mockImplementation((key) => { if (key === 'id') return 'test-id'; if (key === 'nameEmbedding') return [0.2, 0.3, 0.4]; return []; }) }] }); const results = await channel.search('test', 10, 0.5); expect(results).toBeDefined(); }); }); describe('Memory Type Filtering', () => { it('should include memory type filter in GDS query', async () => { (mockSession.run as any).mockResolvedValue({ records: [] }); await channel.search('test', 10, 0.5, ['project', 'task']); expect(mockSession.run).toHaveBeenCalledWith( expect.stringContaining('WHERE m.memoryType IN $memoryTypes'), expect.objectContaining({ memoryTypes: ['project', 'task'] }) ); }); it('should include memory type filter in in-memory query', async () => { // Force in-memory path (mockSession.run as any) .mockRejectedValueOnce(new Error('GDS not available')) .mockResolvedValueOnce({ records: [] }); await channel.search('test', 10, 0.5, ['project']); expect(mockSession.run).toHaveBeenLastCalledWith( expect.stringContaining('WHERE m.memoryType IN $memoryTypes'), expect.objectContaining({ memoryTypes: ['project'] }) ); }); }); describe('Cosine Similarity Calculation', () => { it('should calculate similarity between valid vectors', () => { const vector1 = [1, 0, 0]; const vector2 = [0, 1, 0]; // Access private method for testing const similarity = (channel as any).cosineSimilarity(vector1, vector2); expect(similarity).toBe(0); // Orthogonal vectors }); it('should handle identical vectors', () => { const vector1 = [1, 1, 1]; const vector2 = [1, 1, 1]; const similarity = (channel as any).cosineSimilarity(vector1, vector2); expect(similarity).toBe(1); // Identical vectors }); it('should handle invalid vectors gracefully', () => { const similarity1 = (channel as any).cosineSimilarity([], [1, 2]); const similarity2 = (channel as any).cosineSimilarity(null, [1, 2]); const similarity3 = (channel as any).cosineSimilarity([NaN, NaN], [1, 2]); expect(similarity1).toBe(0); expect(similarity2).toBe(0); expect(similarity3).toBe(0); // All NaN values should result in 0 magnitude }); }); describe('Threshold Filtering', () => { it('should filter results by similarity threshold', async () => { // Force in-memory calculation with test data (mockSession.run as any) .mockRejectedValueOnce(new Error('GDS not available')) .mockResolvedValueOnce({ records: [ { get: vi.fn().mockImplementation((key) => { if (key === 'id') return 'high-sim'; if (key === 'nameEmbedding') return [0.1, 0.2, 0.3]; // Will have high similarity return []; }) }, { get: vi.fn().mockImplementation((key) => { if (key === 'id') return 'low-sim'; if (key === 'nameEmbedding') return [1, 0, 0]; // Will have low similarity return []; }) } ] }); const results = await channel.search('test', 10, 0.8); // High threshold // Should filter out low similarity results expect(results.length).toBeLessThanOrEqual(1); }); }); describe('Limit Enforcement', () => { it('should respect result limit in GDS query', async () => { (mockSession.run as any).mockResolvedValue({ records: [] }); await channel.search('test', 5, 0.1); expect(mockSession.run).toHaveBeenCalledWith( expect.any(String), expect.objectContaining({ limit: expect.objectContaining({ toNumber: expect.any(Function) }) }) ); }); }); });

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/sylweriusz/mcp-neo4j-memory-server'

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