mcp-codesentry
Version:
CodeSentry MCP - AI-powered code review assistant with 5 specialized review tools for security, best practices, and comprehensive code analysis
144 lines • 6.49 kB
JavaScript
import { describe, it, expect, beforeEach, vi } from 'vitest';
import { GeminiClient } from '../../src/gemini/client.js';
// Mock Google Generative AI
vi.mock('@google/generative-ai', () => ({
GoogleGenerativeAI: vi.fn().mockImplementation(() => ({
getGenerativeModel: vi.fn().mockImplementation(() => ({
generateContent: vi.fn().mockResolvedValue({
response: {
text: () => JSON.stringify({
approved: true,
feedback: {
summary: 'Good implementation plan',
issues: [],
suggestions: ['Consider adding error handling'],
strengths: ['Clear structure', 'Good separation of concerns']
},
metadata: {
confidence: 0.8
}
})
}
})
}))
}))
}));
describe('GeminiClient', () => {
let client;
const testConfig = {
apiKey: 'test-api-key',
proModel: 'gemini-1.5-pro',
flashModel: 'gemini-1.5-flash'
};
beforeEach(() => {
vi.clearAllMocks();
client = new GeminiClient(testConfig);
});
describe('initialization', () => {
it('should create client with valid config', () => {
expect(client).toBeDefined();
});
it('should throw error if API key is missing', () => {
expect(() => new GeminiClient({ ...testConfig, apiKey: '' })).toThrow('Gemini API key is required');
});
});
describe('reviewPlan', () => {
it('should review a plan and return structured response', async () => {
const params = {
taskId: 'test-123',
taskDescription: 'Implement user authentication',
implementationPlan: 'Use JWT tokens with refresh token rotation',
codebaseContext: 'Express.js API with PostgreSQL'
};
const response = await client.reviewPlan(params);
expect(response).toBeDefined();
expect(response.approved).toBe(true);
expect(response.reviewType).toBe('plan');
expect(response.feedback.summary).toBe('Good implementation plan');
expect(response.metadata.taskId).toBe('test-123');
expect(response.metadata.confidence).toBe(0.8);
});
it('should include model used in metadata', async () => {
const params = {
taskId: 'test-123',
taskDescription: 'Test task',
implementationPlan: 'Test plan',
codebaseContext: 'Test context'
};
const response = await client.reviewPlan(params);
expect(response.metadata.modelUsed).toBe('gemini-1.5-pro');
});
});
describe('reviewImplementation', () => {
it('should review implementation and return structured response', async () => {
const params = {
taskId: 'test-456',
taskDescription: 'Implement user authentication',
originalPlan: 'Use JWT tokens with refresh token rotation',
implementationSummary: 'Implemented JWT auth with Redis session store',
codebaseSnapshot: 'Current code state with auth implementation'
};
const response = await client.reviewImplementation(params);
expect(response).toBeDefined();
expect(response.approved).toBe(true);
expect(response.reviewType).toBe('implementation');
expect(response.feedback.summary).toBe('Good implementation plan');
expect(response.metadata.taskId).toBe('test-456');
});
it('should use flash model for implementation reviews', async () => {
const params = {
taskId: 'test-456',
taskDescription: 'Test task',
originalPlan: 'Test plan',
implementationSummary: 'Test summary',
codebaseSnapshot: 'Test snapshot'
};
const response = await client.reviewImplementation(params);
expect(response.metadata.modelUsed).toBe('gemini-1.5-flash');
});
});
describe('error handling', () => {
it('should handle API errors gracefully', async () => {
const { GoogleGenerativeAI } = await import('@google/generative-ai');
const mockGenerateContent = vi.fn().mockRejectedValue(new Error('API Error'));
vi.mocked(GoogleGenerativeAI).mockImplementation(() => ({
getGenerativeModel: vi.fn().mockImplementation(() => ({
generateContent: mockGenerateContent
}))
}));
const errorClient = new GeminiClient(testConfig);
const params = {
taskId: 'test-error',
taskDescription: 'Test task',
implementationPlan: 'Test plan',
codebaseContext: 'Test context'
};
await expect(errorClient.reviewPlan(params)).rejects.toThrow('API Error');
});
it('should handle invalid JSON response', async () => {
const { GoogleGenerativeAI } = await import('@google/generative-ai');
vi.mocked(GoogleGenerativeAI).mockImplementation(() => ({
getGenerativeModel: vi.fn().mockImplementation(() => ({
generateContent: vi.fn().mockResolvedValue({
response: {
text: () => 'Invalid JSON'
}
})
}))
}));
const errorClient = new GeminiClient(testConfig);
const params = {
taskId: 'test-parse-error',
taskDescription: 'Test task',
implementationPlan: 'Test plan',
codebaseContext: 'Test context'
};
const response = await errorClient.reviewPlan(params);
expect(response.approved).toBe(false);
expect(response.feedback.summary).toBe('Error parsing review response');
expect(response.feedback.issues).toContain('Failed to parse AI response');
expect(response.metadata.confidence).toBe(0);
});
});
});
//# sourceMappingURL=client.test.js.map