Skip to main content
Glama
UniversalCreateService-objects-deals-tasks.test.tsβ€’8.6 kB
/** * Split: UniversalCreateService objects/deals/tasks operations */ import { describe, it, expect, beforeEach, vi } from 'vitest'; vi.mock('../../src/services/ValidationService.js', () => ({ ValidationService: { truncateSuggestions: vi.fn((s: string[]) => s), validateEmailAddresses: vi.fn(), }, })); vi.mock('../../src/handlers/tool-configs/universal/field-mapper.js', () => ({ mapRecordFields: vi.fn(), validateResourceType: vi.fn(), getFieldSuggestions: vi.fn(), validateFields: vi.fn(), getValidResourceTypes: vi.fn( () => 'companies, people, lists, records, deals, tasks' ), FIELD_MAPPINGS: {}, })); vi.mock('../../src/utils/validation-utils.js', () => ({ validateRecordFields: vi.fn(), })); vi.mock('../../src/utils/attribute-format-helpers.js', () => ({ convertAttributeFormats: vi.fn((t: string, d: any) => d), getFormatErrorHelp: vi.fn( (t: string, f: string, m: string) => `Enhanced: ${m}` ), })); vi.mock('../../src/config/deal-defaults.js', () => ({ applyDealDefaultsWithValidation: vi.fn(), applyDealDefaultsWithValidationLegacy: vi.fn(), getDealDefaults: vi.fn(() => ({ stage: 'default-stage' })), validateDealInput: vi.fn(() => ({ isValid: true, suggestions: [], warnings: [], })), })); vi.mock('../../src/errors/enhanced-api-errors.js', () => ({ EnhancedApiError: vi .fn() .mockImplementation( ( message: string, statusCode: number, endpoint: string, method: string ) => { const e: any = new Error(message); e.statusCode = statusCode; e.endpoint = endpoint; e.method = method; e.name = 'EnhancedApiError'; return e; } ), ErrorEnhancer: { autoEnhance: vi.fn((e: any) => e) }, ErrorTemplates: { TASK_FIELD_MAPPING: vi.fn( (a: string, b: string) => new Error(`Use ${b} instead of ${a}`) ), }, })); vi.mock('../../src/objects/records/index.js', () => ({ createObjectRecord: vi.fn(), })); // Mock the create service factory to return a mock service const mockCreateService = { createCompany: vi.fn(), createPerson: vi.fn(), createTask: vi.fn(), createList: vi.fn(), createNote: vi.fn(), createDeal: vi.fn(), updateTask: vi.fn(), }; vi.mock('../../src/services/create/index.js', () => ({ getCreateService: vi.fn(() => mockCreateService), shouldUseMockData: vi.fn(() => true), })); import { UniversalCreateService } from '../../src/services/UniversalCreateService.js'; import { UniversalResourceType } from '../../src/handlers/tool-configs/universal/types.js'; import { AttioRecord } from '../../src/types/attio.js'; import { applyDealDefaultsWithValidation, validateDealInput, } from '../../src/config/deal-defaults.js'; import { createObjectRecord } from '../../src/objects/records/index.js'; import { getCreateService } from '../../src/services/create/index.js'; import { mapRecordFields, getFieldSuggestions, validateFields, } from '../../src/handlers/tool-configs/universal/field-mapper.js'; import { getFormatErrorHelp } from '../../src/utils/attribute-format-helpers.js'; describe('UniversalCreateService', () => { beforeEach(() => { vi.clearAllMocks(); delete process.env.E2E_MODE; // Setup default mock returns vi.mocked(validateFields).mockReturnValue({ valid: true, warnings: [], suggestions: [], errors: [], } as any); vi.mocked(mapRecordFields).mockImplementation( (resourceType: string, data: any) => ({ mapped: data, warnings: [], errors: [], }) as any ); }); describe('createRecord - objects/deals/tasks', () => { it('should create a records object record', async () => { const mockRecord: AttioRecord = { id: { record_id: 'record_abc' }, values: { name: 'Test Record' }, } as any; vi.mocked(createObjectRecord).mockResolvedValue(mockRecord); const result = await UniversalCreateService.createRecord({ resource_type: UniversalResourceType.RECORDS, record_data: { values: { name: 'Test Record' }, object: 'companies' }, }); expect(createObjectRecord).toHaveBeenCalledWith('companies', { values: { name: 'Test Record' }, }); expect(result).toEqual(mockRecord); }); it('should create a deals record with defaults validation', async () => { const mockDeal: AttioRecord = { id: { record_id: 'deal_def' }, values: { name: 'Test Deal' }, } as any; const mockDealData = { name: 'Test Deal', stage: 'qualified' } as any; const mockDealValidation = { dealData: mockDealData, warnings: [], suggestions: [], }; vi.mocked(applyDealDefaultsWithValidation).mockResolvedValue( mockDealValidation ); vi.mocked(createObjectRecord).mockResolvedValue(mockDeal); const result = await UniversalCreateService.createRecord({ resource_type: UniversalResourceType.DEALS, record_data: { values: { name: 'Test Deal' } }, }); expect(validateDealInput).toHaveBeenCalledWith({ name: 'Test Deal' }); expect(applyDealDefaultsWithValidation).toHaveBeenCalled(); expect(result).toEqual(mockDeal); }); it('should create a task record with field transformation', async () => { const mockTaskRecord: AttioRecord = { id: { record_id: 'task_ghi', task_id: 'task_ghi' }, values: { content: 'Test Task' }, } as any; mockCreateService.createTask.mockResolvedValue(mockTaskRecord); vi.mocked(mapRecordFields).mockReturnValue({ mapped: { content: 'Test Task', assignees: 'user_123', deadline_at: '2024-02-01', linked_records: 'comp_123', }, warnings: [], errors: [], } as any); const result = await UniversalCreateService.createRecord({ resource_type: UniversalResourceType.TASKS, record_data: { values: { content: 'Test Task', assignees: 'user_123', deadline_at: '2024-02-01', linked_records: 'comp_123', }, }, }); expect(mockCreateService.createTask).toHaveBeenCalledWith({ content: 'Test Task', assigneeId: 'user_123', dueDate: '2024-02-01', recordId: 'comp_123', }); expect(result).toEqual(mockTaskRecord); }); it('should handle deals with stage validation failure and retry', async () => { const originalData = { name: 'Test Deal', stage: 'invalid-stage' } as any; const defaultData = { name: 'Test Deal', stage: 'default-stage' } as any; const mockDeal: AttioRecord = { id: { record_id: 'deal_123' }, values: { name: 'Test Deal' }, } as any; const originalValidation = { dealData: originalData, warnings: ['Invalid stage warning'], suggestions: ['Use default-stage'], }; const defaultValidation = { dealData: defaultData, warnings: [], suggestions: [], }; vi.mocked(applyDealDefaultsWithValidation) .mockResolvedValueOnce(originalValidation) .mockResolvedValueOnce(defaultValidation); vi.mocked(createObjectRecord) .mockRejectedValueOnce(new Error('Cannot find Status "invalid-stage"')) .mockResolvedValueOnce(mockDeal); const result = await UniversalCreateService.createRecord({ resource_type: UniversalResourceType.DEALS, record_data: { values: { name: 'Test Deal', stage: 'invalid-stage' } }, }); expect(createObjectRecord).toHaveBeenCalledTimes(2); expect(result).toEqual(mockDeal); }); it('should handle task creation with empty content (E2E mode)', async () => { process.env.E2E_MODE = 'true'; const mockTaskRecord: AttioRecord = { id: { record_id: 'task_123', task_id: 'task_123' }, values: { content: 'New task' }, } as any; mockCreateService.createTask.mockResolvedValue(mockTaskRecord); vi.mocked(mapRecordFields).mockReturnValue({ mapped: { content: '' }, warnings: [], errors: [], } as any); const result = await UniversalCreateService.createRecord({ resource_type: UniversalResourceType.TASKS, record_data: { values: { content: '' } }, }); expect(result).toEqual(mockTaskRecord); expect(mockCreateService.createTask).toHaveBeenCalledWith({ content: 'New task', }); }); }); });

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