196 lines
5.4 KiB
TypeScript
196 lines
5.4 KiB
TypeScript
import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest'
|
|
import { resolveConfig } from '../../config/merge.js'
|
|
|
|
// Mock the loader module to avoid file system access
|
|
vi.mock('../../config/loader.js', () => ({
|
|
loadConfig: vi.fn().mockResolvedValue({ config: {}, filePath: null }),
|
|
}))
|
|
|
|
describe('resolveConfig', () => {
|
|
const originalEnv = process.env
|
|
|
|
beforeEach(() => {
|
|
process.env = { ...originalEnv }
|
|
// Clear any MAILDEV_ env vars
|
|
Object.keys(process.env).forEach((key) => {
|
|
if (key.startsWith('MAILDEV_')) {
|
|
delete process.env[key]
|
|
}
|
|
})
|
|
})
|
|
|
|
afterEach(() => {
|
|
process.env = originalEnv
|
|
vi.clearAllMocks()
|
|
})
|
|
|
|
it('should return default config when no options provided', async () => {
|
|
const { config } = await resolveConfig({})
|
|
|
|
expect(config.smtp).toBe(1025)
|
|
expect(config.web).toBe(1080)
|
|
expect(config.ip).toBe('::')
|
|
expect(config.webIp).toBe('0.0.0.0')
|
|
expect(config.basePathname).toBe('/')
|
|
expect(config.verbose).toBe(false)
|
|
expect(config.mcp).toBe(false)
|
|
})
|
|
|
|
it('should apply CLI options over defaults', async () => {
|
|
const { config } = await resolveConfig({
|
|
smtp: '2025',
|
|
web: '3080',
|
|
verbose: true,
|
|
})
|
|
|
|
expect(config.smtp).toBe(2025)
|
|
expect(config.web).toBe(3080)
|
|
expect(config.verbose).toBe(true)
|
|
})
|
|
|
|
it('should apply environment variables over defaults', async () => {
|
|
process.env.MAILDEV_SMTP_PORT = '4025'
|
|
process.env.MAILDEV_WEB_PORT = '5080'
|
|
|
|
const { config } = await resolveConfig({})
|
|
|
|
expect(config.smtp).toBe(4025)
|
|
expect(config.web).toBe(5080)
|
|
})
|
|
|
|
it('should prioritize CLI options over environment variables', async () => {
|
|
process.env.MAILDEV_SMTP_PORT = '4025'
|
|
|
|
const { config } = await resolveConfig({
|
|
smtp: '5025',
|
|
})
|
|
|
|
expect(config.smtp).toBe(5025)
|
|
})
|
|
|
|
it('should parse string port options as numbers', async () => {
|
|
const { config } = await resolveConfig({
|
|
smtp: '9025',
|
|
web: '9080',
|
|
outgoingPort: '587',
|
|
})
|
|
|
|
expect(config.smtp).toBe(9025)
|
|
expect(typeof config.smtp).toBe('number')
|
|
expect(config.web).toBe(9080)
|
|
expect(typeof config.web).toBe('number')
|
|
expect(config.outgoingPort).toBe(587)
|
|
expect(typeof config.outgoingPort).toBe('number')
|
|
})
|
|
|
|
it('should handle string options correctly', async () => {
|
|
const { config } = await resolveConfig({
|
|
ip: '127.0.0.1',
|
|
webIp: '192.168.1.1',
|
|
basePathname: '/mail/',
|
|
incomingUser: 'smtp_user',
|
|
incomingPass: 'smtp_pass',
|
|
})
|
|
|
|
expect(config.ip).toBe('127.0.0.1')
|
|
expect(config.webIp).toBe('192.168.1.1')
|
|
expect(config.basePathname).toBe('/mail/')
|
|
expect(config.incomingUser).toBe('smtp_user')
|
|
expect(config.incomingPass).toBe('smtp_pass')
|
|
})
|
|
|
|
it('should handle boolean options correctly', async () => {
|
|
const { config } = await resolveConfig({
|
|
verbose: true,
|
|
silent: false,
|
|
mcp: true,
|
|
disableWeb: true,
|
|
})
|
|
|
|
expect(config.verbose).toBe(true)
|
|
expect(config.silent).toBe(false)
|
|
expect(config.mcp).toBe(true)
|
|
expect(config.disableWeb).toBe(true)
|
|
})
|
|
|
|
it('should handle auto-relay as boolean', async () => {
|
|
const { config } = await resolveConfig({
|
|
autoRelay: true,
|
|
})
|
|
|
|
expect(config.autoRelay).toBe(true)
|
|
})
|
|
|
|
it('should handle auto-relay as email string', async () => {
|
|
const { config } = await resolveConfig({
|
|
autoRelay: 'test@example.com',
|
|
})
|
|
|
|
expect(config.autoRelay).toBe('test@example.com')
|
|
})
|
|
|
|
it('should parse hideExtensions as array', async () => {
|
|
const { config } = await resolveConfig({
|
|
hideExtensions: 'STARTTLS,PIPELINING',
|
|
})
|
|
|
|
expect(config.hideExtensions).toEqual(['STARTTLS', 'PIPELINING'])
|
|
})
|
|
|
|
it('should handle hideExtensions with spaces', async () => {
|
|
const { config } = await resolveConfig({
|
|
hideExtensions: ' STARTTLS , PIPELINING , 8BITMIME ',
|
|
})
|
|
|
|
expect(config.hideExtensions).toEqual(['STARTTLS', 'PIPELINING', '8BITMIME'])
|
|
})
|
|
|
|
it('should convert hideExtensions to uppercase', async () => {
|
|
const { config } = await resolveConfig({
|
|
hideExtensions: 'starttls,pipelining',
|
|
})
|
|
|
|
expect(config.hideExtensions).toEqual(['STARTTLS', 'PIPELINING'])
|
|
})
|
|
|
|
it('should handle outgoing relay options', async () => {
|
|
const { config } = await resolveConfig({
|
|
outgoingHost: 'smtp.example.com',
|
|
outgoingPort: '587',
|
|
outgoingUser: 'relay_user',
|
|
outgoingPass: 'relay_pass',
|
|
outgoingSecure: true,
|
|
})
|
|
|
|
expect(config.outgoingHost).toBe('smtp.example.com')
|
|
expect(config.outgoingPort).toBe(587)
|
|
expect(config.outgoingUser).toBe('relay_user')
|
|
expect(config.outgoingPass).toBe('relay_pass')
|
|
expect(config.outgoingSecure).toBe(true)
|
|
})
|
|
|
|
it('should handle mail directory option', async () => {
|
|
const { config } = await resolveConfig({
|
|
mailDirectory: '/var/mail/test',
|
|
})
|
|
|
|
expect(config.mailDirectory).toBe('/var/mail/test')
|
|
})
|
|
|
|
it('should return null configFilePath when no config file found', async () => {
|
|
const { configFilePath } = await resolveConfig({})
|
|
|
|
expect(configFilePath).toBeNull()
|
|
})
|
|
|
|
it('should not override defined values when CLI options not provided', async () => {
|
|
process.env.MAILDEV_SMTP_PORT = '4025'
|
|
|
|
// Not providing smtp option at all (vs providing undefined)
|
|
const { config } = await resolveConfig({})
|
|
|
|
// Environment variable should apply
|
|
expect(config.smtp).toBe(4025)
|
|
})
|
|
})
|