Files
BIPMaterialManager/tests/unit/config-manager.test.ts
Misaka fc71b2a585 fix(test): replace meaningless assertions with behavior-based tests across 7 test files
Replace toBeDefined()/typeof checks with assertions that verify actual
behavior and output content. Key changes:

- locators: assert actual CSS selector values instead of existence
- logger-integration: test run()/getContext()/withRequestContext() behavior
- logger: verify winstonCalls content (level, message, metadata)
- config-manager: test default values, singleton, and getConfig() throws
- erp-auth: remove empty Class Structure block (covered by behavior tests)
- audit-logger: spy on auditLogger.info to verify JSONL entry content
- extractor: remove Math.ceil tests, verify error result structure

Net: -209 lines of hollow/redundant test code.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-04 22:07:09 +08:00

160 lines
5.5 KiB
TypeScript

/**
* ConfigManager Unit Tests
*
* Tests for ConfigManager default configuration values, schema validation,
* and singleton behavior.
* Logger is mocked to isolate ConfigManager testing.
*/
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest'
// Mock logger to prevent initialization issues
vi.mock('../../src/main/services/logger', () => ({
createLogger: vi.fn(() => ({
info: vi.fn(),
error: vi.fn(),
warn: vi.fn(),
debug: vi.fn()
})),
applyLoggingConfig: vi.fn(),
trackDuration: vi.fn()
}))
// Mock audit-logger
vi.mock('../../src/main/services/logger/audit-logger', () => ({
applyAuditConfig: vi.fn()
}))
describe('ConfigManager', () => {
beforeEach(() => {
vi.clearAllMocks()
})
afterEach(() => {
vi.resetModules()
})
it('should return default config with correct logging values', async () => {
const { ConfigManager } = await import('../../src/main/services/config/config-manager')
const manager = ConfigManager.getInstance()
const defaultConfig = manager.getDefaultConfig()
expect(defaultConfig.logging.level).toBe('info')
expect(defaultConfig.logging.auditRetention).toBe(30)
expect(defaultConfig.logging.appRetention).toBe(14)
})
it('should return default config with correct database defaults', async () => {
const { ConfigManager } = await import('../../src/main/services/config/config-manager')
const manager = ConfigManager.getInstance()
const defaultConfig = manager.getDefaultConfig()
expect(defaultConfig.database.activeType).toBe('mysql')
expect(defaultConfig.database.mysql.host).toBe('localhost')
expect(defaultConfig.database.mysql.port).toBe(3306)
expect(defaultConfig.database.mysql.database).toBe('erp_db')
})
it('should return default config with correct extraction defaults', async () => {
const { ConfigManager } = await import('../../src/main/services/config/config-manager')
const manager = ConfigManager.getInstance()
const defaultConfig = manager.getDefaultConfig()
expect(defaultConfig.extraction.batchSize).toBe(100)
expect(defaultConfig.extraction.headless).toBe(true)
expect(defaultConfig.extraction.autoConvert).toBe(true)
})
it('should throw when getConfig() is called before initialize()', async () => {
const { ConfigManager } = await import('../../src/main/services/config/config-manager')
// Reset singleton to get a fresh uninitialized instance
const FreshConfigManager = ConfigManager as any
FreshConfigManager.instance = null
const manager = ConfigManager.getInstance()
expect(() => manager.getConfig()).toThrow('Configuration not initialized')
})
it('should return the same singleton instance', async () => {
const { ConfigManager } = await import('../../src/main/services/config/config-manager')
const a = ConfigManager.getInstance()
const b = ConfigManager.getInstance()
expect(a).toBe(b)
})
})
describe('Config Schema Validation', () => {
it('should validate complete logging configuration', async () => {
const { loggingConfigSchema } = await import('../../src/main/types/config.schema')
const validConfig = {
level: 'debug' as const,
auditRetention: 60,
appRetention: 21
}
const result = loggingConfigSchema.safeParse(validConfig)
expect(result.success).toBe(true)
if (result.success) {
expect(result.data.level).toBe('debug')
expect(result.data.auditRetention).toBe(60)
expect(result.data.appRetention).toBe(21)
}
})
it('should validate logging level enum values', async () => {
const { loggingConfigSchema } = await import('../../src/main/types/config.schema')
const validLevels = ['error', 'warn', 'info', 'debug', 'verbose']
for (const level of validLevels) {
const result = loggingConfigSchema.safeParse({ level })
expect(result.success).toBe(true)
}
})
it('should reject invalid logging level', async () => {
const { loggingConfigSchema } = await import('../../src/main/types/config.schema')
const result = loggingConfigSchema.safeParse({ level: 'invalid_level' })
expect(result.success).toBe(false)
})
it('should validate audit retention range (1-365)', async () => {
const { loggingConfigSchema } = await import('../../src/main/types/config.schema')
expect(loggingConfigSchema.safeParse({ auditRetention: 1 }).success).toBe(true)
expect(loggingConfigSchema.safeParse({ auditRetention: 365 }).success).toBe(true)
expect(loggingConfigSchema.safeParse({ auditRetention: 0 }).success).toBe(false)
expect(loggingConfigSchema.safeParse({ auditRetention: 366 }).success).toBe(false)
})
it('should validate app retention range (1-365)', async () => {
const { loggingConfigSchema } = await import('../../src/main/types/config.schema')
expect(loggingConfigSchema.safeParse({ appRetention: 1 }).success).toBe(true)
expect(loggingConfigSchema.safeParse({ appRetention: 365 }).success).toBe(true)
expect(loggingConfigSchema.safeParse({ appRetention: 0 }).success).toBe(false)
expect(loggingConfigSchema.safeParse({ appRetention: 366 }).success).toBe(false)
})
it('should use default values when logging config is partial', async () => {
const { loggingConfigSchema } = await import('../../src/main/types/config.schema')
const result = loggingConfigSchema.safeParse({ level: 'warn' })
expect(result.success).toBe(true)
if (result.success) {
expect(result.data.auditRetention).toBe(30)
expect(result.data.appRetention).toBe(14)
}
})
})