import { beforeEach, describe, expect, it } from 'bun:test'; import { HandlerRegistry } from '../src/registry'; import type { HandlerConfiguration, HandlerMetadata } from '../src/types'; describe('HandlerRegistry', () => { let registry: HandlerRegistry; beforeEach(() => { registry = new HandlerRegistry(); }); describe('register', () => { it('should register a handler', () => { const metadata: HandlerMetadata = { name: 'test-handler', service: 'test-service', operations: [ { name: 'operation1', method: 'method1' }, { name: 'operation2', method: 'method2' }, ], }; const config: HandlerConfiguration = { name: 'test-handler', operations: { operation1: async () => {}, operation2: async () => {}, }, }; registry.register(metadata, config); expect(registry.hasHandler('test-handler')).toBe(true); expect(registry.getHandlerNames()).toContain('test-handler'); }); it('should allow duplicate registration', () => { const metadata: HandlerMetadata = { name: 'duplicate', operations: [], }; const config: HandlerConfiguration = { name: 'duplicate', operations: {}, }; registry.register(metadata, config); // Should not throw on duplicate registration expect(() => { registry.register(metadata, config); }).not.toThrow(); }); }); describe('getConfiguration', () => { it('should return registered handler config', () => { const config: HandlerConfiguration = { name: 'my-handler', operations: { doSomething: async () => 'result', }, }; registry.register({ name: 'my-handler', operations: [] }, config); const retrieved = registry.getConfiguration('my-handler'); expect(retrieved).toBe(config); }); it('should return undefined for unknown handler', () => { const result = registry.getConfiguration('unknown'); expect(result).toBeUndefined(); }); }); describe('getOperation', () => { it('should return operation handler', () => { const operationFn = async () => 'test'; registry.register( { name: 'handler1', operations: [{ name: 'op1', method: 'method1' }] }, { name: 'handler1', operations: { op1: operationFn } } ); const retrieved = registry.getOperation('handler1', 'op1'); expect(retrieved).toBe(operationFn); }); it('should return undefined for unknown operation', () => { registry.register({ name: 'handler1', operations: [] }, { name: 'handler1', operations: {} }); const result = registry.getOperation('handler1', 'unknown'); expect(result).toBeUndefined(); }); }); describe('scheduled jobs', () => { it('should register handler with scheduled jobs', () => { const metadata: HandlerMetadata = { name: 'scheduled-handler', operations: [], schedules: [ { operation: 'scheduled-op', cronPattern: '* * * * *', priority: 5, }, ], }; const config: HandlerConfiguration = { name: 'scheduled-handler', operations: {}, scheduledJobs: [ { type: 'scheduled-handler-scheduled-op', operation: 'scheduled-op', cronPattern: '* * * * *', priority: 5, }, ], }; registry.register(metadata, config); const handlers = registry.getAllHandlersWithSchedule(); expect(handlers.size).toBe(1); expect(handlers.has('scheduled-handler')).toBe(true); const handlerData = handlers.get('scheduled-handler'); expect(handlerData?.scheduledJobs).toHaveLength(1); }); it('should return all handlers including those without schedules', () => { registry.register( { name: 'no-schedule', operations: [] }, { name: 'no-schedule', operations: {} } ); registry.register( { name: 'with-schedule', operations: [], schedules: [{ operation: 'op', cronPattern: '* * * * *' }], }, { name: 'with-schedule', operations: {}, scheduledJobs: [{ type: 'job', operation: 'op', cronPattern: '* * * * *' }], } ); const handlers = registry.getAllHandlersWithSchedule(); expect(handlers.size).toBe(2); const noScheduleData = handlers.get('no-schedule'); expect(noScheduleData?.scheduledJobs).toHaveLength(0); const withScheduleData = handlers.get('with-schedule'); expect(withScheduleData?.scheduledJobs).toHaveLength(1); }); }); describe('service mapping', () => { it('should track handler service', () => { registry.register( { name: 'handler1', service: 'service-a', operations: [] }, { name: 'handler1', operations: {} } ); expect(registry.getHandlerService('handler1')).toBe('service-a'); }); it('should return undefined for handler without service', () => { registry.register({ name: 'handler2', operations: [] }, { name: 'handler2', operations: {} }); expect(registry.getHandlerService('handler2')).toBeUndefined(); }); }); describe('getAllMetadata', () => { it('should return all registered handlers', () => { registry.register({ name: 'h1', operations: [] }, { name: 'h1', operations: {} }); registry.register({ name: 'h2', operations: [] }, { name: 'h2', operations: {} }); const all = registry.getAllMetadata(); expect(all.size).toBe(2); expect(all.has('h1')).toBe(true); expect(all.has('h2')).toBe(true); }); }); });