UNPKG

@meldscience/meld

Version:

pipeable one-shot prompt scripting toolkit

150 lines (124 loc) 4.99 kB
import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest'; import { loadConfig, setupConfig, RC_FILE } from '../src/config'; import { writeFileSync, unlinkSync, existsSync, readFileSync } from 'fs'; import { join } from 'path'; import { homedir } from 'os'; import { execSync } from 'child_process'; // Mock execSync vi.mock('child_process', () => ({ execSync: vi.fn() })); const RC_PATH = join(homedir(), RC_FILE); describe('Config', () => { let originalRcContent: string | null = null; let originalEnv: NodeJS.ProcessEnv; beforeEach(() => { // Backup environment originalEnv = { ...process.env }; // Clear environment variables we're testing delete process.env.ANTHROPIC_API_KEY; delete process.env.OPENAI_API_KEY; delete process.env.DEFAULT_MODEL; // Backup existing config if it exists if (existsSync(RC_PATH)) { originalRcContent = readFileSync(RC_PATH, 'utf-8'); unlinkSync(RC_PATH); // Remove the file for clean tests } // Reset execSync mock vi.mocked(execSync).mockReset(); }); afterEach(() => { // Restore environment process.env = originalEnv; // Restore original config or remove test config if (originalRcContent) { writeFileSync(RC_PATH, originalRcContent); } else if (existsSync(RC_PATH)) { unlinkSync(RC_PATH); } }); it('should load config from environment variables', () => { // Set environment variables process.env.ANTHROPIC_API_KEY = 'test-anthropic-key'; process.env.OPENAI_API_KEY = 'test-openai-key'; process.env.DEFAULT_MODEL = 'test-model'; // Debug: Print environment variables console.log('Environment variables before loadConfig:'); console.log('ANTHROPIC_API_KEY:', process.env.ANTHROPIC_API_KEY); console.log('OPENAI_API_KEY:', process.env.OPENAI_API_KEY); console.log('DEFAULT_MODEL:', process.env.DEFAULT_MODEL); const config = loadConfig(); // Debug: Print loaded config console.log('Loaded config:'); console.log('config.anthropicApiKey:', config.anthropicApiKey); console.log('config.openaiApiKey:', config.openaiApiKey); console.log('config.defaultModel:', config.defaultModel); expect(config.anthropicApiKey).toBe('test-anthropic-key'); expect(config.openaiApiKey).toBe('test-openai-key'); expect(config.defaultModel).toBe('test-model'); }); it('should load config from rc file', () => { const testConfig = { anthropicApiKey: 'test-anthropic-key', openaiApiKey: 'test-openai-key', defaultModel: 'test-model' }; writeFileSync(RC_PATH, JSON.stringify(testConfig)); const config = loadConfig(); expect(config.anthropicApiKey).toBe('test-anthropic-key'); expect(config.openaiApiKey).toBe('test-openai-key'); expect(config.defaultModel).toBe('test-model'); }); it('should resolve 1Password secret references', () => { // Mock 1Password CLI responses vi.mocked(execSync) .mockReturnValueOnce('test-anthropic-key') .mockReturnValueOnce('test-openai-key'); const testConfig = { anthropicApiKey: 'op://vault/anthropic/api-key', openaiApiKey: 'op://vault/openai/api-key', defaultModel: 'test-model' }; writeFileSync(RC_PATH, JSON.stringify(testConfig)); const config = loadConfig(); expect(config.anthropicApiKey).toBe('test-anthropic-key'); expect(config.openaiApiKey).toBe('test-openai-key'); expect(config.defaultModel).toBe('test-model'); // Verify 1Password CLI was called correctly expect(execSync).toHaveBeenCalledWith('op read "op://vault/anthropic/api-key"', { encoding: 'utf-8' }); expect(execSync).toHaveBeenCalledWith('op read "op://vault/openai/api-key"', { encoding: 'utf-8' }); }); it('should handle 1Password CLI errors gracefully', () => { // Mock 1Password CLI error vi.mocked(execSync).mockImplementation(() => { const error = new Error('1Password CLI not found'); error.message = '1Password CLI not found'; throw error; }); const testConfig = { anthropicApiKey: 'op://vault/anthropic/api-key' }; writeFileSync(RC_PATH, JSON.stringify(testConfig)); expect(() => loadConfig()).toThrow('Failed to resolve 1Password secret reference'); }); it('should override rc file with passed options', () => { const testConfig = { anthropicApiKey: 'test-anthropic-key', openaiApiKey: 'test-openai-key', defaultModel: 'test-model' }; writeFileSync(RC_PATH, JSON.stringify(testConfig)); const config = loadConfig({ anthropicApiKey: 'override-key' }); expect(config.anthropicApiKey).toBe('override-key'); expect(config.openaiApiKey).toBe('test-openai-key'); expect(config.defaultModel).toBe('test-model'); }); it('should handle missing rc file gracefully', () => { if (existsSync(RC_PATH)) { unlinkSync(RC_PATH); } expect(() => loadConfig()).not.toThrow(); }); });