Skip to main content
Glama
exact-search-channel-simplified.test.ts4.26 kB
/** * ExactSearchChannel - Simplified Tests * Tests for the current FULLTEXT implementation */ import { describe, it, expect, beforeEach, vi } from 'vitest'; import { ExactSearchChannel } from '../../../../src/infrastructure/services/search/exact-search-channel'; describe('ExactSearchChannel - Current Implementation Tests', () => { let channel: ExactSearchChannel; let mockSession: any; beforeEach(() => { mockSession = { run: vi.fn() }; channel = new ExactSearchChannel(mockSession); }); describe('FULLTEXT Search Implementation', () => { it('should use FULLTEXT indexes for search', async () => { // Mock all search calls to return empty results mockSession.run.mockResolvedValue({ records: [] }); await channel.search('test query', 10); // Should call FULLTEXT search for metadata expect(mockSession.run).toHaveBeenCalledWith( expect.stringContaining("CALL db.index.fulltext.queryNodes('memory_metadata_idx'"), expect.objectContaining({ query: 'test query' }) ); // Should call FULLTEXT search for content expect(mockSession.run).toHaveBeenCalledWith( expect.stringContaining("CALL db.index.fulltext.queryNodes('observation_content_idx'"), expect.objectContaining({ query: 'test query' }) ); // Should call regular search for names expect(mockSession.run).toHaveBeenCalledWith( expect.stringContaining('WHERE toLower(m.name) CONTAINS'), expect.objectContaining({ query: 'test query' }) ); }); it('should handle memory type filtering', async () => { mockSession.run.mockResolvedValue({ records: [] }); await channel.search('test', 10, ['project', 'note']); // All calls should include memoryTypes parameter expect(mockSession.run).toHaveBeenCalledWith( expect.any(String), expect.objectContaining({ memoryTypes: ['project', 'note'] }) ); }); it('should combine results from different sources', async () => { // Mock different searches to return different results const metadataResult = { records: [{ get: vi.fn().mockImplementation((key) => { switch (key) { case 'id': return 'meta-id'; case 'name': return 'Metadata Match'; case 'metadata': return '{"test": "data"}'; default: return null; } }) }] }; const nameResult = { records: [{ get: vi.fn().mockImplementation((key) => { switch (key) { case 'id': return 'name-id'; case 'name': return 'Name Match'; case 'metadata': return '{}'; case 'exactNameMatch': return true; default: return null; } }) }] }; const emptyResult = { records: [] }; mockSession.run .mockResolvedValueOnce(metadataResult) // metadata search .mockResolvedValueOnce(emptyResult) // content search .mockResolvedValueOnce(nameResult); // name search const results = await channel.search('test', 10); expect(results).toHaveLength(2); expect(results.some(r => r.id === 'meta-id')).toBe(true); expect(results.some(r => r.id === 'name-id')).toBe(true); }); it('should handle Lucene query sanitization', async () => { mockSession.run.mockResolvedValue({ records: [] }); // Test with special Lucene characters await channel.search('test+query:special', 10); // Should sanitize the query for FULLTEXT calls expect(mockSession.run).toHaveBeenCalledWith( expect.stringContaining('CALL db.index.fulltext.queryNodes'), expect.objectContaining({ query: 'test\\+query\\:special' // Escaped special characters }) ); }); it('should handle empty results gracefully', async () => { mockSession.run.mockResolvedValue({ records: [] }); const results = await channel.search('nonexistent', 10); expect(results).toHaveLength(0); expect(Array.isArray(results)).toBe(true); }); }); });

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