import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest'; import { loadPluginConfig, getCodexMode } from '../lib/config.js'; import type { PluginConfig } from '../lib/types.js'; import * as fs from 'node:fs'; import * as os from 'node:os'; import * as path from 'node:path'; // Mock the fs module vi.mock('node:fs', async () => { const actual = await vi.importActual('node:fs'); return { ...actual, existsSync: vi.fn(), readFileSync: vi.fn(), }; }); describe('Plugin Configuration', () => { const mockExistsSync = vi.mocked(fs.existsSync); const mockReadFileSync = vi.mocked(fs.readFileSync); let originalEnv: string | undefined; beforeEach(() => { originalEnv = process.env.CODEX_MODE; vi.clearAllMocks(); }); afterEach(() => { if (originalEnv === undefined) { delete process.env.CODEX_MODE; } else { process.env.CODEX_MODE = originalEnv; } }); describe('loadPluginConfig', () => { it('should return default config when file does not exist', () => { mockExistsSync.mockReturnValue(false); const config = loadPluginConfig(); expect(config).toEqual({ codexMode: true }); expect(mockExistsSync).toHaveBeenCalledWith( path.join(os.homedir(), '.opencode', 'openai-codex-auth-config.json') ); }); it('should load config from file when it exists', () => { mockExistsSync.mockReturnValue(true); mockReadFileSync.mockReturnValue(JSON.stringify({ codexMode: false })); const config = loadPluginConfig(); expect(config).toEqual({ codexMode: false }); }); it('should merge user config with defaults', () => { mockExistsSync.mockReturnValue(true); mockReadFileSync.mockReturnValue(JSON.stringify({})); const config = loadPluginConfig(); expect(config).toEqual({ codexMode: true }); }); it('should handle invalid JSON gracefully', () => { mockExistsSync.mockReturnValue(true); mockReadFileSync.mockReturnValue('invalid json'); const consoleSpy = vi.spyOn(console, 'warn').mockImplementation(() => {}); const config = loadPluginConfig(); expect(config).toEqual({ codexMode: true }); expect(consoleSpy).toHaveBeenCalled(); consoleSpy.mockRestore(); }); it('should handle file read errors gracefully', () => { mockExistsSync.mockReturnValue(true); mockReadFileSync.mockImplementation(() => { throw new Error('Permission denied'); }); const consoleSpy = vi.spyOn(console, 'warn').mockImplementation(() => {}); const config = loadPluginConfig(); expect(config).toEqual({ codexMode: true }); expect(consoleSpy).toHaveBeenCalled(); consoleSpy.mockRestore(); }); }); describe('getCodexMode', () => { it('should return true by default', () => { delete process.env.CODEX_MODE; const config: PluginConfig = {}; const result = getCodexMode(config); expect(result).toBe(true); }); it('should use config value when env var not set', () => { delete process.env.CODEX_MODE; const config: PluginConfig = { codexMode: false }; const result = getCodexMode(config); expect(result).toBe(false); }); it('should prioritize env var CODEX_MODE=1 over config', () => { process.env.CODEX_MODE = '1'; const config: PluginConfig = { codexMode: false }; const result = getCodexMode(config); expect(result).toBe(true); }); it('should prioritize env var CODEX_MODE=0 over config', () => { process.env.CODEX_MODE = '0'; const config: PluginConfig = { codexMode: true }; const result = getCodexMode(config); expect(result).toBe(false); }); it('should handle env var with any value other than "1" as false', () => { process.env.CODEX_MODE = 'false'; const config: PluginConfig = { codexMode: true }; const result = getCodexMode(config); expect(result).toBe(false); }); it('should use config codexMode=true when explicitly set', () => { delete process.env.CODEX_MODE; const config: PluginConfig = { codexMode: true }; const result = getCodexMode(config); expect(result).toBe(true); }); }); describe('Priority order', () => { it('should follow priority: env var > config file > default', () => { // Test 1: env var overrides config process.env.CODEX_MODE = '0'; expect(getCodexMode({ codexMode: true })).toBe(false); // Test 2: config overrides default delete process.env.CODEX_MODE; expect(getCodexMode({ codexMode: false })).toBe(false); // Test 3: default when neither set expect(getCodexMode({})).toBe(true); }); }); });