import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest'; import { writeFileSync, mkdirSync, rmSync, existsSync } from 'fs'; import { resolve } from 'path'; import { loadConfig, findConfigFile } from '../src/config'; const TMP = resolve(__dirname, 'tmp-config'); function clean() { try { rmSync(TMP, { recursive: true, force: true }); } catch {} } describe('config', () => { beforeEach(() => { clean(); mkdirSync(TMP, { recursive: true }); }); afterEach(() => { clean(); vi.restoreAllMocks(); }); it('finds .codegov.yml', () => { writeFileSync(resolve(TMP, '.codegov.yml'), 'enabled: true\n'); expect(findConfigFile(TMP)).toBe(resolve(TMP, '.codegov.yml')); }); it('finds .codegov.json', () => { writeFileSync(resolve(TMP, '.codegov.json'), '{"enabled":true}'); expect(findConfigFile(TMP)).toBe(resolve(TMP, '.codegov.json')); }); it('returns null when no config exists', () => { expect(findConfigFile(TMP)).toBeNull(); }); it('loads JSON config', () => { writeFileSync(resolve(TMP, '.codegov.json'), JSON.stringify({ enabled: true, gates: { rfc: { required: false } } })); const { config, usingDefaults } = loadConfig(undefined, TMP); expect(config.enabled).toBe(true); expect(config.gates.rfc?.required).toBe(false); expect(usingDefaults).toBe(false); }); it('loads YAML config', () => { writeFileSync(resolve(TMP, '.codegov.yml'), 'enabled: true\ngates:\n disclosure:\n required: false\n'); const { config, usingDefaults } = loadConfig(undefined, TMP); expect(config.enabled).toBe(true); expect(config.gates.disclosure?.required).toBe(false); expect(usingDefaults).toBe(false); }); it('uses defaults when no config exists', () => { const { config, usingDefaults } = loadConfig(undefined, TMP); expect(config.enabled).toBe(true); expect(config.gates.disclosure?.required).toBe(true); expect(usingDefaults).toBe(true); }); it('merges partial config with defaults', () => { writeFileSync(resolve(TMP, '.codegov.json'), JSON.stringify({ enabled: false })); const { config } = loadConfig(undefined, TMP); expect(config.enabled).toBe(false); expect(config.gates.checklist?.required).toBe(true); }); it('throws on missing explicit config path', () => { expect(() => loadConfig('/nonexistent/.codegov.yml', TMP)).toThrow('Config file not found'); }); it('throws on invalid config', () => { writeFileSync(resolve(TMP, '.codegov.json'), 'not-json'); expect(() => loadConfig(undefined, TMP)).toThrow(); }); });