Skip to main content
Glama
timeframe-api-integration.test.tsβ€’11.8 kB
/** * API integration tests for timeframe search functionality (Issue #475) * Tests that date parameters are properly passed to the Attio API calls */ import { describe, it, expect, beforeEach, vi } from 'vitest'; import { UniversalSearchService } from '../../../../src/services/UniversalSearchService.js'; import { UniversalResourceType } from '../../../../src/handlers/tool-configs/universal/types.js'; import type { UniversalSearchParams } from '../../../../src/handlers/tool-configs/universal/types.js'; // Mock external dependencies vi.mock('../../../../src/api/attio-client.js'); // Mock the search functions with vi.fn() vi.mock('../../../../src/objects/companies/index.js', () => ({ advancedSearchCompanies: vi.fn().mockResolvedValue([]), })); vi.mock('../../../../src/objects/people/index.js', () => ({ advancedSearchPeople: vi.fn().mockResolvedValue({ results: [] }), })); // Import the mocked functions to access them in tests import { advancedSearchCompanies } from '../../../../src/objects/companies/index.js'; import { advancedSearchPeople } from '../../../../src/objects/people/index.js'; // Type interfaces for test data interface FilterItem { attribute?: { slug?: string }; condition?: string; value?: unknown; } interface FiltersStructure { filters: FilterItem[]; } interface MockCall { mock: { calls: unknown[][] }; } describe.skip('Timeframe API Integration Tests - DEPRECATED', () => { // These tests are now deprecated because we force all timeframe searches // to use Query API instead of Advanced Search API for better compatibility const mockDate = new Date('2023-08-15T12:00:00.000Z'); beforeEach(() => { vi.useFakeTimers(); vi.setSystemTime(mockDate); vi.clearAllMocks(); }); afterEach(() => { vi.useRealTimers(); }); describe('Companies API Parameter Passing', () => { it('should pass date filters to advancedSearchCompanies', async () => { const params: UniversalSearchParams = { resource_type: UniversalResourceType.COMPANIES, date_from: '2023-08-01T00:00:00Z', date_to: '2023-08-15T23:59:59Z', date_field: 'created_at', }; await UniversalSearchService.searchRecords(params); // Verify that advancedSearchCompanies was called with enhanced filters expect(advancedSearchCompanies).toHaveBeenCalledTimes(1); const [filters, limit, offset] = ( advancedSearchCompanies as unknown as MockCall ).mock.calls[0]; // Verify that the filters include the date parameters const filtersData = filters as FiltersStructure; expect(filtersData).toBeDefined(); expect(filtersData.filters).toBeDefined(); expect(Array.isArray(filtersData.filters)).toBe(true); // Should contain date range filters const dateFilters = filtersData.filters.filter( (f) => f.attribute?.slug === 'created_at' ); expect(dateFilters.length).toBe(2); // Start and end date filters }); it('should pass relative timeframe filters to advancedSearchCompanies', async () => { const params: UniversalSearchParams = { resource_type: UniversalResourceType.COMPANIES, timeframe: 'last_7_days', date_field: 'updated_at', }; await UniversalSearchService.searchRecords(params); expect(advancedSearchCompanies).toHaveBeenCalledTimes(1); const [filters] = (advancedSearchCompanies as unknown as MockCall).mock .calls[0]; // Should contain timeframe filters const dateFilters = (filters as FiltersStructure).filters.filter( (f) => f.attribute?.slug === 'updated_at' ); expect(dateFilters.length).toBe(2); // Start and end date filters }); it('should merge date filters with existing filters for companies', async () => { const params: UniversalSearchParams = { resource_type: UniversalResourceType.COMPANIES, filters: { filters: [ { attribute: { slug: 'name' }, condition: 'contains', value: 'test company', }, ], }, date_from: '2023-08-01T00:00:00Z', date_to: '2023-08-15T23:59:59Z', date_field: 'created_at', }; await UniversalSearchService.searchRecords(params); expect(advancedSearchCompanies).toHaveBeenCalledTimes(1); const [filters] = (advancedSearchCompanies as unknown as MockCall).mock .calls[0]; // Should contain both original and date filters expect((filters as FiltersStructure).filters.length).toBe(3); // 1 original + 2 date filters // Verify original filter is preserved const nameFilter = (filters as FiltersStructure).filters.find( (f) => f.attribute?.slug === 'name' ); expect(nameFilter).toBeDefined(); expect(nameFilter.value).toBe('test company'); // Verify date filters are added const dateFilters = (filters as FiltersStructure).filters.filter( (f) => f.attribute?.slug === 'created_at' ); expect(dateFilters.length).toBe(2); }); }); describe('People API Parameter Passing', () => { it('should pass date filters to advancedSearchPeople', async () => { const params: UniversalSearchParams = { resource_type: UniversalResourceType.PEOPLE, created_after: '2023-08-01T00:00:00Z', created_before: '2023-08-15T23:59:59Z', }; await UniversalSearchService.searchRecords(params); // Verify that advancedSearchPeople was called with enhanced filters expect(advancedSearchPeople).toHaveBeenCalledTimes(1); const [filters, paginationOptions] = ( advancedSearchPeople as unknown as MockCall ).mock.calls[0]; // Verify that the filters include the date parameters expect(filters).toBeDefined(); expect((filters as FiltersStructure).filters).toBeDefined(); expect(Array.isArray((filters as FiltersStructure).filters)).toBe(true); // Should contain date range filters for created_at const dateFilters = (filters as FiltersStructure).filters.filter( (f) => f.attribute?.slug === 'created_at' ); expect(dateFilters.length).toBe(2); // Start and end date filters }); it('should handle single date bounds for people', async () => { const params: UniversalSearchParams = { resource_type: UniversalResourceType.PEOPLE, updated_after: '2023-08-01T00:00:00Z', }; await UniversalSearchService.searchRecords(params); expect(advancedSearchPeople).toHaveBeenCalledTimes(1); const [filters] = (advancedSearchPeople as unknown as MockCall).mock .calls[0]; // Should contain single date filter const dateFilters = (filters as FiltersStructure).filters.filter( (f) => f.attribute?.slug === 'updated_at' ); expect(dateFilters.length).toBe(1); // Only start date filter expect(dateFilters[0].condition).toBe('greater_than_or_equal_to'); }); it('should merge date filters with existing filters for people', async () => { const params: UniversalSearchParams = { resource_type: UniversalResourceType.PEOPLE, filters: { filters: [ { attribute: { slug: 'email_addresses' }, condition: 'contains', value: '@example.com', }, ], }, timeframe: 'this_month', date_field: 'created_at', }; await UniversalSearchService.searchRecords(params); expect(advancedSearchPeople).toHaveBeenCalledTimes(1); const [filters] = (advancedSearchPeople as unknown as MockCall).mock .calls[0]; // Should contain both original and date filters expect((filters as FiltersStructure).filters.length).toBe(3); // 1 original + 2 date filters // Verify original filter is preserved const emailFilter = (filters as FiltersStructure).filters.find( (f) => f.attribute?.slug === 'email_addresses' ); expect(emailFilter).toBeDefined(); expect(emailFilter.value).toBe('@example.com'); // Verify date filters are added const dateFilters = (filters as FiltersStructure).filters.filter( (f) => f.attribute?.slug === 'created_at' ); expect(dateFilters.length).toBe(2); }); }); describe('Date Filter Condition Mapping', () => { it('should use correct filter conditions for date ranges', async () => { const params: UniversalSearchParams = { resource_type: UniversalResourceType.COMPANIES, date_from: '2023-08-01T00:00:00Z', date_to: '2023-08-15T23:59:59Z', date_field: 'created_at', }; await UniversalSearchService.searchRecords(params); const [filters] = (advancedSearchCompanies as unknown as MockCall).mock .calls[0]; const dateFilters = (filters as FiltersStructure).filters.filter( (f) => f.attribute?.slug === 'created_at' ); // Verify correct conditions are used const startFilter = dateFilters.find( (f) => f.condition === 'greater_than_or_equal_to' ); const endFilter = dateFilters.find( (f) => f.condition === 'less_than_or_equal_to' ); expect(startFilter).toBeDefined(); expect(startFilter.value).toBe('2023-08-01T00:00:00Z'); expect(endFilter).toBeDefined(); expect(endFilter.value).toBe('2023-08-15T23:59:59Z'); }); it('should handle exact date matching', async () => { // This tests the equals operator, though it's rarely used in practice const params: UniversalSearchParams = { resource_type: UniversalResourceType.PEOPLE, timeframe_attribute: 'created_at', start_date: '2023-08-15T00:00:00Z', date_operator: 'equals', }; await UniversalSearchService.searchRecords(params); const [filters] = (advancedSearchPeople as unknown as MockCall).mock .calls[0]; const dateFilters = (filters as FiltersStructure).filters.filter( (f) => f.attribute?.slug === 'created_at' ); expect(dateFilters.length).toBe(1); expect(dateFilters[0].condition).toBe('equals'); expect(dateFilters[0].value).toBe('2023-08-15T00:00:00Z'); }); }); describe('Error Handling in API Integration', () => { it('should handle date validation errors gracefully', async () => { const params: UniversalSearchParams = { resource_type: UniversalResourceType.COMPANIES, date_from: 'invalid-date-format', date_to: '2023-08-15T23:59:59Z', }; await expect( UniversalSearchService.searchRecords(params) ).rejects.toThrow('Date parameter validation failed'); // Should not call the API function with invalid data expect(advancedSearchCompanies).not.toHaveBeenCalled(); }); it('should handle missing timeframe attribute gracefully', async () => { const params: UniversalSearchParams = { resource_type: UniversalResourceType.COMPANIES, start_date: '2023-08-01T00:00:00Z', end_date: '2023-08-15T23:59:59Z', // No timeframe_attribute provided }; // Should not throw error, but should not apply date filtering const results = await UniversalSearchService.searchRecords(params); expect(Array.isArray(results)).toBe(true); // Should call the API without enhanced filters expect(advancedSearchCompanies).toHaveBeenCalledTimes(1); const [filters] = (advancedSearchCompanies as unknown as MockCall).mock .calls[0]; expect((filters as FiltersStructure).filters).toEqual([]); // No filters should be added }); }); });

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