UNPKG

gitsums

Version:

Small utility to generate description for git changes with ai

157 lines (124 loc) 6.25 kB
import ConfigService, {CONFIG_PATH, DEFAULT_CONFIG} from '../ConfigService'; import {jest} from '@jest/globals'; import {PathLike} from 'fs'; function getInstance() { const mockFileSystem = { readFile: jest.fn<(path: PathLike, encoding: BufferEncoding) => Promise<string>>(), writeFile: jest.fn<(path: PathLike, data: string, encoding: BufferEncoding) => Promise<void>>(), mkdir: jest.fn<(path: PathLike, options: { recursive: boolean }) => Promise<void>>(), access: jest.fn<(path: PathLike) => Promise<void>>(), }; const mockOnError = jest.fn(); const mockOnSuccess = jest.fn(); const configService = new ConfigService(mockOnSuccess, mockOnError, mockFileSystem as any); return {configService, mockFileSystem, mockOnError, mockOnSuccess}; } describe('Config', () => { describe('getPublicConfig', () => { it('should return the parsed config if the file exists and is valid', async () => { const {configService, mockFileSystem} = getInstance(); const mockConfig = {apiKey: 'test-key', ignoreFiles: ['node_modules'], model: 'gpt-4.1-nano', customPrompt: ''}; mockFileSystem.readFile.mockResolvedValue(JSON.stringify(mockConfig)); const result = await configService.getPublicConfig(); expect(mockFileSystem.readFile).toHaveBeenCalledWith(CONFIG_PATH, 'utf-8'); expect(result).toEqual(mockConfig); }); it('should return the default config if the file does not exist', async () => { const {configService, mockFileSystem} = getInstance(); mockFileSystem.readFile.mockRejectedValue({code: 'ENOENT'}); const result = await configService.getPublicConfig(); expect(mockFileSystem.readFile).toHaveBeenCalledWith(CONFIG_PATH, 'utf-8'); expect(result).toEqual(DEFAULT_CONFIG); }); it('should return the default config if the file contains invalid JSON', async () => { const {configService, mockFileSystem} = getInstance(); mockFileSystem.readFile.mockResolvedValue('invalid-json'); const result = await configService.getPublicConfig(); expect(mockFileSystem.readFile).toHaveBeenCalledWith(CONFIG_PATH, 'utf-8'); expect(result).toEqual(DEFAULT_CONFIG); }); }); describe('updateConfig', () => { it('should update the config with the provided function', async () => { const {configService, mockFileSystem} = getInstance(); const mockConfig = {apiKey: 'test-key', ignoreFiles: []}; mockFileSystem.readFile.mockResolvedValue(JSON.stringify(mockConfig)); mockFileSystem.writeFile.mockResolvedValue(undefined); const newConfig = {apiKey: 'new-key', ignoreFiles: ['dist'], model: 'gpt-3.5-turbo', customPrompt: ''}; await configService.updateConfig(() => newConfig); expect(mockFileSystem.writeFile).toHaveBeenCalledWith( CONFIG_PATH, JSON.stringify(newConfig, null, 2), 'utf-8' ); }); }); describe('saveConfig', () => { it('should create the config directory if it does not exist and save the config', async () => { const {configService, mockFileSystem} = getInstance(); mockFileSystem.access.mockRejectedValue({code: 'ENOENT'}); mockFileSystem.mkdir.mockResolvedValue(undefined); mockFileSystem.writeFile.mockResolvedValue(undefined); const newConfig = {apiKey: 'test-key', ignoreFiles: [], model: 'gpt-3.5-turbo', customPrompt: ''}; await configService.saveConfig(newConfig); expect(mockFileSystem.mkdir).toHaveBeenCalledWith(expect.any(String), {recursive: true}); expect(mockFileSystem.writeFile).toHaveBeenCalledWith( CONFIG_PATH, JSON.stringify(newConfig, null, 2), 'utf-8' ); }); it('should save the config if the directory already exists', async () => { const {configService, mockFileSystem} = getInstance(); mockFileSystem.access.mockResolvedValue(undefined); mockFileSystem.writeFile.mockResolvedValue(undefined); const newConfig = {apiKey: 'test-key', ignoreFiles: [], model: 'gpt-3.5-turbo', customPrompt: ''}; await configService.saveConfig(newConfig); expect(mockFileSystem.mkdir).not.toHaveBeenCalled(); expect(mockFileSystem.writeFile).toHaveBeenCalledWith( CONFIG_PATH, JSON.stringify(newConfig, null, 2), 'utf-8' ); }); }); describe('getChatGptApiKey', () => { it('should return the API key from the environment variable if it exists', async () => { const {configService} = getInstance(); process.env.OPENAI_API_KEY = 'env-key'; const result = await configService.getChatGptApiKey(); expect(result).toBe('env-key'); delete process.env.OPENAI_API_KEY; }); it('should return the API key from the config if the environment variable does not exist', async () => { const {configService, mockFileSystem} = getInstance(); const mockConfig = {apiKey: 'config-key', ignoreFiles: [], model: 'gpt-4.1-nano'}; mockFileSystem.readFile.mockResolvedValue(JSON.stringify(mockConfig)); const result = await configService.getChatGptApiKey(); expect(result).toBe('config-key'); }); it('should throw error if no API key is found', async () => { const {configService, mockFileSystem} = getInstance(); mockFileSystem.readFile.mockResolvedValue(JSON.stringify(DEFAULT_CONFIG)); try { await configService.getChatGptApiKey(); } catch (error) { expect(error).toEqual(new Error('API key is required.')); } }); }); describe('saveChatGptApiKey', () => { it('should save the API key to the config', async () => { const {configService, mockFileSystem} = getInstance(); const mockConfig = {apiKey: null, ignoreFiles: [], model: 'gpt-4.1-nano', customPrompt: ''}; mockFileSystem.readFile.mockResolvedValue(JSON.stringify(mockConfig)); mockFileSystem.writeFile.mockResolvedValue(undefined); await configService.saveChatGptApiKey('new-key'); expect(mockFileSystem.writeFile).toHaveBeenCalledWith( CONFIG_PATH, JSON.stringify({apiKey: 'new-key', ignoreFiles: [], model: 'gpt-4.1-nano', customPrompt: ''}, null, 2), 'utf-8' ); }); }); });