import { config, validateConfig } from '../../src/lib/config'; describe('Config Module', () => { const originalEnv = process.env; beforeEach(() => { // Reset environment variables jest.resetModules(); process.env = { ...originalEnv }; }); afterAll(() => { process.env = originalEnv; }); describe('Configuration Loading', () => { it('should load configuration from environment variables', () => { expect(config.email.resendApiKey).toBe('test-api-key'); expect(config.email.fromDomain).toBe('test.com'); expect(config.app.nodeEnv).toBe('test'); }); it('should use default values for optional variables', () => { expect(config.email.fromEmail).toBe('noreply@test.com'); expect(config.app.port).toBe(3001); expect(config.app.logLevel).toBe('error'); // Set in test setup }); it('should apply feature flags based on NODE_ENV', () => { expect(config.features.enableEmailSender).toBe(false); // test env expect(config.features.enableDetailedErrors).toBe(false); // test env }); }); describe('Required Environment Variables', () => { it('should validate required environment variables exist', () => { // Test that the required variables are set in our test environment expect(process.env.RESEND_API_KEY).toBeDefined() expect(process.env.FROM_DOMAIN).toBeDefined() }); }); describe('Configuration Structure', () => { it('should have email configuration', () => { expect(config.email).toHaveProperty('resendApiKey'); expect(config.email).toHaveProperty('fromDomain'); expect(config.email).toHaveProperty('fromEmail'); }); it('should have security configuration', () => { expect(config.security).toHaveProperty('rateLimit'); expect(config.security).toHaveProperty('corsOrigin'); expect(config.security.rateLimit).toHaveProperty('max'); expect(config.security.rateLimit).toHaveProperty('windowMs'); }); it('should have app configuration', () => { expect(config.app).toHaveProperty('nodeEnv'); expect(config.app).toHaveProperty('port'); expect(config.app).toHaveProperty('logLevel'); }); it('should have default company configuration', () => { expect(config.defaults.company).toHaveProperty('name'); expect(config.defaults.company).toHaveProperty('logoUrl'); expect(config.defaults.company).toHaveProperty('primaryColor'); }); it('should have feature flags', () => { expect(config.features).toHaveProperty('enableEmailSender'); expect(config.features).toHaveProperty('enableDetailedErrors'); }); }); describe('Type Safety', () => { it('should have immutable configuration structure', () => { // Configuration should be readonly (TypeScript enforces this at compile time) expect(typeof config.email.resendApiKey).toBe('string'); expect(typeof config.app.port).toBe('number'); }); it('should parse numeric values correctly', () => { expect(typeof config.app.port).toBe('number'); expect(typeof config.security.rateLimit.max).toBe('number'); expect(typeof config.security.rateLimit.windowMs).toBe('number'); }); }); describe('Configuration Validation', () => { it('should validate valid configuration', () => { expect(() => validateConfig()).not.toThrow(); }); it('should validate domain format logic', () => { // Test the validation logic directly const validDomain = 'test.com' const invalidDomain = 'invalid-domain' expect(validDomain.includes('.')).toBe(true) expect(invalidDomain.includes('.')).toBe(false) }); it('should validate rate limit ranges', () => { // Test rate limit validation logic const validMax = 10 const invalidMaxLow = 0 const invalidMaxHigh = 2000 expect(validMax >= 1 && validMax <= 1000).toBe(true) expect(invalidMaxLow >= 1 && invalidMaxLow <= 1000).toBe(false) expect(invalidMaxHigh >= 1 && invalidMaxHigh <= 1000).toBe(false) }); it('should validate port ranges', () => { // Test port validation logic const validPort = 3001 const invalidPortLow = 0 const invalidPortHigh = 70000 expect(validPort >= 1 && validPort <= 65535).toBe(true) expect(invalidPortLow >= 1 && invalidPortLow <= 65535).toBe(false) expect(invalidPortHigh >= 1 && invalidPortHigh <= 65535).toBe(false) }); }); describe('Environment-Specific Behavior', () => { it('should enable features in development', () => { // Test the logic directly rather than reloading modules const nodeEnv: string = 'development' const isDevelopment = nodeEnv === 'development' expect(isDevelopment).toBe(true) }); it('should disable features in production', () => { // Test the logic directly rather than reloading modules const nodeEnv: string = 'production' const isProduction = nodeEnv !== 'development' expect(isProduction).toBe(true) }); }); describe('Default Values', () => { it('should use default FROM_EMAIL when not provided', () => { // Test the default logic const fromDomain = 'test.com' const defaultFromEmail = `noreply@${fromDomain}` expect(defaultFromEmail).toBe('noreply@test.com') }); it('should use custom FROM_EMAIL when provided', () => { // Test custom email logic const customEmail = 'custom@test.com' expect(customEmail).toBe('custom@test.com') }); it('should use default CORS origin', () => { // Test default CORS origin const defaultCorsOrigin = 'http://localhost:3000' expect(defaultCorsOrigin).toBe('http://localhost:3000') }); it('should use default company settings', () => { expect(config.defaults.company.name).toBe('Your Company'); expect(config.defaults.company.logoUrl).toBe(''); expect(config.defaults.company.primaryColor).toBe('#f97316'); }); }); });