Skip to main content
Glama
advanced-operations-search.test.tsβ€’8.29 kB
import { describe, it, expect, beforeEach, vi, afterEach } from 'vitest'; import { UniversalResourceType, RelationshipType, AdvancedSearchParams, RelationshipSearchParams, } from '../../../../src/handlers/tool-configs/universal/types.js'; import { setupUnitTestMocks, cleanupMocks, getMockInstances, } from './helpers/index.js'; describe('Universal Advanced Operations - Search Tests', () => { let advancedSearchConfig: any; let searchByRelationshipConfig: any; beforeEach(async () => { await setupUnitTestMocks(); // Import after mocks are set up const advancedOps = await import( '../../../../src/handlers/tool-configs/universal/advanced-operations.js' ); advancedSearchConfig = advancedOps.advancedSearchConfig; searchByRelationshipConfig = advancedOps.searchByRelationshipConfig; }); afterEach(() => { cleanupMocks(); }); describe('records_search_advanced tool', () => { it('should perform advanced search successfully', async () => { const mockResults = [ { id: { record_id: 'comp-1' }, values: { name: 'Advanced Company', industry: 'Technology', location: 'San Francisco', }, }, ]; const { mockHandlers } = getMockInstances(); mockHandlers.handleUniversalSearch.mockResolvedValue(mockResults); const params: any = { resource_type: UniversalResourceType.COMPANIES, query: 'technology', filters: [ { attribute: { slug: 'industry' }, condition: 'equals', value: 'Technology', }, ], sort_by: 'name', sort_order: 'asc', limit: 20, }; const result = await advancedSearchConfig.handler(params); expect(result).toEqual(mockResults); expect(mockHandlers.handleUniversalSearch).toHaveBeenCalledWith({ resource_type: params.resource_type, query: params.query, filters: params.filters, limit: params.limit, offset: params.offset, }); }); it('should format advanced search results with context', async () => { const mockResults = [ { id: { record_id: 'comp-1' }, values: { name: 'Tech Corp', industry: 'Technology', location: 'San Francisco', website: 'https://techcorp.com', }, }, ]; const { mockHandlers } = getMockInstances(); mockHandlers.formatResourceType.mockReturnValue('company'); const formatted = (advancedSearchConfig.formatResult as any)( mockResults, UniversalResourceType.COMPANIES ); expect(formatted).toContain('Advanced search found 1 company'); expect(formatted).toContain( '1. Tech Corp [Technology] (San Francisco) - https://techcorp.com (ID: comp-1)' ); }); it('should handle advanced search errors', async () => { const { mockHandlers } = getMockInstances(); const mockError = new Error('Filter error'); mockHandlers.handleUniversalSearch.mockRejectedValue(mockError); mockHandlers.createUniversalError.mockReturnValue( new Error('advanced search failed for companies: Filter error') ); const params: AdvancedSearchParams = { resource_type: UniversalResourceType.COMPANIES, query: 'test', }; await expect(advancedSearchConfig.handler(params)).rejects.toThrow( 'Universal records_search_advanced failed for resource type companies: Filter error' ); }); }); describe('records_search_by_relationship tool', () => { it('should search company to people relationships', async () => { const mockResults = [ { id: { record_id: 'person-1' }, values: { name: [{ value: 'John Doe' }], role: [{ value: 'CEO' }], email: [{ value: 'john@company.com' }], }, }, ]; const { mockSpecialized } = getMockInstances(); mockSpecialized.searchPeopleByCompany.mockResolvedValue(mockResults); const params: RelationshipSearchParams = { relationship_type: RelationshipType.COMPANY_TO_PEOPLE, source_id: 'comp-1', target_resource_type: UniversalResourceType.PEOPLE, limit: 10, }; const result = await searchByRelationshipConfig.handler(params); expect(result).toEqual(mockResults); expect(mockSpecialized.searchPeopleByCompany).toHaveBeenCalledWith( 'comp-1' ); }); it('should search people to company relationships', async () => { const mockResults = [ { id: { record_id: 'comp-1' }, values: { name: [{ value: 'Test Company' }], industry: [{ value: 'Technology' }], }, }, ]; const { mockSpecialized } = getMockInstances(); mockSpecialized.searchCompaniesByPeople.mockResolvedValue(mockResults); const params: RelationshipSearchParams = { relationship_type: RelationshipType.PEOPLE_TO_COMPANY, source_id: 'person-1', target_resource_type: UniversalResourceType.COMPANIES, }; const result = await searchByRelationshipConfig.handler(params); expect(result).toEqual(mockResults); expect(mockSpecialized.searchCompaniesByPeople).toHaveBeenCalledWith( 'person-1' ); }); it('should handle unsupported task relationships with helpful error', async () => { const params: RelationshipSearchParams = { relationship_type: RelationshipType.PERSON_TO_TASKS, source_id: 'person-1', target_resource_type: UniversalResourceType.TASKS, }; await expect(searchByRelationshipConfig.handler(params)).rejects.toThrow( /Task relationship search .* is not currently available/ ); }); it('should format relationship results correctly', async () => { const mockResults = [ { id: { record_id: 'person-1' }, values: { name: [{ value: 'John Doe' }], role: [{ value: 'CEO' }], email: [{ value: 'john@company.com' }], }, }, ]; const formatted = (searchByRelationshipConfig.formatResult as any)( mockResults, RelationshipType.COMPANY_TO_PEOPLE ); expect(formatted).toContain('Found 1 records for company to people'); expect(formatted).toContain( '1. John Doe (CEO) - john@company.com (ID: person-1)' ); }); }); describe('Search tool validation and edge cases', () => { it('should handle validation errors in search tools', async () => { const { mockSchemas } = getMockInstances(); // Store the original mock implementation to restore it later const originalMock = mockSchemas.validateUniversalToolParams; mockSchemas.validateUniversalToolParams.mockImplementation(() => { throw new Error('Validation failed'); }); const tools = [ { tool: advancedSearchConfig, params: { resource_type: UniversalResourceType.COMPANIES }, }, { tool: searchByRelationshipConfig, params: { relationship_type: RelationshipType.COMPANY_TO_PEOPLE, source_id: 'test', }, }, ]; for (const { tool, params } of tools) { await expect(tool.handler(params)).rejects.toThrow('Validation failed'); } // Restore the original mock behavior to not affect other tests mockSchemas.validateUniversalToolParams.mockImplementation( (operation: string, params: any) => { return params || {}; } ); }); it('should handle empty search results gracefully', async () => { const emptyResults: any[] = []; // For empty arrays, formatters should show "found 0" not "No results found" based on current implementation expect(advancedSearchConfig.formatResult(emptyResults)).toContain( 'Advanced search found 0 records:' ); expect(searchByRelationshipConfig.formatResult(emptyResults)).toContain( 'Found 0 records for' ); }); }); });

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/kesslerio/attio-mcp-server'

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