Skip to main content
Glama
records.test.tsβ€’8.77 kB
import { describe, it, expect, beforeEach, vi } from 'vitest'; import { createObjectRecord, getObjectRecord, updateObjectRecord, deleteObjectRecord, listObjectRecords, batchCreateObjectRecords, batchUpdateObjectRecords, formatRecordAttribute, formatRecordAttributes, } from '../../src/objects/records'; import * as attioOperations from '../../src/api/operations/index'; import { getAttioClient } from '../../src/api/attio-client'; import { AttioRecord, RecordAttributes } from '../../src/types/attio'; // Mock the attio-operations module vi.mock('../../src/api/operations/index'); describe('Records API', () => { // Sample mock data const mockRecord: AttioRecord = { id: { record_id: 'record123', }, values: { name: 'Test Record', description: 'This is a test record', }, }; // Mock API client for global override mechanism const mockPost = vi.fn(); const mockGet = vi.fn(); const mockPatch = vi.fn(); const mockDelete = vi.fn(); const mockApiClient = { post: mockPost, get: mockGet, patch: mockPatch, delete: mockDelete, }; beforeEach(() => { vi.clearAllMocks(); // Set up test-specific client override ( globalThis as { setTestApiClient?: (client: unknown) => void } ).setTestApiClient?.(mockApiClient); }); describe('createObjectRecord', () => { it('should call createRecord to create a new record', async () => { // Setup mock response const mockAttributes = { name: 'Test Record', description: 'This is a test record', }; // Mock the createRecord function vi.mocked(attioOperations.createRecord).mockResolvedValue(mockRecord); // Call the function const result = await createObjectRecord<AttioRecord>( 'companies', mockAttributes ); // Assertions expect(attioOperations.createRecord).toHaveBeenCalledWith({ objectSlug: 'companies', objectId: undefined, attributes: mockAttributes, }); expect(result).toEqual(mockRecord); }); it('should handle errors and use fallback implementation if needed', async () => { // Mock data const mockAttributes = { name: 'Test Record', description: 'This is a test record', }; // Mock the createRecord function to throw an error that's a non-Error object // This will bypass the error instanceof Error check vi.mocked(attioOperations.createRecord).mockImplementation(() => { // Return a Promise that rejects with a non-Error object return Promise.reject({ message: 'API error' }); }); // Mock the direct API call for fallback mockPost.mockResolvedValue({ data: { data: mockRecord, }, }); // Call the function const result = await createObjectRecord<AttioRecord>( 'companies', mockAttributes ); // Assertions expect(attioOperations.createRecord).toHaveBeenCalled(); expect(mockApiClient.post).toHaveBeenCalledWith( '/objects/companies/records', { data: { values: mockAttributes, }, } ); expect(result).toEqual(mockRecord); }); }); describe('getObjectRecord', () => { it('should call getRecord to get record details', async () => { // Mock the getRecord function vi.mocked(attioOperations.getRecord).mockResolvedValue(mockRecord); // Call the function const result = await getObjectRecord<AttioRecord>( 'companies', 'record123' ); // Assertions expect(attioOperations.getRecord).toHaveBeenCalledWith( 'companies', 'record123', undefined, undefined ); expect(result).toEqual(mockRecord); }); it('should support attributes parameter', async () => { // Mock the getRecord function vi.mocked(attioOperations.getRecord).mockResolvedValue(mockRecord); // Call the function with attributes const attributes = ['name', 'description']; const result = await getObjectRecord<AttioRecord>( 'companies', 'record123', attributes ); // Assertions expect(attioOperations.getRecord).toHaveBeenCalledWith( 'companies', 'record123', attributes, undefined ); expect(result).toEqual(mockRecord); }); }); describe('updateObjectRecord', () => { it('should call updateRecord to update a record', async () => { // Setup mock data const mockAttributes = { description: 'Updated description', }; // Mock the updateRecord function vi.mocked(attioOperations.updateRecord).mockResolvedValue(mockRecord); // Call the function const result = await updateObjectRecord<AttioRecord>( 'companies', 'record123', mockAttributes ); // Assertions expect(attioOperations.updateRecord).toHaveBeenCalledWith({ objectSlug: 'companies', objectId: undefined, recordId: 'record123', attributes: mockAttributes, }); expect(result).toEqual(mockRecord); }); }); describe('deleteObjectRecord', () => { it('should call deleteRecord to delete a record', async () => { // Mock the deleteRecord function vi.mocked(attioOperations.deleteRecord).mockResolvedValue(true); // Call the function const result = await deleteObjectRecord('companies', 'record123'); // Assertions expect(attioOperations.deleteRecord).toHaveBeenCalledWith( 'companies', 'record123', undefined ); expect(result).toBe(true); }); }); describe('listObjectRecords', () => { it('should call listRecords to list records', async () => { // Mock response data const mockRecords = [ mockRecord, { ...mockRecord, id: { record_id: 'record456' } }, ]; // Mock the listRecords function vi.mocked(attioOperations.listRecords).mockResolvedValue(mockRecords); // Call the function const result = await listObjectRecords<AttioRecord>('companies'); // Assertions expect(attioOperations.listRecords).toHaveBeenCalledWith({ objectSlug: 'companies', objectId: undefined, }); expect(result).toEqual(mockRecords); expect(result.length).toBe(2); }); it('should support filtering options', async () => { // Mock response data const mockRecords = [mockRecord]; // Mock the listRecords function vi.mocked(attioOperations.listRecords).mockResolvedValue(mockRecords); // Call the function with options const options = { query: 'Test', pageSize: 10, sort: 'name', direction: 'asc' as const, }; const result = await listObjectRecords<AttioRecord>('companies', options); // Assertions expect(attioOperations.listRecords).toHaveBeenCalledWith({ objectSlug: 'companies', objectId: undefined, ...options, }); expect(result).toEqual(mockRecords); }); }); describe('formatRecordAttribute', () => { it('should correctly format Date values', () => { const date = new Date('2023-01-01T00:00:00Z'); const result = formatRecordAttribute('date_field', date); expect(result).toBe('2023-01-01T00:00:00.000Z'); }); it('should handle currency fields', () => { const result = formatRecordAttribute('annual_revenue', 5000000); expect(result).toBe(5000000); }); it('should handle record ID links', () => { const result = formatRecordAttribute('primary_contact', 'record_abc123'); expect(result).toEqual({ record_id: 'record_abc123' }); }); it('should return null and undefined as is', () => { expect(formatRecordAttribute('field1', null)).toBeNull(); expect(formatRecordAttribute('field2', undefined)).toBeUndefined(); }); }); describe('formatRecordAttributes', () => { it('should format multiple attributes', () => { const date = new Date('2023-01-01T00:00:00Z'); const attributes: Record<string, unknown> = { name: 'Test Record', founded_date: date, annual_revenue: 5000000, primary_contact: 'record_abc123', description: null, }; const result = formatRecordAttributes(attributes); expect(result).toEqual({ name: 'Test Record', founded_date: '2023-01-01T00:00:00.000Z', annual_revenue: 5000000, primary_contact: { record_id: 'record_abc123' }, description: null, }); }); }); });

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