import { EventRecord, AllowedModule, Manifest } from '../../src/types/common'; import { CBFileSystem } from '../../src/node/file-system'; import { CBProcess } from '../../src/node/process'; describe('Shared Types', () => { describe('EventRecord interface', () => { it('should allow valid EventRecord objects', () => { const validEventRecord: EventRecord = { api_version: 'v2', content: { customer: { id: 'cust_123', email: 'test@example.com' } }, event_type: 'customer_created', id: 'evt_123456789', object: 'event', occurred_at: 1640995200, source: 'webhook', webhook_status: 'success', webhooks: [ { id: 'webhook_123', object: 'webhook', webhook_status: 'success' } ] }; expect(validEventRecord).toBeDefined(); expect(validEventRecord.api_version).toBe('v2'); expect(validEventRecord.event_type).toBe('customer_created'); expect(validEventRecord.id).toBe('evt_123456789'); expect(validEventRecord.object).toBe('event'); expect(typeof validEventRecord.occurred_at).toBe('number'); expect(validEventRecord.webhooks).toHaveLength(1); }); it('should allow complex content objects', () => { const eventWithComplexContent: EventRecord = { api_version: 'v2', content: { subscription: { id: 'sub_123', status: 'active', plan_id: 'plan_456', customer_id: 'cust_789', metadata: { source: 'api', environment: 'production' } }, customer: { id: 'cust_789', email: 'customer@example.com', first_name: 'John', last_name: 'Doe' } }, event_type: 'subscription_created', id: 'evt_987654321', object: 'event', occurred_at: 1640995200, source: 'api', webhook_status: 'pending', webhooks: [] }; expect(eventWithComplexContent.content['subscription']).toBeDefined(); expect(eventWithComplexContent.content['customer']).toBeDefined(); expect(eventWithComplexContent.content['subscription'].metadata).toBeDefined(); }); it('should allow empty webhooks array', () => { const eventWithEmptyWebhooks: EventRecord = { api_version: 'v2', content: {}, event_type: 'test_event', id: 'evt_123', object: 'event', occurred_at: 1640995200, source: 'test', webhook_status: 'success', webhooks: [] }; expect(eventWithEmptyWebhooks.webhooks).toHaveLength(0); }); it('should allow multiple webhooks', () => { const eventWithMultipleWebhooks: EventRecord = { api_version: 'v2', content: {}, event_type: 'test_event', id: 'evt_123', object: 'event', occurred_at: 1640995200, source: 'test', webhook_status: 'success', webhooks: [ { id: 'webhook_1', object: 'webhook', webhook_status: 'success' }, { id: 'webhook_2', object: 'webhook', webhook_status: 'failed' } ] }; expect(eventWithMultipleWebhooks.webhooks).toHaveLength(2); expect(eventWithMultipleWebhooks.webhooks[0]!.id).toBe('webhook_1'); expect(eventWithMultipleWebhooks.webhooks[1]!.id).toBe('webhook_2'); }); }); describe('AllowedModule interface', () => { it('should allow AllowedModule with required name', () => { const allowedModule: AllowedModule = { name: 'lodash', type: 'public' }; expect(allowedModule.name).toBe('lodash'); expect(allowedModule.version).toBeUndefined(); }); it('should allow AllowedModule with optional version', () => { const allowedModuleWithVersion: AllowedModule = { name: 'lodash', version: '4.17.21', type: 'public' }; expect(allowedModuleWithVersion.name).toBe('lodash'); expect(allowedModuleWithVersion.version).toBe('4.17.21'); }); it('should allow various module names', () => { const modules: AllowedModule[] = [ { name: 'lodash', type: 'public' }, { name: '@types/node', version: '18.0.0', type: 'public' }, { name: 'express', type: 'public' }, { name: 'axios', version: '1.0.0', type: 'public' } ]; modules.forEach(module => { expect(module.name).toBeDefined(); expect(typeof module.name).toBe('string'); }); }); }); describe('Manifest interface', () => { it('should allow Manifest with required events', () => { const manifest: Manifest = { events: { 'customer_created': { handler: 'handler/customerCreated.js' }, 'subscription_created': { handler: 'handler/subscriptionCreated.js' } } }; expect(manifest.events).toBeDefined(); expect(manifest.events['customer_created']).toBeDefined(); expect(manifest.events['customer_created']!.handler).toBe('handler/customerCreated.js'); expect(manifest.dependencies).toBeUndefined(); }); it('should allow Manifest with optional dependencies', () => { const manifestWithDeps: Manifest = { events: { 'invoice_generated': { handler: 'handler/invoiceGenerated.js' } }, dependencies: { 'lodash': '4.17.21', 'axios': '1.0.0', '@types/node': '18.0.0' } }; expect(manifestWithDeps.events).toBeDefined(); expect(manifestWithDeps.dependencies).toBeDefined(); expect(manifestWithDeps.dependencies!['lodash']).toBe('4.17.21'); expect(manifestWithDeps.dependencies!['axios']).toBe('1.0.0'); }); it('should allow empty events object', () => { const emptyManifest: Manifest = { events: {} }; expect(emptyManifest.events).toBeDefined(); expect(Object.keys(emptyManifest.events)).toHaveLength(0); }); it('should allow complex event handler paths', () => { const manifestWithComplexPaths: Manifest = { events: { 'customer_created': { handler: './src/handlers/customer/customerCreated.js' }, 'subscription_updated': { handler: './dist/handlers/subscription/subscriptionUpdated.js' }, 'invoice_paid': { handler: 'handlers/invoice/paid.js' } } }; expect(manifestWithComplexPaths.events['customer_created']!.handler) .toBe('./src/handlers/customer/customerCreated.js'); expect(manifestWithComplexPaths.events['subscription_updated']!.handler) .toBe('./dist/handlers/subscription/subscriptionUpdated.js'); expect(manifestWithComplexPaths.events['invoice_paid']!.handler) .toBe('handlers/invoice/paid.js'); }); it('should allow various event types', () => { const manifestWithVariousEvents: Manifest = { events: { 'customer_created': { handler: 'handler1.js' }, 'customer_updated': { handler: 'handler2.js' }, 'customer_deleted': { handler: 'handler3.js' }, 'subscription_created': { handler: 'handler4.js' }, 'subscription_updated': { handler: 'handler5.js' }, 'subscription_cancelled': { handler: 'handler6.js' }, 'invoice_created': { handler: 'handler7.js' }, 'invoice_updated': { handler: 'handler8.js' }, 'invoice_deleted': { handler: 'handler9.js' }, 'payment_succeeded': { handler: 'handler10.js' }, 'payment_failed': { handler: 'handler11.js' } } }; const eventTypes = Object.keys(manifestWithVariousEvents.events); expect(eventTypes).toHaveLength(11); expect(eventTypes).toContain('customer_created'); expect(eventTypes).toContain('subscription_created'); expect(eventTypes).toContain('invoice_created'); expect(eventTypes).toContain('payment_succeeded'); }); }); describe('CBFileSystem interface', () => { it('should define the required interface structure', () => { // This test verifies that the CBFileSystem interface is properly defined // We're testing the TypeScript interface, not runtime behavior const mockFileSystem: CBFileSystem = { existsSync: () => true, readdirSync: () => [], mkdirSync: () => { }, unlinkSync: () => { }, rmdirSync: () => { }, statSync: () => ({ isDirectory: () => true, size: 0 }), createWriteStream: () => ({} as any), readFileSync: () => '', writeFileSync: () => { }, copyFileSync: () => { }, lstatSync: () => ({ isSymbolicLink: () => false } as any), renameSync: () => { }, cpSync: () => { } }; expect(mockFileSystem).toBeDefined(); expect(typeof mockFileSystem.existsSync).toBe('function'); expect(typeof mockFileSystem.readFileSync).toBe('function'); expect(typeof mockFileSystem.writeFileSync).toBe('function'); }); }); describe('CBProcess interface', () => { it('should define the required interface structure', () => { // This test verifies that the CBProcess interface is properly defined // We're testing the TypeScript interface, not runtime behavior const mockProcess: CBProcess = { chdir: () => { }, exit: () => { throw new Error('exit called'); }, cwd: () => '/tmp', env: {}, on: () => { } }; expect(mockProcess).toBeDefined(); expect(typeof mockProcess.cwd).toBe('function'); expect(typeof mockProcess.env).toBe('object'); }); }); describe('Type compatibility', () => { it('should allow EventRecord to be used in function parameters', () => { const processEvent = (event: EventRecord): string => { return `Processing ${event.event_type} event with ID ${event.id}`; }; const testEvent: EventRecord = { api_version: 'v2', content: {}, event_type: 'test_event', id: 'evt_123', object: 'event', occurred_at: 1640995200, source: 'test', webhook_status: 'success', webhooks: [] }; const result = processEvent(testEvent); expect(result).toBe('Processing test_event event with ID evt_123'); }); it('should allow AllowedModule array', () => { const allowedModules: AllowedModule[] = [ { name: 'lodash', version: '4.17.21', type: 'public' }, { name: 'axios', type: 'public' }, { name: 'express', version: '4.18.0', type: 'public' } ]; expect(allowedModules).toHaveLength(3); expect(allowedModules[0]!.name).toBe('lodash'); expect(allowedModules[1]!.version).toBeUndefined(); expect(allowedModules[2]!.version).toBe('4.18.0'); }); it('should allow Manifest with dependencies as Record', () => { const dependencies: Record = { 'lodash': '4.17.21', 'axios': '1.0.0' }; const manifest: Manifest = { events: { 'test_event': { handler: 'test.js' } }, dependencies }; expect(manifest.dependencies).toBe(dependencies); expect(manifest.dependencies!['lodash']).toBe('4.17.21'); }); }); });