created lots of tests

This commit is contained in:
Boki 2025-06-25 09:20:53 -04:00
parent 42baadae38
commit 54f37f9521
21 changed files with 4577 additions and 215 deletions

View 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();
});
});
})