import { describe, test, expect, beforeEach, afterEach } from 'bun:test'; import { writeFileSync, mkdirSync, rmSync } from 'fs'; import { join } from 'path'; import { initializeConfig, getConfig, getConfigManager, resetConfig, getDatabaseConfig, getServiceConfig, getLoggingConfig, getProviderConfig, isDevelopment, isProduction, isTest, } 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 = { app: { name: 'test-app', version: '1.0.0', }, service: { name: 'test-service', port: 3000, }, database: { postgres: { host: 'localhost', port: 5432, database: 'testdb', username: 'testuser', password: 'testpass', }, questdb: { host: 'localhost', httpPort: 9000, pgPort: 8812, }, mongodb: { uri: 'mongodb://localhost:27017', database: 'testdb', }, dragonfly: { host: 'localhost', port: 6379, }, }, logging: { level: 'info', format: 'json', }, providers: { yahoo: { enabled: true, rateLimit: 5, }, quoteMedia: { enabled: false, apiKey: 'test-key', }, }, features: { realtime: true, backtesting: true, }, 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); }); });