202 lines
5.5 KiB
TypeScript
202 lines
5.5 KiB
TypeScript
import { mkdirSync, rmSync, writeFileSync } from 'fs';
|
|
import { join } from 'path';
|
|
import { afterEach, beforeEach, describe, expect, test } from 'bun:test';
|
|
import {
|
|
getConfig,
|
|
getConfigManager,
|
|
getDatabaseConfig,
|
|
getLoggingConfig,
|
|
getProviderConfig,
|
|
getServiceConfig,
|
|
initializeConfig,
|
|
isDevelopment,
|
|
isProduction,
|
|
isTest,
|
|
resetConfig,
|
|
} from '../src';
|
|
|
|
describe('Config Module', () => {
|
|
const testConfigDir = join(process.cwd(), 'test-config-module');
|
|
const originalEnv = { ...process.env };
|
|
|
|
beforeEach(() => {
|
|
resetConfig();
|
|
mkdirSync(testConfigDir, { recursive: true });
|
|
|
|
// Create test configuration files
|
|
const config = {
|
|
name: 'test-app',
|
|
version: '1.0.0',
|
|
service: {
|
|
name: 'test-service',
|
|
port: 3000,
|
|
},
|
|
database: {
|
|
postgres: {
|
|
host: 'localhost',
|
|
port: 5432,
|
|
database: 'testdb',
|
|
user: 'testuser',
|
|
password: 'testpass',
|
|
},
|
|
questdb: {
|
|
host: 'localhost',
|
|
httpPort: 9000,
|
|
pgPort: 8812,
|
|
},
|
|
mongodb: {
|
|
host: 'localhost',
|
|
port: 27017,
|
|
database: 'testdb',
|
|
},
|
|
dragonfly: {
|
|
host: 'localhost',
|
|
port: 6379,
|
|
},
|
|
},
|
|
logging: {
|
|
level: 'info',
|
|
format: 'json',
|
|
},
|
|
providers: {
|
|
yahoo: {
|
|
enabled: true,
|
|
rateLimit: 5,
|
|
},
|
|
qm: {
|
|
enabled: false,
|
|
apiKey: 'test-key',
|
|
},
|
|
},
|
|
environment: 'test',
|
|
};
|
|
|
|
writeFileSync(join(testConfigDir, 'default.json'), JSON.stringify(config, null, 2));
|
|
});
|
|
|
|
afterEach(() => {
|
|
resetConfig();
|
|
rmSync(testConfigDir, { recursive: true, force: true });
|
|
process.env = { ...originalEnv };
|
|
});
|
|
|
|
test('should initialize configuration', async () => {
|
|
const config = await initializeConfig(testConfigDir);
|
|
|
|
expect(config.app.name).toBe('test-app');
|
|
expect(config.service.port).toBe(3000);
|
|
expect(config.environment).toBe('test');
|
|
});
|
|
|
|
test('should get configuration after initialization', async () => {
|
|
await initializeConfig(testConfigDir);
|
|
const config = getConfig();
|
|
|
|
expect(config.app.name).toBe('test-app');
|
|
expect(config.database.postgres.host).toBe('localhost');
|
|
});
|
|
|
|
test('should throw if getting config before initialization', () => {
|
|
expect(() => getConfig()).toThrow('Configuration not initialized');
|
|
});
|
|
|
|
test('should get config manager instance', async () => {
|
|
await initializeConfig(testConfigDir);
|
|
const manager = getConfigManager();
|
|
|
|
expect(manager).toBeDefined();
|
|
expect(manager.get().app.name).toBe('test-app');
|
|
});
|
|
|
|
test('should get database configuration', async () => {
|
|
await initializeConfig(testConfigDir);
|
|
const dbConfig = getDatabaseConfig();
|
|
|
|
expect(dbConfig.postgres.host).toBe('localhost');
|
|
expect(dbConfig.questdb.httpPort).toBe(9000);
|
|
expect(dbConfig.mongodb.database).toBe('testdb');
|
|
});
|
|
|
|
test('should get service configuration', async () => {
|
|
await initializeConfig(testConfigDir);
|
|
const serviceConfig = getServiceConfig();
|
|
|
|
expect(serviceConfig.name).toBe('test-service');
|
|
expect(serviceConfig.port).toBe(3000);
|
|
});
|
|
|
|
test('should get logging configuration', async () => {
|
|
await initializeConfig(testConfigDir);
|
|
const loggingConfig = getLoggingConfig();
|
|
|
|
expect(loggingConfig.level).toBe('info');
|
|
expect(loggingConfig.format).toBe('json');
|
|
});
|
|
|
|
test('should get provider configuration', async () => {
|
|
await initializeConfig(testConfigDir);
|
|
|
|
const yahooConfig = getProviderConfig('yahoo');
|
|
expect(yahooConfig.enabled).toBe(true);
|
|
expect(yahooConfig.rateLimit).toBe(5);
|
|
|
|
const qmConfig = getProviderConfig('quoteMedia');
|
|
expect(qmConfig.enabled).toBe(false);
|
|
expect(qmConfig.apiKey).toBe('test-key');
|
|
});
|
|
|
|
test('should throw for non-existent provider', async () => {
|
|
await initializeConfig(testConfigDir);
|
|
|
|
expect(() => getProviderConfig('nonexistent')).toThrow(
|
|
'Provider configuration not found: nonexistent'
|
|
);
|
|
});
|
|
|
|
test('should check environment correctly', async () => {
|
|
await initializeConfig(testConfigDir);
|
|
|
|
expect(isTest()).toBe(true);
|
|
expect(isDevelopment()).toBe(false);
|
|
expect(isProduction()).toBe(false);
|
|
});
|
|
|
|
test('should handle environment overrides', async () => {
|
|
process.env.NODE_ENV = 'production';
|
|
process.env.STOCKBOT_APP__NAME = 'env-override-app';
|
|
process.env.STOCKBOT_DATABASE__POSTGRES__HOST = 'prod-db';
|
|
|
|
const prodConfig = {
|
|
database: {
|
|
postgres: {
|
|
host: 'prod-host',
|
|
port: 5432,
|
|
},
|
|
},
|
|
};
|
|
|
|
writeFileSync(join(testConfigDir, 'production.json'), JSON.stringify(prodConfig, null, 2));
|
|
|
|
const config = await initializeConfig(testConfigDir);
|
|
|
|
expect(config.environment).toBe('production');
|
|
expect(config.app.name).toBe('env-override-app');
|
|
expect(config.database.postgres.host).toBe('prod-db');
|
|
expect(isProduction()).toBe(true);
|
|
});
|
|
|
|
test('should reset configuration', async () => {
|
|
await initializeConfig(testConfigDir);
|
|
expect(() => getConfig()).not.toThrow();
|
|
|
|
resetConfig();
|
|
expect(() => getConfig()).toThrow('Configuration not initialized');
|
|
});
|
|
|
|
test('should maintain singleton instance', async () => {
|
|
const config1 = await initializeConfig(testConfigDir);
|
|
const config2 = await initializeConfig(testConfigDir);
|
|
|
|
expect(config1).toBe(config2);
|
|
});
|
|
});
|