created lots of tests
This commit is contained in:
parent
42baadae38
commit
54f37f9521
21 changed files with 4577 additions and 215 deletions
46
libs/core/di/test/factories.test.ts
Normal file
46
libs/core/di/test/factories.test.ts
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
import { describe, expect, it } from 'bun:test';
|
||||
import { CacheFactory } from '../src/factories';
|
||||
|
||||
describe('DI Factories', () => {
|
||||
describe('CacheFactory', () => {
|
||||
it('should be exported', () => {
|
||||
expect(CacheFactory).toBeDefined();
|
||||
});
|
||||
|
||||
it('should create cache with configuration', () => {
|
||||
const cacheConfig = {
|
||||
redisConfig: {
|
||||
host: 'localhost',
|
||||
port: 6379,
|
||||
db: 1,
|
||||
},
|
||||
keyPrefix: 'test:',
|
||||
};
|
||||
|
||||
const cache = CacheFactory.create(cacheConfig);
|
||||
expect(cache).toBeDefined();
|
||||
});
|
||||
|
||||
it('should create null cache without config', () => {
|
||||
const cache = CacheFactory.create();
|
||||
expect(cache).toBeDefined();
|
||||
expect(cache.type).toBe('null');
|
||||
});
|
||||
|
||||
it('should create cache with logger', () => {
|
||||
const mockLogger = {
|
||||
info: () => {},
|
||||
error: () => {},
|
||||
warn: () => {},
|
||||
debug: () => {},
|
||||
};
|
||||
|
||||
const cacheConfig = {
|
||||
logger: mockLogger,
|
||||
};
|
||||
|
||||
const cache = CacheFactory.create(cacheConfig);
|
||||
expect(cache).toBeDefined();
|
||||
});
|
||||
});
|
||||
})
|
||||
260
libs/core/di/test/lifecycle.test.ts
Normal file
260
libs/core/di/test/lifecycle.test.ts
Normal file
|
|
@ -0,0 +1,260 @@
|
|||
import { describe, expect, it, mock, beforeEach } from 'bun:test';
|
||||
import { ServiceLifecycleManager } from '../src/utils/lifecycle';
|
||||
import type { AwilixContainer } from 'awilix';
|
||||
|
||||
describe('ServiceLifecycleManager', () => {
|
||||
let manager: ServiceLifecycleManager;
|
||||
|
||||
beforeEach(() => {
|
||||
manager = new ServiceLifecycleManager();
|
||||
});
|
||||
|
||||
describe('initializeServices', () => {
|
||||
it('should initialize services with connect method', async () => {
|
||||
const mockCache = {
|
||||
connect: mock(() => Promise.resolve()),
|
||||
};
|
||||
|
||||
const mockMongoClient = {
|
||||
connect: mock(() => Promise.resolve()),
|
||||
};
|
||||
|
||||
const mockContainer = {
|
||||
cradle: {
|
||||
cache: mockCache,
|
||||
mongoClient: mockMongoClient,
|
||||
postgresClient: null, // Not configured
|
||||
},
|
||||
} as unknown as AwilixContainer;
|
||||
|
||||
await manager.initializeServices(mockContainer);
|
||||
|
||||
expect(mockCache.connect).toHaveBeenCalled();
|
||||
expect(mockMongoClient.connect).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should initialize services with initialize method', async () => {
|
||||
const mockService = {
|
||||
initialize: mock(() => Promise.resolve()),
|
||||
};
|
||||
|
||||
const mockContainer = {
|
||||
cradle: {
|
||||
cache: mockService,
|
||||
},
|
||||
} as unknown as AwilixContainer;
|
||||
|
||||
await manager.initializeServices(mockContainer);
|
||||
|
||||
expect(mockService.initialize).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should handle initialization errors', async () => {
|
||||
const mockService = {
|
||||
connect: mock(() => Promise.reject(new Error('Connection failed'))),
|
||||
};
|
||||
|
||||
const mockContainer = {
|
||||
cradle: {
|
||||
cache: mockService,
|
||||
},
|
||||
} as unknown as AwilixContainer;
|
||||
|
||||
await expect(manager.initializeServices(mockContainer)).rejects.toThrow('Connection failed');
|
||||
});
|
||||
|
||||
it('should handle initialization timeout', async () => {
|
||||
const mockService = {
|
||||
connect: mock(() => new Promise(() => {})), // Never resolves
|
||||
};
|
||||
|
||||
const mockContainer = {
|
||||
cradle: {
|
||||
cache: mockService,
|
||||
},
|
||||
} as unknown as AwilixContainer;
|
||||
|
||||
await expect(manager.initializeServices(mockContainer, 100)).rejects.toThrow('cache initialization timed out after 100ms');
|
||||
});
|
||||
});
|
||||
|
||||
describe('shutdownServices', () => {
|
||||
it('should shutdown services with disconnect method', async () => {
|
||||
const mockCache = {
|
||||
disconnect: mock(() => Promise.resolve()),
|
||||
};
|
||||
|
||||
const mockMongoClient = {
|
||||
disconnect: mock(() => Promise.resolve()),
|
||||
};
|
||||
|
||||
const mockContainer = {
|
||||
cradle: {
|
||||
cache: mockCache,
|
||||
mongoClient: mockMongoClient,
|
||||
},
|
||||
} as unknown as AwilixContainer;
|
||||
|
||||
await manager.shutdownServices(mockContainer);
|
||||
|
||||
expect(mockCache.disconnect).toHaveBeenCalled();
|
||||
expect(mockMongoClient.disconnect).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should shutdown services with close method', async () => {
|
||||
const mockService = {
|
||||
close: mock(() => Promise.resolve()),
|
||||
};
|
||||
|
||||
const mockContainer = {
|
||||
cradle: {
|
||||
queueManager: mockService,
|
||||
},
|
||||
} as unknown as AwilixContainer;
|
||||
|
||||
await manager.shutdownServices(mockContainer);
|
||||
|
||||
expect(mockService.close).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should shutdown services with shutdown method', async () => {
|
||||
const mockService = {
|
||||
shutdown: mock(() => Promise.resolve()),
|
||||
};
|
||||
|
||||
const mockContainer = {
|
||||
cradle: {
|
||||
cache: mockService,
|
||||
},
|
||||
} as unknown as AwilixContainer;
|
||||
|
||||
await manager.shutdownServices(mockContainer);
|
||||
|
||||
expect(mockService.shutdown).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should handle shutdown errors gracefully', async () => {
|
||||
const mockService = {
|
||||
disconnect: mock(() => Promise.reject(new Error('Disconnect failed'))),
|
||||
};
|
||||
|
||||
const mockContainer = {
|
||||
cradle: {
|
||||
cache: mockService,
|
||||
},
|
||||
} as unknown as AwilixContainer;
|
||||
|
||||
// Should not throw
|
||||
await manager.shutdownServices(mockContainer);
|
||||
});
|
||||
|
||||
it('should shutdown services in reverse order', async () => {
|
||||
const callOrder: string[] = [];
|
||||
|
||||
const mockCache = {
|
||||
disconnect: mock(() => {
|
||||
callOrder.push('cache');
|
||||
return Promise.resolve();
|
||||
}),
|
||||
};
|
||||
|
||||
const mockQueueManager = {
|
||||
close: mock(() => {
|
||||
callOrder.push('queue');
|
||||
return Promise.resolve();
|
||||
}),
|
||||
};
|
||||
|
||||
const mockContainer = {
|
||||
cradle: {
|
||||
cache: mockCache,
|
||||
queueManager: mockQueueManager,
|
||||
},
|
||||
} as unknown as AwilixContainer;
|
||||
|
||||
await manager.shutdownServices(mockContainer);
|
||||
|
||||
// Queue manager should be shutdown before cache (reverse order)
|
||||
expect(callOrder[0]).toBe('queue');
|
||||
expect(callOrder[1]).toBe('cache');
|
||||
});
|
||||
});
|
||||
|
||||
describe('mixed lifecycle methods', () => {
|
||||
it('should handle services with multiple lifecycle methods', async () => {
|
||||
const mockService = {
|
||||
connect: mock(() => Promise.resolve()),
|
||||
disconnect: mock(() => Promise.resolve()),
|
||||
initialize: mock(() => Promise.resolve()),
|
||||
shutdown: mock(() => Promise.resolve()),
|
||||
};
|
||||
|
||||
const mockContainer = {
|
||||
cradle: {
|
||||
cache: mockService,
|
||||
},
|
||||
} as unknown as AwilixContainer;
|
||||
|
||||
// Initialize should prefer connect over initialize
|
||||
await manager.initializeServices(mockContainer);
|
||||
expect(mockService.connect).toHaveBeenCalled();
|
||||
expect(mockService.initialize).not.toHaveBeenCalled();
|
||||
|
||||
// Shutdown should prefer disconnect over others
|
||||
await manager.shutdownServices(mockContainer);
|
||||
expect(mockService.disconnect).toHaveBeenCalled();
|
||||
expect(mockService.shutdown).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe('complete lifecycle flow', () => {
|
||||
it('should handle full initialization and shutdown cycle', async () => {
|
||||
const mockCache = {
|
||||
connect: mock(() => Promise.resolve()),
|
||||
disconnect: mock(() => Promise.resolve()),
|
||||
};
|
||||
|
||||
const mockMongoClient = {
|
||||
connect: mock(() => Promise.resolve()),
|
||||
disconnect: mock(() => Promise.resolve()),
|
||||
};
|
||||
|
||||
const mockPostgresClient = {
|
||||
connect: mock(() => Promise.resolve()),
|
||||
close: mock(() => Promise.resolve()),
|
||||
};
|
||||
|
||||
const mockQuestdbClient = {
|
||||
initialize: mock(() => Promise.resolve()),
|
||||
shutdown: mock(() => Promise.resolve()),
|
||||
};
|
||||
|
||||
const mockContainer = {
|
||||
cradle: {
|
||||
cache: mockCache,
|
||||
mongoClient: mockMongoClient,
|
||||
postgresClient: mockPostgresClient,
|
||||
questdbClient: mockQuestdbClient,
|
||||
proxyManager: null, // Not configured
|
||||
queueManager: null, // Not configured
|
||||
},
|
||||
} as unknown as AwilixContainer;
|
||||
|
||||
// Initialize all services
|
||||
await manager.initializeServices(mockContainer);
|
||||
|
||||
expect(mockCache.connect).toHaveBeenCalled();
|
||||
expect(mockMongoClient.connect).toHaveBeenCalled();
|
||||
expect(mockPostgresClient.connect).toHaveBeenCalled();
|
||||
expect(mockQuestdbClient.initialize).toHaveBeenCalled();
|
||||
|
||||
// Shutdown all services
|
||||
await manager.shutdownServices(mockContainer);
|
||||
|
||||
expect(mockCache.disconnect).toHaveBeenCalled();
|
||||
expect(mockMongoClient.disconnect).toHaveBeenCalled();
|
||||
expect(mockPostgresClient.close).toHaveBeenCalled();
|
||||
expect(mockQuestdbClient.shutdown).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
})
|
||||
273
libs/core/di/test/operation-context.test.ts
Normal file
273
libs/core/di/test/operation-context.test.ts
Normal file
|
|
@ -0,0 +1,273 @@
|
|||
import { describe, expect, it, beforeEach, mock } from 'bun:test';
|
||||
import { OperationContext } from '../src/operation-context';
|
||||
import type { OperationContextOptions } from '../src/operation-context';
|
||||
|
||||
describe('OperationContext', () => {
|
||||
const mockLogger = {
|
||||
info: mock(() => {}),
|
||||
error: mock(() => {}),
|
||||
warn: mock(() => {}),
|
||||
debug: mock(() => {}),
|
||||
trace: mock(() => {}),
|
||||
child: mock(() => mockLogger),
|
||||
};
|
||||
|
||||
const mockContainer = {
|
||||
resolve: mock((name: string) => ({ name })),
|
||||
resolveAsync: mock(async (name: string) => ({ name })),
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
// Reset mocks
|
||||
Object.keys(mockLogger).forEach(key => {
|
||||
if (typeof mockLogger[key as keyof typeof mockLogger] === 'function') {
|
||||
(mockLogger as any)[key] = mock(() =>
|
||||
key === 'child' ? mockLogger : undefined
|
||||
);
|
||||
}
|
||||
});
|
||||
mockContainer.resolve = mock((name: string) => ({ name }));
|
||||
mockContainer.resolveAsync = mock(async (name: string) => ({ name }));
|
||||
});
|
||||
|
||||
describe('constructor', () => {
|
||||
it('should create context with required options', () => {
|
||||
const options: OperationContextOptions = {
|
||||
handlerName: 'test-handler',
|
||||
operationName: 'test-op',
|
||||
};
|
||||
|
||||
const context = new OperationContext(options);
|
||||
|
||||
expect(context).toBeDefined();
|
||||
expect(context.traceId).toBeDefined();
|
||||
expect(context.metadata).toEqual({});
|
||||
expect(context.logger).toBeDefined();
|
||||
});
|
||||
|
||||
it('should create context with all options', () => {
|
||||
const options: OperationContextOptions = {
|
||||
handlerName: 'test-handler',
|
||||
operationName: 'test-op',
|
||||
parentLogger: mockLogger,
|
||||
container: mockContainer,
|
||||
metadata: { key: 'value' },
|
||||
traceId: 'custom-trace-id',
|
||||
};
|
||||
|
||||
const context = new OperationContext(options);
|
||||
|
||||
expect(context.traceId).toBe('custom-trace-id');
|
||||
expect(context.metadata).toEqual({ key: 'value' });
|
||||
expect(context.logger).toBe(mockLogger);
|
||||
});
|
||||
});
|
||||
|
||||
describe('static create', () => {
|
||||
it('should create context using static method', () => {
|
||||
const context = OperationContext.create('handler', 'operation', {
|
||||
metadata: { foo: 'bar' },
|
||||
});
|
||||
|
||||
expect(context).toBeDefined();
|
||||
expect(context.metadata).toEqual({ foo: 'bar' });
|
||||
});
|
||||
});
|
||||
|
||||
describe('service resolution', () => {
|
||||
it('should resolve services from container', () => {
|
||||
const context = new OperationContext({
|
||||
handlerName: 'test',
|
||||
operationName: 'test-op',
|
||||
container: mockContainer,
|
||||
});
|
||||
|
||||
const service = context.resolve('myService');
|
||||
expect(service).toEqual({ name: 'myService' });
|
||||
expect(mockContainer.resolve).toHaveBeenCalledWith('myService');
|
||||
});
|
||||
|
||||
it('should resolve services asynchronously', async () => {
|
||||
const context = new OperationContext({
|
||||
handlerName: 'test',
|
||||
operationName: 'test-op',
|
||||
container: mockContainer,
|
||||
});
|
||||
|
||||
const service = await context.resolveAsync('myService');
|
||||
expect(service).toEqual({ name: 'myService' });
|
||||
expect(mockContainer.resolveAsync).toHaveBeenCalledWith('myService');
|
||||
});
|
||||
|
||||
it('should throw error when no container available', () => {
|
||||
const context = new OperationContext({
|
||||
handlerName: 'test',
|
||||
operationName: 'test-op',
|
||||
});
|
||||
|
||||
expect(() => context.resolve('service')).toThrow('No service container available');
|
||||
});
|
||||
|
||||
it('should throw error when no container available for async', async () => {
|
||||
const context = new OperationContext({
|
||||
handlerName: 'test',
|
||||
operationName: 'test-op',
|
||||
});
|
||||
|
||||
await expect(context.resolveAsync('service')).rejects.toThrow('No service container available');
|
||||
});
|
||||
});
|
||||
|
||||
describe('metadata', () => {
|
||||
it('should add metadata', () => {
|
||||
const context = new OperationContext({
|
||||
handlerName: 'test',
|
||||
operationName: 'test-op',
|
||||
});
|
||||
|
||||
context.addMetadata('userId', '12345');
|
||||
context.addMetadata('correlationId', 'corr-456');
|
||||
|
||||
expect(context.metadata.userId).toBe('12345');
|
||||
expect(context.metadata.correlationId).toBe('corr-456');
|
||||
});
|
||||
|
||||
it('should preserve initial metadata', () => {
|
||||
const context = new OperationContext({
|
||||
handlerName: 'test',
|
||||
operationName: 'test-op',
|
||||
metadata: { initial: 'value' },
|
||||
});
|
||||
|
||||
context.addMetadata('added', 'new-value');
|
||||
|
||||
expect(context.metadata.initial).toBe('value');
|
||||
expect(context.metadata.added).toBe('new-value');
|
||||
});
|
||||
});
|
||||
|
||||
describe('execution time', () => {
|
||||
it('should track execution time', async () => {
|
||||
const context = new OperationContext({
|
||||
handlerName: 'test',
|
||||
operationName: 'test-op',
|
||||
});
|
||||
|
||||
// Wait a bit
|
||||
await new Promise(resolve => setTimeout(resolve, 50));
|
||||
|
||||
const executionTime = context.getExecutionTime();
|
||||
expect(executionTime).toBeGreaterThan(40);
|
||||
expect(executionTime).toBeLessThan(100);
|
||||
});
|
||||
});
|
||||
|
||||
describe('logging', () => {
|
||||
it('should log successful completion', () => {
|
||||
const context = new OperationContext({
|
||||
handlerName: 'test',
|
||||
operationName: 'test-op',
|
||||
parentLogger: mockLogger,
|
||||
});
|
||||
|
||||
context.logCompletion(true);
|
||||
|
||||
expect(mockLogger.info).toHaveBeenCalledWith(
|
||||
'Operation completed successfully',
|
||||
expect.objectContaining({
|
||||
executionTime: expect.any(Number),
|
||||
metadata: {},
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
it('should log failed completion with error', () => {
|
||||
const context = new OperationContext({
|
||||
handlerName: 'test',
|
||||
operationName: 'test-op',
|
||||
parentLogger: mockLogger,
|
||||
});
|
||||
|
||||
const error = new Error('Test error');
|
||||
context.logCompletion(false, error);
|
||||
|
||||
expect(mockLogger.error).toHaveBeenCalledWith(
|
||||
'Operation failed',
|
||||
expect.objectContaining({
|
||||
executionTime: expect.any(Number),
|
||||
error: 'Test error',
|
||||
stack: expect.any(String),
|
||||
metadata: {},
|
||||
})
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('child context', () => {
|
||||
it('should create child context', () => {
|
||||
const parent = new OperationContext({
|
||||
handlerName: 'parent',
|
||||
operationName: 'parent-op',
|
||||
parentLogger: mockLogger,
|
||||
container: mockContainer,
|
||||
traceId: 'parent-trace',
|
||||
metadata: { parentKey: 'parentValue' },
|
||||
});
|
||||
|
||||
const child = parent.createChild('child-op', { childKey: 'childValue' });
|
||||
|
||||
expect(child.traceId).toBe('parent-trace'); // Inherits trace ID
|
||||
expect(child.metadata).toEqual({
|
||||
parentKey: 'parentValue',
|
||||
childKey: 'childValue',
|
||||
});
|
||||
expect(child.logger).toBe(mockLogger); // Inherits logger
|
||||
});
|
||||
|
||||
it('should create child without additional metadata', () => {
|
||||
const parent = new OperationContext({
|
||||
handlerName: 'parent',
|
||||
operationName: 'parent-op',
|
||||
metadata: { key: 'value' },
|
||||
});
|
||||
|
||||
const child = parent.createChild('child-op');
|
||||
|
||||
expect(child.metadata).toEqual({ key: 'value' });
|
||||
});
|
||||
});
|
||||
|
||||
describe('dispose', () => {
|
||||
it('should log completion on dispose', async () => {
|
||||
const context = new OperationContext({
|
||||
handlerName: 'test',
|
||||
operationName: 'test-op',
|
||||
parentLogger: mockLogger,
|
||||
});
|
||||
|
||||
await context.dispose();
|
||||
|
||||
expect(mockLogger.info).toHaveBeenCalledWith(
|
||||
'Operation completed successfully',
|
||||
expect.any(Object)
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('trace ID generation', () => {
|
||||
it('should generate unique trace IDs', () => {
|
||||
const context1 = new OperationContext({
|
||||
handlerName: 'test',
|
||||
operationName: 'test-op',
|
||||
});
|
||||
|
||||
const context2 = new OperationContext({
|
||||
handlerName: 'test',
|
||||
operationName: 'test-op',
|
||||
});
|
||||
|
||||
expect(context1.traceId).not.toBe(context2.traceId);
|
||||
expect(context1.traceId).toMatch(/^\d+-[a-z0-9]+$/);
|
||||
});
|
||||
});
|
||||
});
|
||||
293
libs/core/di/test/registration.test.ts
Normal file
293
libs/core/di/test/registration.test.ts
Normal file
|
|
@ -0,0 +1,293 @@
|
|||
import { describe, expect, it, mock } from 'bun:test';
|
||||
import { createContainer, asClass, asFunction, asValue } from 'awilix';
|
||||
import {
|
||||
registerCacheServices,
|
||||
registerDatabaseServices,
|
||||
registerServiceDependencies,
|
||||
} from '../src/registrations';
|
||||
|
||||
describe('DI Registrations', () => {
|
||||
describe('registerCacheServices', () => {
|
||||
it('should register null cache when no redis config', () => {
|
||||
const container = createContainer();
|
||||
const config = {
|
||||
service: {
|
||||
name: 'test-service',
|
||||
type: 'WORKER' as const,
|
||||
},
|
||||
// No redis config
|
||||
};
|
||||
|
||||
registerCacheServices(container, config);
|
||||
|
||||
const cache = container.resolve('cache');
|
||||
expect(cache).toBeDefined();
|
||||
expect(cache.type).toBe('null'); // NullCache type
|
||||
});
|
||||
|
||||
it('should register redis cache when redis config exists', () => {
|
||||
const container = createContainer();
|
||||
|
||||
// Register logger first as it's a dependency
|
||||
container.register({
|
||||
logger: asValue({
|
||||
info: () => {},
|
||||
error: () => {},
|
||||
warn: () => {},
|
||||
debug: () => {},
|
||||
}),
|
||||
});
|
||||
|
||||
const config = {
|
||||
service: {
|
||||
name: 'test-service',
|
||||
type: 'WORKER' as const,
|
||||
},
|
||||
redis: {
|
||||
host: 'localhost',
|
||||
port: 6379,
|
||||
db: 1,
|
||||
},
|
||||
};
|
||||
|
||||
registerCacheServices(container, config);
|
||||
|
||||
const cache = container.resolve('cache');
|
||||
expect(cache).toBeDefined();
|
||||
});
|
||||
|
||||
it('should register service cache', () => {
|
||||
const container = createContainer();
|
||||
|
||||
// Register dependencies
|
||||
container.register({
|
||||
cache: asValue({ type: 'null' }),
|
||||
config: asValue({
|
||||
service: { name: 'test-service' },
|
||||
redis: { host: 'localhost', port: 6379 },
|
||||
}),
|
||||
logger: asValue({ info: () => {} }),
|
||||
});
|
||||
|
||||
const config = {
|
||||
service: {
|
||||
name: 'test-service',
|
||||
type: 'WORKER' as const,
|
||||
},
|
||||
};
|
||||
|
||||
registerCacheServices(container, config);
|
||||
|
||||
const serviceCache = container.resolve('serviceCache');
|
||||
expect(serviceCache).toBeDefined();
|
||||
});
|
||||
});
|
||||
|
||||
describe('registerDatabaseServices', () => {
|
||||
it('should register MongoDB when config exists', () => {
|
||||
const container = createContainer();
|
||||
const mockLogger = {
|
||||
info: () => {},
|
||||
error: () => {},
|
||||
warn: () => {},
|
||||
debug: () => {},
|
||||
};
|
||||
|
||||
container.register({
|
||||
logger: asValue(mockLogger),
|
||||
});
|
||||
|
||||
const config = {
|
||||
service: {
|
||||
name: 'test-service',
|
||||
type: 'WORKER' as const,
|
||||
},
|
||||
mongodb: {
|
||||
uri: 'mongodb://localhost:27017',
|
||||
database: 'test-db',
|
||||
},
|
||||
};
|
||||
|
||||
registerDatabaseServices(container, config);
|
||||
|
||||
// Check that mongodb is registered
|
||||
const registrations = container.registrations;
|
||||
expect(registrations.mongodb).toBeDefined();
|
||||
});
|
||||
|
||||
it('should register Postgres when config exists', () => {
|
||||
const container = createContainer();
|
||||
const mockLogger = { info: () => {}, error: () => {} };
|
||||
|
||||
container.register({
|
||||
logger: asValue(mockLogger),
|
||||
});
|
||||
|
||||
const config = {
|
||||
service: {
|
||||
name: 'test-service',
|
||||
type: 'WORKER' as const,
|
||||
},
|
||||
postgres: {
|
||||
host: 'localhost',
|
||||
port: 5432,
|
||||
database: 'test-db',
|
||||
username: 'user',
|
||||
password: 'pass',
|
||||
},
|
||||
};
|
||||
|
||||
registerDatabaseServices(container, config);
|
||||
|
||||
const registrations = container.registrations;
|
||||
expect(registrations.postgres).toBeDefined();
|
||||
});
|
||||
|
||||
it('should register QuestDB when config exists', () => {
|
||||
const container = createContainer();
|
||||
const mockLogger = { info: () => {}, error: () => {} };
|
||||
|
||||
container.register({
|
||||
logger: asValue(mockLogger),
|
||||
});
|
||||
|
||||
const config = {
|
||||
service: {
|
||||
name: 'test-service',
|
||||
type: 'WORKER' as const,
|
||||
},
|
||||
questdb: {
|
||||
host: 'localhost',
|
||||
httpPort: 9000,
|
||||
pgPort: 8812,
|
||||
},
|
||||
};
|
||||
|
||||
registerDatabaseServices(container, config);
|
||||
|
||||
const registrations = container.registrations;
|
||||
expect(registrations.questdb).toBeDefined();
|
||||
});
|
||||
|
||||
it('should not register databases without config', () => {
|
||||
const container = createContainer();
|
||||
const config = {
|
||||
service: {
|
||||
name: 'test-service',
|
||||
type: 'WORKER' as const,
|
||||
},
|
||||
// No database configs
|
||||
};
|
||||
|
||||
registerDatabaseServices(container, config);
|
||||
|
||||
const registrations = container.registrations;
|
||||
expect(registrations.mongodb).toBeUndefined();
|
||||
expect(registrations.postgres).toBeUndefined();
|
||||
expect(registrations.questdb).toBeUndefined();
|
||||
});
|
||||
});
|
||||
|
||||
describe('registerServiceDependencies', () => {
|
||||
it('should register browser service when config exists', () => {
|
||||
const container = createContainer();
|
||||
const mockLogger = { info: () => {}, error: () => {} };
|
||||
|
||||
container.register({
|
||||
logger: asValue(mockLogger),
|
||||
config: asValue({
|
||||
browser: { headless: true },
|
||||
}),
|
||||
});
|
||||
|
||||
const config = {
|
||||
service: {
|
||||
name: 'test-service',
|
||||
type: 'WORKER' as const,
|
||||
},
|
||||
browser: {
|
||||
headless: true,
|
||||
timeout: 30000,
|
||||
},
|
||||
};
|
||||
|
||||
registerServiceDependencies(container, config);
|
||||
|
||||
const registrations = container.registrations;
|
||||
expect(registrations.browser).toBeDefined();
|
||||
});
|
||||
|
||||
it('should register proxy service when config exists', () => {
|
||||
const container = createContainer();
|
||||
const mockLogger = { info: () => {}, error: () => {} };
|
||||
|
||||
container.register({
|
||||
logger: asValue(mockLogger),
|
||||
});
|
||||
|
||||
const config = {
|
||||
service: {
|
||||
name: 'test-service',
|
||||
type: 'WORKER' as const,
|
||||
},
|
||||
proxy: {
|
||||
enabled: true,
|
||||
rotateOnError: true,
|
||||
},
|
||||
};
|
||||
|
||||
registerServiceDependencies(container, config);
|
||||
|
||||
const registrations = container.registrations;
|
||||
expect(registrations.proxyManager).toBeDefined();
|
||||
});
|
||||
|
||||
it('should register queue services for worker type', () => {
|
||||
const container = createContainer();
|
||||
const mockLogger = { info: () => {}, error: () => {} };
|
||||
|
||||
container.register({
|
||||
logger: asValue(mockLogger),
|
||||
config: asValue({
|
||||
service: { name: 'test-service', type: 'WORKER' },
|
||||
redis: { host: 'localhost', port: 6379 },
|
||||
}),
|
||||
});
|
||||
|
||||
const config = {
|
||||
service: {
|
||||
name: 'test-service',
|
||||
type: 'WORKER' as const,
|
||||
},
|
||||
redis: {
|
||||
host: 'localhost',
|
||||
port: 6379,
|
||||
},
|
||||
};
|
||||
|
||||
registerServiceDependencies(container, config);
|
||||
|
||||
const registrations = container.registrations;
|
||||
expect(registrations.queueManager).toBeDefined();
|
||||
});
|
||||
|
||||
it('should not register queue for API type', () => {
|
||||
const container = createContainer();
|
||||
const config = {
|
||||
service: {
|
||||
name: 'test-api',
|
||||
type: 'API' as const,
|
||||
},
|
||||
redis: {
|
||||
host: 'localhost',
|
||||
port: 6379,
|
||||
},
|
||||
};
|
||||
|
||||
registerServiceDependencies(container, config);
|
||||
|
||||
const registrations = container.registrations;
|
||||
expect(registrations.queueManager).toBeUndefined();
|
||||
});
|
||||
});
|
||||
})
|
||||
Loading…
Add table
Add a link
Reference in a new issue