Skip to main content
Glama
vector-store.test.ts3.9 kB
/** * Vector Store Tests */ import { describe, test, expect, vi, beforeEach, afterEach } from 'vitest'; import type { VectorRecord } from './types.js'; import fs from 'fs'; // Create mock factory inside vi.mock to avoid hoisting issues vi.mock('@lancedb/lancedb', () => { const mockTable = { add: vi.fn().mockResolvedValue({}), vectorSearch: vi.fn().mockReturnValue({ limit: vi.fn().mockReturnValue({ toArray: vi.fn().mockResolvedValue([ { id: 'doc1-chunk-0', text: 'Test content', title: 'Test', url: 'http://test.com', _distance: 0.1 }, ]), }), }), countRows: vi.fn().mockResolvedValue(10), }; const mockDb = { tableNames: vi.fn().mockResolvedValue(['documents']), openTable: vi.fn().mockResolvedValue(mockTable), createTable: vi.fn().mockResolvedValue(mockTable), }; return { connect: vi.fn().mockResolvedValue(mockDb), __mockTable: mockTable, __mockDb: mockDb, }; }); describe('VectorStore', () => { let store: Awaited<ReturnType<typeof import('./vector-store.js')['VectorStore']>>['prototype']; let VectorStore: typeof import('./vector-store.js')['VectorStore']; let mockTable: ReturnType<typeof vi.fn>; const testDataDir = '/tmp/test-vector-store'; beforeEach(async () => { vi.clearAllMocks(); // Import after mocking const vectorStoreModule = await import('./vector-store.js'); VectorStore = vectorStoreModule.VectorStore; store = new VectorStore({ dataDir: testDataDir }, 1536); // Get mock references const lancedb = await import('@lancedb/lancedb'); mockTable = (lancedb as unknown as { __mockTable: typeof mockTable }).__mockTable; }); afterEach(() => { // Cleanup if (fs.existsSync(testDataDir)) { fs.rmSync(testDataDir, { recursive: true, force: true }); } }); test('should initialize store', async () => { await store.init(); const lancedb = await import('@lancedb/lancedb'); expect(lancedb.connect).toHaveBeenCalledWith(testDataDir); }); test('should save records', async () => { const records: VectorRecord[] = [ { id: 'doc1-chunk-0', vector: Array(1536).fill(0.1), text: 'Test content', title: 'Test Document', url: 'http://example.com/doc1', }, ]; const count = await store.save(records); expect(count).toBe(1); expect(mockTable.add).toHaveBeenCalledWith(records, { mode: 'overwrite' }); }); test('should return 0 for empty records', async () => { const count = await store.save([]); expect(count).toBe(0); expect(mockTable.add).not.toHaveBeenCalled(); }); test('should search for similar documents', async () => { const queryVector = Array(1536).fill(0.1); const results = await store.search(queryVector, 5); expect(results).toHaveLength(1); expect(results[0].id).toBe('doc1-chunk-0'); expect(results[0].score).toBe(0.1); }); test('should filter out init record from search results', async () => { mockTable.vectorSearch.mockReturnValueOnce({ limit: vi.fn().mockReturnValue({ toArray: vi.fn().mockResolvedValue([ { id: '__init__', text: '', title: '', url: '', _distance: 0 }, { id: 'doc1-chunk-0', text: 'Test', title: 'Test', url: 'http://test.com', _distance: 0.1 }, ]), }), }); const results = await store.search(Array(1536).fill(0.1)); expect(results).toHaveLength(1); expect(results[0].id).toBe('doc1-chunk-0'); }); test('should count rows', async () => { const count = await store.count(); expect(count).toBe(10); }); test('should clear store', async () => { await store.clear(); expect(mockTable.add).toHaveBeenCalledWith( expect.arrayContaining([ expect.objectContaining({ id: '__init__' }), ]), { mode: 'overwrite' } ); }); });

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/huiseo/outline-wiki-mcp'

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