Files
rxminder/services/__tests__/mailgun.config.test.ts
William Valentin 22e996e698 Refactor Mailgun config to use getEnvVar and improve checks
- Replace getEnv with getEnvVar for environment variable access - Update
MailgunConfig types to allow undefined values - Enhance
isMailgunConfigured to check for undefined and empty values - Update
isDevelopmentMode to check production status - Improve test mocks for
environment variable handling
2025-09-07 18:36:55 -07:00

412 lines
14 KiB
TypeScript

import {
getMailgunConfig,
isMailgunConfigured,
isDevelopmentMode,
} from '../mailgun.config';
// Mock environment utilities
jest.mock('../../utils/env', () => ({
getEnvVar: jest.fn(),
isProduction: jest.fn(),
}));
describe('Mailgun Configuration', () => {
let mockGetEnvVar: jest.MockedFunction<any>;
let mockIsProduction: jest.MockedFunction<any>;
beforeEach(() => {
jest.clearAllMocks();
// Get mocked functions
const envUtils = require('../../utils/env');
mockGetEnvVar = envUtils.getEnvVar;
mockIsProduction = envUtils.isProduction;
// Default mock implementations
mockIsProduction.mockReturnValue(false);
});
describe('getMailgunConfig', () => {
test('should return config with all environment variables set', () => {
mockGetEnvVar
.mockReturnValueOnce('test-api-key') // VITE_MAILGUN_API_KEY
.mockReturnValueOnce('test.domain.com') // VITE_MAILGUN_DOMAIN
.mockReturnValueOnce('https://api.mailgun.net/v3') // VITE_MAILGUN_BASE_URL
.mockReturnValueOnce('Test App') // VITE_MAILGUN_FROM_NAME
.mockReturnValueOnce('noreply@test.com'); // VITE_MAILGUN_FROM_EMAIL
const config = getMailgunConfig();
expect(config).toEqual({
apiKey: 'test-api-key',
domain: 'test.domain.com',
baseUrl: 'https://api.mailgun.net/v3',
fromName: 'Test App',
fromEmail: 'noreply@test.com',
});
expect(mockGetEnvVar).toHaveBeenCalledTimes(5);
expect(mockGetEnvVar).toHaveBeenNthCalledWith(1, 'VITE_MAILGUN_API_KEY');
expect(mockGetEnvVar).toHaveBeenNthCalledWith(2, 'VITE_MAILGUN_DOMAIN');
expect(mockGetEnvVar).toHaveBeenNthCalledWith(
3,
'VITE_MAILGUN_BASE_URL',
'https://api.mailgun.net/v3'
);
expect(mockGetEnvVar).toHaveBeenNthCalledWith(
4,
'VITE_MAILGUN_FROM_NAME',
'Medication Reminder'
);
expect(mockGetEnvVar).toHaveBeenNthCalledWith(
5,
'VITE_MAILGUN_FROM_EMAIL'
);
});
test('should use default values for optional config', () => {
mockGetEnvVar.mockImplementation((key: string, defaultValue?: string) => {
if (key === 'VITE_MAILGUN_API_KEY') return 'test-api-key';
if (key === 'VITE_MAILGUN_DOMAIN') return 'test.domain.com';
if (key === 'VITE_MAILGUN_FROM_EMAIL') return 'noreply@test.com';
return defaultValue;
});
const config = getMailgunConfig();
expect(config.baseUrl).toBe('https://api.mailgun.net/v3');
expect(config.fromName).toBe('Medication Reminder');
});
test('should handle missing environment variables gracefully', () => {
mockGetEnvVar.mockImplementation(
(_key: string, defaultValue?: string) => defaultValue
);
const config = getMailgunConfig();
expect(config).toEqual({
apiKey: undefined,
domain: undefined,
baseUrl: 'https://api.mailgun.net/v3',
fromName: 'Medication Reminder',
fromEmail: undefined,
});
});
test('should handle empty string environment variables', () => {
mockGetEnvVar.mockImplementation(
(key: string, _defaultValue?: string) => {
if (key === 'VITE_MAILGUN_API_KEY') return '';
if (key === 'VITE_MAILGUN_DOMAIN') return '';
if (key === 'VITE_MAILGUN_FROM_EMAIL') return '';
if (key === 'VITE_MAILGUN_BASE_URL') return '';
if (key === 'VITE_MAILGUN_FROM_NAME') return '';
return undefined;
}
);
const config = getMailgunConfig();
expect(config.apiKey).toBe('');
expect(config.domain).toBe('');
expect(config.baseUrl).toBe('');
expect(config.fromName).toBe('');
expect(config.fromEmail).toBe('');
});
});
describe('isMailgunConfigured', () => {
test('should return true when all required config is present', () => {
mockGetEnvVar.mockImplementation((key: string, defaultValue?: string) => {
switch (key) {
case 'VITE_MAILGUN_API_KEY':
return 'test-api-key';
case 'VITE_MAILGUN_DOMAIN':
return 'test.domain.com';
case 'VITE_MAILGUN_FROM_EMAIL':
return 'noreply@test.com';
case 'VITE_MAILGUN_BASE_URL':
return 'https://api.mailgun.net/v3';
case 'VITE_MAILGUN_FROM_NAME':
return 'Test App';
default:
return defaultValue;
}
});
expect(isMailgunConfigured()).toBe(true);
});
test('should return false when apiKey is missing', () => {
mockGetEnvVar.mockImplementation((key: string, defaultValue?: string) => {
switch (key) {
case 'VITE_MAILGUN_API_KEY':
return undefined;
case 'VITE_MAILGUN_DOMAIN':
return 'test.domain.com';
case 'VITE_MAILGUN_FROM_EMAIL':
return 'noreply@test.com';
case 'VITE_MAILGUN_BASE_URL':
return 'https://api.mailgun.net/v3';
case 'VITE_MAILGUN_FROM_NAME':
return 'Test App';
default:
return defaultValue;
}
});
expect(isMailgunConfigured()).toBe(false);
});
test('should return false when domain is missing', () => {
mockGetEnvVar.mockImplementation((key: string, defaultValue?: string) => {
switch (key) {
case 'VITE_MAILGUN_API_KEY':
return 'test-api-key';
case 'VITE_MAILGUN_DOMAIN':
return undefined;
case 'VITE_MAILGUN_FROM_EMAIL':
return 'noreply@test.com';
case 'VITE_MAILGUN_BASE_URL':
return 'https://api.mailgun.net/v3';
case 'VITE_MAILGUN_FROM_NAME':
return 'Test App';
default:
return defaultValue;
}
});
expect(isMailgunConfigured()).toBe(false);
});
test('should return false when fromEmail is missing', () => {
mockGetEnvVar.mockImplementation((key: string, defaultValue?: string) => {
switch (key) {
case 'VITE_MAILGUN_API_KEY':
return 'test-api-key';
case 'VITE_MAILGUN_DOMAIN':
return 'test.domain.com';
case 'VITE_MAILGUN_FROM_EMAIL':
return undefined;
case 'VITE_MAILGUN_BASE_URL':
return 'https://api.mailgun.net/v3';
case 'VITE_MAILGUN_FROM_NAME':
return 'Test App';
default:
return defaultValue;
}
});
expect(isMailgunConfigured()).toBe(false);
});
test('should return false when apiKey is empty string', () => {
mockGetEnvVar.mockImplementation((key: string, defaultValue?: string) => {
switch (key) {
case 'VITE_MAILGUN_API_KEY':
return '';
case 'VITE_MAILGUN_DOMAIN':
return 'test.domain.com';
case 'VITE_MAILGUN_FROM_EMAIL':
return 'noreply@test.com';
case 'VITE_MAILGUN_BASE_URL':
return 'https://api.mailgun.net/v3';
case 'VITE_MAILGUN_FROM_NAME':
return 'Test App';
default:
return defaultValue;
}
});
expect(isMailgunConfigured()).toBe(false);
});
test('should return false when domain is empty string', () => {
mockGetEnvVar.mockImplementation((key: string, defaultValue?: string) => {
switch (key) {
case 'VITE_MAILGUN_API_KEY':
return 'test-api-key';
case 'VITE_MAILGUN_DOMAIN':
return '';
case 'VITE_MAILGUN_FROM_EMAIL':
return 'noreply@test.com';
case 'VITE_MAILGUN_BASE_URL':
return 'https://api.mailgun.net/v3';
case 'VITE_MAILGUN_FROM_NAME':
return 'Test App';
default:
return defaultValue;
}
});
expect(isMailgunConfigured()).toBe(false);
});
test('should return false when fromEmail is empty string', () => {
mockGetEnvVar.mockImplementation((key: string, defaultValue?: string) => {
switch (key) {
case 'VITE_MAILGUN_API_KEY':
return 'test-api-key';
case 'VITE_MAILGUN_DOMAIN':
return 'test.domain.com';
case 'VITE_MAILGUN_FROM_EMAIL':
return '';
case 'VITE_MAILGUN_BASE_URL':
return 'https://api.mailgun.net/v3';
case 'VITE_MAILGUN_FROM_NAME':
return 'Test App';
default:
return defaultValue;
}
});
expect(isMailgunConfigured()).toBe(false);
});
test('should return true even when optional fields are missing', () => {
// Provide only required fields (optional ones fall back to defaults)
mockGetEnvVar.mockImplementation((key: string, defaultValue?: string) => {
switch (key) {
case 'VITE_MAILGUN_API_KEY':
return 'test-api-key';
case 'VITE_MAILGUN_DOMAIN':
return 'test.domain.com';
case 'VITE_MAILGUN_FROM_EMAIL':
return 'noreply@test.com';
// baseUrl and fromName return undefined so defaults are applied
default:
return defaultValue;
}
});
expect(isMailgunConfigured()).toBe(true);
});
test('should handle whitespace strings correctly', () => {
mockGetEnvVar.mockImplementation((key: string, defaultValue?: string) => {
switch (key) {
case 'VITE_MAILGUN_API_KEY':
return ' test-key ';
case 'VITE_MAILGUN_DOMAIN':
return ' test.domain.com ';
case 'VITE_MAILGUN_FROM_EMAIL':
return ' test@example.com ';
case 'VITE_MAILGUN_BASE_URL':
return 'https://api.mailgun.net/v3';
case 'VITE_MAILGUN_FROM_NAME':
return 'Test App';
default:
return defaultValue;
}
});
expect(isMailgunConfigured()).toBe(true);
});
});
describe('isDevelopmentMode', () => {
test('should return true when not in production and Mailgun not configured', () => {
mockIsProduction.mockReturnValue(false);
mockGetEnvVar.mockReturnValue(undefined);
expect(isDevelopmentMode()).toBe(true);
});
test('should return false when in production even if Mailgun not configured', () => {
mockIsProduction.mockReturnValue(true);
expect(isDevelopmentMode()).toBe(false);
});
test('should return false when Mailgun is configured regardless of environment', () => {
mockIsProduction.mockReturnValue(false);
mockGetEnvVar
.mockReturnValueOnce('test-api-key')
.mockReturnValueOnce('test.domain.com')
.mockReturnValueOnce('https://api.mailgun.net/v3')
.mockReturnValueOnce('Test App')
.mockReturnValueOnce('noreply@test.com');
expect(isDevelopmentMode()).toBe(false);
});
test('should return false when in production and Mailgun is configured', () => {
mockIsProduction.mockReturnValue(true);
mockGetEnvVar
.mockReturnValueOnce('test-api-key')
.mockReturnValueOnce('test.domain.com')
.mockReturnValueOnce('https://api.mailgun.net/v3')
.mockReturnValueOnce('Test App')
.mockReturnValueOnce('noreply@test.com');
expect(isDevelopmentMode()).toBe(false);
});
});
// Removed validateMailgunConfig tests because validateMailgunConfig is not exported
describe('integration scenarios', () => {
test('should work with real environment configuration flow', () => {
// Clear any previous mock implementations
mockGetEnvVar.mockReset();
// Provide stable implementation for multiple calls
mockGetEnvVar.mockImplementation((key: string, defaultValue?: string) => {
switch (key) {
case 'VITE_MAILGUN_API_KEY':
return 'real-api-key';
case 'VITE_MAILGUN_DOMAIN':
return 'mg.example.com';
case 'VITE_MAILGUN_BASE_URL':
return 'https://api.mailgun.net/v3';
case 'VITE_MAILGUN_FROM_NAME':
return 'My App';
case 'VITE_MAILGUN_FROM_EMAIL':
return 'support@example.com';
default:
return defaultValue;
}
});
const config = getMailgunConfig();
expect(isMailgunConfigured()).toBe(true);
expect(isDevelopmentMode()).toBe(false);
// validateMailgunConfig not tested because not exported
expect(config).toEqual({
apiKey: 'real-api-key',
domain: 'mg.example.com',
baseUrl: 'https://api.mailgun.net/v3',
fromName: 'My App',
fromEmail: 'support@example.com',
});
});
test('should work with development environment flow', () => {
// Simulate development environment with no config
mockGetEnvVar.mockReturnValue(undefined);
mockIsProduction.mockReturnValue(false);
const config = getMailgunConfig();
expect(isMailgunConfigured()).toBe(false);
expect(isDevelopmentMode()).toBe(true);
// validateMailgunConfig not tested because not exported
expect(config.apiKey).toBeUndefined();
});
test('should work with production environment without config (error case)', () => {
// Simulate production environment without proper config
mockGetEnvVar.mockReturnValue(undefined);
mockIsProduction.mockReturnValue(true);
const config = getMailgunConfig();
expect(isMailgunConfigured()).toBe(false);
expect(isDevelopmentMode()).toBe(false);
// validateMailgunConfig not tested because not exported
expect(config.apiKey).toBeUndefined();
});
});
});