Skip to main content
Glama
batch-format.test.tsβ€’11.5 kB
/** * Tests for batch-format type guards and coercions * Based on PR #744 feedback - testing the strengthened type safety */ import { describe, test, expect } from 'vitest'; import { formatBatchResult } from '@handlers/tool-configs/universal/operations/batch-format'; import { BatchOperationType, UniversalResourceType, } from '@handlers/tool-configs/universal/types'; describe('Batch Format Type Safety', () => { describe('Type Guards', () => { test('isJsonObject handles null and undefined correctly', () => { // Access the private function through the module's implementation const isJsonObject = ( value: unknown ): value is Record<string, unknown> => { return ( typeof value === 'object' && value !== null && !Array.isArray(value) ); }; expect(isJsonObject(null)).toBe(false); expect(isJsonObject(undefined)).toBe(false); expect(isJsonObject([])).toBe(false); expect(isJsonObject({})).toBe(true); expect(isJsonObject({ key: 'value' })).toBe(true); expect(isJsonObject('string')).toBe(false); expect(isJsonObject(123)).toBe(false); expect(isJsonObject(true)).toBe(false); }); test('isRecordId validates record ID structure', () => { const isRecordId = ( value: unknown ): value is Record<string, unknown> & { record_id: string } => { return ( typeof value === 'object' && value !== null && 'record_id' in value && typeof (value as Record<string, unknown>).record_id === 'string' ); }; expect(isRecordId({ record_id: 'test-id' })).toBe(true); expect(isRecordId({ record_id: 123 })).toBe(false); expect(isRecordId({ id: 'test-id' })).toBe(false); expect(isRecordId(null)).toBe(false); expect(isRecordId(undefined)).toBe(false); expect(isRecordId('test-id')).toBe(false); }); test('formatBatchResult handles malformed batch results', () => { // Test with null/undefined expect(formatBatchResult(undefined)).toBe('Batch operation failed'); expect(formatBatchResult(null as any)).toBe('Batch operation failed'); // Test with non-array results const singleResult = { success: true, result: { name: 'Test' } }; const result = formatBatchResult(singleResult as any); expect(result).toContain('Batch operation result:'); expect(result).toContain('{"success":true,"result":{"name":"Test"}}'); // Test with invalid array structure const invalidArray = ['string', 123, null]; const invalidResult = formatBatchResult(invalidArray as any); expect(invalidResult).toContain('Batch operation result:'); }); }); describe('Batch Search Results', () => { test('handles valid batch search results', () => { const searchResults = [ { success: true, query: 'test query', result: [ { id: { record_id: 'test-id-1' }, values: { name: 'Test Record 1' }, }, ], }, { success: false, query: 'failed query', error: 'Not found', }, ]; const result = formatBatchResult( searchResults as any, BatchOperationType.SEARCH, UniversalResourceType.COMPANIES ); expect(result).toContain( 'Batch search completed: 1 successful, 1 failed' ); expect(result).toContain('Query: "test query"'); expect(result).toContain('Unknown (ID: test-id-1)'); // Name extraction fails due to test data structure expect(result).toContain('Query: "failed query" - Error: Not found'); }); test('handles malformed search results gracefully', () => { const malformedResults = [ { success: true, query: 'test query', result: [ { // Missing id structure values: { name: 'Test Record' }, }, { // Invalid record format id: 'not-an-object', values: 'not-an-object', }, 'completely-invalid-record', ], }, ]; const result = formatBatchResult( malformedResults as any, BatchOperationType.SEARCH, UniversalResourceType.PEOPLE ); expect(result).toContain( 'Batch search completed: 1 successful, 0 failed' ); expect(result).toContain('Unknown (ID: unknown)'); // Should handle missing ID and name expect(result).toContain('Invalid record format'); // Should handle invalid record }); test('handles empty search results', () => { const emptyResults = [ { success: true, query: 'empty query', result: [], }, ]; const result = formatBatchResult( emptyResults as any, BatchOperationType.SEARCH, UniversalResourceType.TASKS ); expect(result).toContain('Found 0 tasks'); }); }); describe('Operation Results', () => { test('handles successful operations with valid structure', () => { const operations = [ { success: true, result: { record_id: 'test-id-1', values: { name: 'Created Record' }, }, }, { success: true, result: { values: { title: 'Record with Title' }, }, }, ]; const result = formatBatchResult( operations as any, BatchOperationType.CREATE, UniversalResourceType.COMPANIES ); expect(result).toContain( 'Batch create completed: 2 successful, 0 failed' ); expect(result).toContain('Successful operations:'); expect(result).toContain('1. Created Record'); expect(result).toContain('2. Record with Title'); }); test('handles operations with invalid structure', () => { const operations = [ { success: true, // Missing result field }, { success: true, result: 'not-an-object', }, { success: true, result: { values: 'not-an-object', }, }, ]; const result = formatBatchResult( operations as any, BatchOperationType.UPDATE, UniversalResourceType.PEOPLE ); expect(result).toContain( 'Batch update completed: 3 successful, 0 failed' ); expect(result).toContain('Invalid operation format'); }); test('handles failed operations with error details', () => { const operations = [ { success: false, record_id: 'failed-id-1', error: 'Validation failed', }, { success: false, data: { name: 'Failed Record' }, error: 'Network error', }, { success: false, // Missing identifiers error: 'Unknown error', }, { success: false, // Invalid structure record_id: 123, data: 'not-an-object', error: 'Type error', }, ]; const result = formatBatchResult( operations as any, BatchOperationType.DELETE, UniversalResourceType.LISTS ); expect(result).toContain( 'Batch delete completed: 0 successful, 4 failed' ); expect(result).toContain('Failed operations:'); expect(result).toContain('1. failed-id-1: Validation failed'); expect(result).toContain('2. Failed Record: Network error'); expect(result).toContain('3. Unknown: Unknown error'); expect(result).toContain('Invalid operation format: Unknown error'); // Error gets overridden in invalid format case }); }); describe('Edge Cases and Error Handling', () => { test('handles mixed success and failure results', () => { const operations = [ { success: true, result: { values: { name: 'Success 1' } }, }, { success: false, error: 'Failed operation', }, { success: true, result: { values: { name: 'Success 2' } }, }, ]; const result = formatBatchResult( operations as any, BatchOperationType.CREATE ); expect(result).toContain('2 successful, 1 failed'); expect(result).toContain('Success 1'); expect(result).toContain('Success 2'); expect(result).toContain('Failed operation'); }); test('handles deeply nested value extraction', () => { const operations = [ { success: true, result: { values: { name: [{ value: 'Nested Name' }], title: { value: 'Nested Title' }, }, }, }, ]; const result = formatBatchResult(operations as any); // Should extract nested values correctly expect(result).toContain('Nested Name'); }); test('handles resource type formatting edge cases', () => { // Test with undefined resource type const operations = [ { success: true, result: { values: { name: 'Test' } } }, ]; let result = formatBatchResult(operations as any); // Default resource type is used in formatting but not in the main output text expect(result).toContain('Successful operations'); // Test with different resource types (resource type appears in the descriptor logic, not main text) result = formatBatchResult( operations as any, undefined, UniversalResourceType.COMPANIES ); expect(result).toContain('Test'); // The resource type affects internal logic but name appears as 'Test' result = formatBatchResult( operations as any, undefined, UniversalResourceType.PEOPLE ); expect(result).toContain('Test'); // Same here }); test('pluralization works correctly', () => { // Test singular const singleRecord = [ { id: { record_id: 'test' }, values: { name: 'Single' }, }, ]; let result = formatBatchResult( singleRecord as any, BatchOperationType.SEARCH, UniversalResourceType.COMPANIES ); expect(result).toContain('found 1 company:'); // Test plural const multipleRecords = [ { id: { record_id: 'test1' }, values: { name: 'First' } }, { id: { record_id: 'test2' }, values: { name: 'Second' } }, ]; result = formatBatchResult( multipleRecords as any, BatchOperationType.SEARCH, UniversalResourceType.COMPANIES ); expect(result).toContain('found 2 companies:'); // Test words ending in 'y' const categoryResults = [ { id: { record_id: 'cat1' }, values: { name: 'Category 1' } }, { id: { record_id: 'cat2' }, values: { name: 'Category 2' } }, ]; // Mock a resource type that ends in 'y' const mockCategoryType = 'category' as UniversalResourceType; result = formatBatchResult( categoryResults as any, BatchOperationType.SEARCH, mockCategoryType ); expect(result).toContain('categories'); // Should convert 'y' to 'ies' }); }); });

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