Skip to main content
Glama

DollhouseMCP

by DollhouseMCP
fuzzy-matching.test.tsβ€’7.21 kB
/** * Integration tests for fuzzy matching in portfolio_element_manager * Ensures that the fuzzy matching capability works as advertised */ import { describe, it, expect, beforeEach, jest } from '@jest/globals'; describe('Fuzzy Matching Integration Tests', () => { describe('portfolio_element_manager fuzzy matching', () => { it('should find "Verbose-Victorian-Scholar" when searching for "Victorian Scholar"', () => { // Test data setup const elements = [ { name: 'Verbose-Victorian-Scholar', type: 'personas' }, { name: 'Creative-Writer', type: 'personas' }, { name: 'Debug-Detective', type: 'personas' } ]; // Fuzzy matching function (simplified for testing) const fuzzyMatch = (search: string, target: string): boolean => { const normalize = (s: string) => s.toLowerCase().replaceAll(/[-_\s]/g, ''); return normalize(target).includes(normalize(search)); }; // Test various search patterns const searches = [ 'Victorian Scholar', 'verbose victorian', 'victorian', 'VICTORIAN SCHOLAR', 'verbose-victorian-scholar' ]; searches.forEach(search => { const found = elements.find(e => fuzzyMatch(search, e.name)); expect(found).toBeDefined(); expect(found?.name).toBe('Verbose-Victorian-Scholar'); }); }); it('should handle partial matches correctly', () => { const elements = [ { name: 'Super-Creative-Writer-Pro', type: 'personas' }, { name: 'Creative-Writer', type: 'personas' }, { name: 'Technical-Writer', type: 'personas' } ]; const fuzzyMatch = (search: string, target: string): boolean => { const normalize = (s: string) => s.toLowerCase().replaceAll(/[-_\s]/g, ''); return normalize(target).includes(normalize(search)); }; // Search for "creative writer" const matches = elements.filter(e => fuzzyMatch('creative writer', e.name)); // Should find both elements containing "creative writer" expect(matches).toHaveLength(2); expect(matches.map(m => m.name)).toContain('Super-Creative-Writer-Pro'); expect(matches.map(m => m.name)).toContain('Creative-Writer'); }); it('should be case-insensitive', () => { const elements = [ { name: 'Debug-Detective', type: 'personas' } ]; const fuzzyMatch = (search: string, target: string): boolean => { const normalize = (s: string) => s.toLowerCase().replaceAll(/[-_\s]/g, ''); return normalize(target).includes(normalize(search)); }; const testCases = [ 'debug detective', 'Debug Detective', 'DEBUG DETECTIVE', 'DeBuG dEtEcTiVe' ]; testCases.forEach(search => { const found = elements.find(e => fuzzyMatch(search, e.name)); expect(found).toBeDefined(); expect(found?.name).toBe('Debug-Detective'); }); }); it('should handle special characters in search', () => { const elements = [ { name: 'Code-Review-Expert', type: 'skills' } ]; const fuzzyMatch = (search: string, target: string): boolean => { const normalize = (s: string) => s.toLowerCase().replaceAll(/[-_\s]/g, ''); return normalize(target).includes(normalize(search)); }; const searches = [ 'code-review', 'code_review', 'code review', 'code.review', // Should still work after normalization 'code/review' // Should still work after normalization ]; searches.forEach(search => { const normalizedSearch = search.toLowerCase().replaceAll(/[-_\s.\/]/g, ''); const found = elements.find(e => { const normalizedTarget = e.name.toLowerCase().replaceAll(/[-_\s]/g, ''); return normalizedTarget.includes(normalizedSearch); }); expect(found).toBeDefined(); expect(found?.name).toBe('Code-Review-Expert'); }); }); it('should return no results for non-matching searches', () => { const elements = [ { name: 'Creative-Writer', type: 'personas' }, { name: 'Debug-Detective', type: 'personas' } ]; const fuzzyMatch = (search: string, target: string): boolean => { const normalize = (s: string) => s.toLowerCase().replaceAll(/[-_\s]/g, ''); return normalize(target).includes(normalize(search)); }; const searches = [ 'nonexistent', 'xyz123', 'quantum physicist' ]; searches.forEach(search => { const found = elements.find(e => fuzzyMatch(search, e.name)); expect(found).toBeUndefined(); }); }); it('should prioritize exact matches over fuzzy matches', () => { const elements = [ { name: 'Writer', type: 'personas' }, { name: 'Creative-Writer', type: 'personas' }, { name: 'Technical-Writer-Pro', type: 'personas' } ]; // More sophisticated matching with priority const findBestMatch = (search: string, items: typeof elements) => { const normalize = (s: string) => s.toLowerCase().replaceAll(/[-_\s]/g, ''); const searchNorm = normalize(search); // First try exact match const exact = items.find(e => normalize(e.name) === searchNorm); if (exact) return exact; // Then try fuzzy match return items.find(e => normalize(e.name).includes(searchNorm)); }; // Should find exact "Writer" not "Creative-Writer" const result = findBestMatch('writer', elements); expect(result?.name).toBe('Writer'); }); }); describe('Edge cases', () => { it('should handle empty search strings gracefully', () => { const elements = [ { name: 'Test-Element', type: 'personas' } ]; const fuzzyMatch = (search: string, target: string): boolean => { if (!search || !target) return false; const normalize = (s: string) => s.toLowerCase().replaceAll(/[-_\s]/g, ''); return normalize(target).includes(normalize(search)); }; const found = elements.find(e => fuzzyMatch('', e.name)); expect(found).toBeUndefined(); }); it('should handle unicode characters', () => { const elements = [ { name: 'CafΓ©-Writer', type: 'personas' }, { name: 'NaΓ―ve-Assistant', type: 'personas' } ]; const fuzzyMatch = (search: string, target: string): boolean => { const normalize = (s: string) => s.toLowerCase().replaceAll(/[-_\s]/g, ''); return normalize(target).includes(normalize(search)); }; // Search with accented characters let found = elements.find(e => fuzzyMatch('cafΓ©', e.name)); expect(found?.name).toBe('CafΓ©-Writer'); // Search without accents (depending on normalization strategy) found = elements.find(e => fuzzyMatch('naive', e.name)); // This might not match depending on normalization - that's ok // The important thing is it doesn't crash expect(found?.name === 'NaΓ―ve-Assistant' || found === undefined).toBe(true); }); }); });

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/DollhouseMCP/DollhouseMCP'

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