"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const fs_1 = require("fs"); const config_1 = require("../../src/commands/config"); const utils_1 = require("./utils"); describe('config', () => { const originalEnv = { ...process.env }; let globalConfigFile; let envConfigFile; function resetEnv(env) { Object.keys(process.env).forEach((key) => { if (!(key in env)) { delete process.env[key]; } else { process.env[key] = env[key]; } }); } beforeEach(async () => { resetEnv(originalEnv); if (globalConfigFile) await globalConfigFile.cleanup(); if (envConfigFile) await envConfigFile.cleanup(); }); afterEach(async () => { if (globalConfigFile) await globalConfigFile.cleanup(); if (envConfigFile) await envConfigFile.cleanup(); }); afterAll(() => { resetEnv(originalEnv); }); const generateConfig = async (fileName, content) => { const fileContent = Object.entries(content) .map(([key, value]) => `${key}="${value}"`) .join('\n'); return await (0, utils_1.prepareFile)(fileName, fileContent); }; describe('getConfig', () => { it('should prioritize local .env over global .opencommit config', async () => { globalConfigFile = await generateConfig('.opencommit', { OCO_API_KEY: 'global-key', OCO_MODEL: 'gpt-3.5-turbo', OCO_LANGUAGE: 'en' }); envConfigFile = await generateConfig('.env', { OCO_API_KEY: 'local-key', OCO_LANGUAGE: 'fr' }); const config = (0, config_1.getConfig)({ globalPath: globalConfigFile.filePath, envPath: envConfigFile.filePath }); expect(config).not.toEqual(null); expect(config.OCO_API_KEY).toEqual('local-key'); expect(config.OCO_MODEL).toEqual('gpt-3.5-turbo'); expect(config.OCO_LANGUAGE).toEqual('fr'); }); it('should fallback to global config when local config is not set', async () => { globalConfigFile = await generateConfig('.opencommit', { OCO_API_KEY: 'global-key', OCO_MODEL: 'gpt-4', OCO_LANGUAGE: 'de', OCO_DESCRIPTION: 'true' }); envConfigFile = await generateConfig('.env', { OCO_API_URL: 'local-api-url' }); const config = (0, config_1.getConfig)({ globalPath: globalConfigFile.filePath, envPath: envConfigFile.filePath }); expect(config).not.toEqual(null); expect(config.OCO_API_KEY).toEqual('global-key'); expect(config.OCO_API_URL).toEqual('local-api-url'); expect(config.OCO_MODEL).toEqual('gpt-4'); expect(config.OCO_LANGUAGE).toEqual('de'); expect(config.OCO_DESCRIPTION).toEqual(true); }); it('should handle boolean and numeric values correctly', async () => { globalConfigFile = await generateConfig('.opencommit', { OCO_TOKENS_MAX_INPUT: '4096', OCO_TOKENS_MAX_OUTPUT: '500', OCO_GITPUSH: 'true' }); envConfigFile = await generateConfig('.env', { OCO_TOKENS_MAX_INPUT: '8192', OCO_ONE_LINE_COMMIT: 'false', OCO_OMIT_SCOPE: 'true' }); const config = (0, config_1.getConfig)({ globalPath: globalConfigFile.filePath, envPath: envConfigFile.filePath }); expect(config).not.toEqual(null); expect(config.OCO_TOKENS_MAX_INPUT).toEqual(8192); expect(config.OCO_TOKENS_MAX_OUTPUT).toEqual(500); expect(config.OCO_GITPUSH).toEqual(true); expect(config.OCO_ONE_LINE_COMMIT).toEqual(false); expect(config.OCO_OMIT_SCOPE).toEqual(true); }); it('should handle custom HTTP headers correctly', async () => { globalConfigFile = await generateConfig('.opencommit', { OCO_API_CUSTOM_HEADERS: '{"X-Global-Header": "global-value"}' }); envConfigFile = await generateConfig('.env', { OCO_API_CUSTOM_HEADERS: '{"Authorization": "Bearer token123", "X-Custom-Header": "test-value"}' }); const config = (0, config_1.getConfig)({ globalPath: globalConfigFile.filePath, envPath: envConfigFile.filePath }); expect(config).not.toEqual(null); expect(config.OCO_API_CUSTOM_HEADERS).toEqual({ "Authorization": "Bearer token123", "X-Custom-Header": "test-value" }); // No need to parse JSON again since it's already an object const parsedHeaders = config.OCO_API_CUSTOM_HEADERS; expect(parsedHeaders).toHaveProperty('Authorization', 'Bearer token123'); expect(parsedHeaders).toHaveProperty('X-Custom-Header', 'test-value'); expect(parsedHeaders).not.toHaveProperty('X-Global-Header'); }); it('should handle empty local config correctly', async () => { globalConfigFile = await generateConfig('.opencommit', { OCO_API_KEY: 'global-key', OCO_MODEL: 'gpt-4', OCO_LANGUAGE: 'es' }); envConfigFile = await generateConfig('.env', {}); const config = (0, config_1.getConfig)({ globalPath: globalConfigFile.filePath, envPath: envConfigFile.filePath }); expect(config).not.toEqual(null); expect(config.OCO_API_KEY).toEqual('global-key'); expect(config.OCO_MODEL).toEqual('gpt-4'); expect(config.OCO_LANGUAGE).toEqual('es'); }); it('should override global config with null values in local .env', async () => { globalConfigFile = await generateConfig('.opencommit', { OCO_API_KEY: 'global-key', OCO_MODEL: 'gpt-4', OCO_LANGUAGE: 'es' }); envConfigFile = await generateConfig('.env', { OCO_API_KEY: 'null' }); const config = (0, config_1.getConfig)({ globalPath: globalConfigFile.filePath, envPath: envConfigFile.filePath }); expect(config).not.toEqual(null); expect(config.OCO_API_KEY).toEqual(null); }); it('should handle empty global config', async () => { globalConfigFile = await generateConfig('.opencommit', {}); envConfigFile = await generateConfig('.env', {}); const config = (0, config_1.getConfig)({ globalPath: globalConfigFile.filePath, envPath: envConfigFile.filePath }); expect(config).not.toEqual(null); expect(config.OCO_API_KEY).toEqual(undefined); }); }); describe('setConfig', () => { beforeEach(async () => { // we create and delete the file to have the parent directory, but not the file, to test the creation of the file globalConfigFile = await generateConfig('.opencommit', {}); (0, fs_1.rmSync)(globalConfigFile.filePath); }); it('should create .opencommit file with DEFAULT CONFIG if it does not exist on first setConfig run', async () => { const isGlobalConfigFileExist = (0, fs_1.existsSync)(globalConfigFile.filePath); expect(isGlobalConfigFileExist).toBe(false); await (0, config_1.setConfig)([[config_1.CONFIG_KEYS.OCO_API_KEY, 'persisted-key_1']], globalConfigFile.filePath); const fileContent = (0, fs_1.readFileSync)(globalConfigFile.filePath, 'utf8'); expect(fileContent).toContain('OCO_API_KEY=persisted-key_1'); Object.entries(config_1.DEFAULT_CONFIG).forEach(([key, value]) => { expect(fileContent).toContain(`${key}=${value}`); }); }); it('should set new config values', async () => { globalConfigFile = await generateConfig('.opencommit', {}); await (0, config_1.setConfig)([ [config_1.CONFIG_KEYS.OCO_API_KEY, 'new-key'], [config_1.CONFIG_KEYS.OCO_MODEL, 'gpt-4'] ], globalConfigFile.filePath); const config = (0, config_1.getConfig)({ globalPath: globalConfigFile.filePath }); expect(config.OCO_API_KEY).toEqual('new-key'); expect(config.OCO_MODEL).toEqual('gpt-4'); }); it('should update existing config values', async () => { globalConfigFile = await generateConfig('.opencommit', { OCO_API_KEY: 'initial-key' }); await (0, config_1.setConfig)([[config_1.CONFIG_KEYS.OCO_API_KEY, 'updated-key']], globalConfigFile.filePath); const config = (0, config_1.getConfig)({ globalPath: globalConfigFile.filePath }); expect(config.OCO_API_KEY).toEqual('updated-key'); }); it('should handle boolean and numeric values correctly', async () => { globalConfigFile = await generateConfig('.opencommit', {}); await (0, config_1.setConfig)([ [config_1.CONFIG_KEYS.OCO_TOKENS_MAX_INPUT, '8192'], [config_1.CONFIG_KEYS.OCO_DESCRIPTION, 'true'], [config_1.CONFIG_KEYS.OCO_ONE_LINE_COMMIT, 'false'] ], globalConfigFile.filePath); const config = (0, config_1.getConfig)({ globalPath: globalConfigFile.filePath }); expect(config.OCO_TOKENS_MAX_INPUT).toEqual(8192); expect(config.OCO_DESCRIPTION).toEqual(true); expect(config.OCO_ONE_LINE_COMMIT).toEqual(false); }); it('should throw an error for unsupported config keys', async () => { globalConfigFile = await generateConfig('.opencommit', {}); try { await (0, config_1.setConfig)([['UNSUPPORTED_KEY', 'value']], globalConfigFile.filePath); throw new Error('NEVER_REACHED'); } catch (error) { expect(error.message).toContain('Unsupported config key: UNSUPPORTED_KEY'); expect(error.message).not.toContain('NEVER_REACHED'); } }); it('should persist changes to the config file', async () => { const isGlobalConfigFileExist = (0, fs_1.existsSync)(globalConfigFile.filePath); expect(isGlobalConfigFileExist).toBe(false); await (0, config_1.setConfig)([[config_1.CONFIG_KEYS.OCO_API_KEY, 'persisted-key']], globalConfigFile.filePath); const fileContent = (0, fs_1.readFileSync)(globalConfigFile.filePath, 'utf8'); expect(fileContent).toContain('OCO_API_KEY=persisted-key'); }); it('should set multiple configs in a row and keep the changes', async () => { const isGlobalConfigFileExist = (0, fs_1.existsSync)(globalConfigFile.filePath); expect(isGlobalConfigFileExist).toBe(false); await (0, config_1.setConfig)([[config_1.CONFIG_KEYS.OCO_API_KEY, 'persisted-key']], globalConfigFile.filePath); const fileContent1 = (0, fs_1.readFileSync)(globalConfigFile.filePath, 'utf8'); expect(fileContent1).toContain('OCO_API_KEY=persisted-key'); await (0, config_1.setConfig)([[config_1.CONFIG_KEYS.OCO_MODEL, 'gpt-4']], globalConfigFile.filePath); const fileContent2 = (0, fs_1.readFileSync)(globalConfigFile.filePath, 'utf8'); expect(fileContent2).toContain('OCO_MODEL=gpt-4'); }); }); });