import { describe, it, expect, jest, beforeAll, afterAll } from '@jest/globals';
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
import { MemoryTransport } from '../../utils/memory-transport.js';
import { predictROI } from '../../../src/tools/predict-roi.js';
import { mcpDb } from '../../../src/db/supabase.js';
// Mock external dependencies
jest.mock('../../../src/db/supabase.js');
jest.mock('../../../src/services/benchmark-aggregator.js');
jest.mock('../../../src/services/dutch-benchmark-validator.js');
describe('Predict ROI Tool Integration', () => {
let server: McpServer;
let transport: MemoryTransport;
beforeAll(() => {
// Setup MCP server
server = new McpServer(
{
name: 'test-server',
version: '1.0.0',
},
{
capabilities: {
tools: {},
}
}
);
// Register the predict_roi tool
server.tool(
'predict_roi',
'Test predict ROI tool',
{},
async (args: any) => {
const result = await predictROI(args);
return {
content: [{
type: 'text',
text: JSON.stringify(result, null, 2)
}]
};
}
);
// Create memory transport for testing
transport = new MemoryTransport();
});
afterAll(async () => {
await server.close();
});
describe('Tool Registration', () => {
it('should register predict_roi tool correctly', async () => {
await server.connect(transport);
const tools = await transport.callMethod('tools/list', {});
expect(tools.tools).toHaveLength(1);
expect(tools.tools[0].name).toBe('predict_roi');
});
});
describe('Tool Execution', () => {
const validInput = {
organization_id: 'test-org-123',
project: {
name: 'AI Implementation',
client_name: 'Test Corp',
industry: 'technology',
description: 'Test project'
},
use_cases: [
{
name: 'Invoice Processing',
category: 'document_processing',
current_state: {
volume_per_month: 1000,
cost_per_transaction: 10,
time_per_transaction: 15,
error_rate: 0.05,
resource_hours: 150
},
future_state: {
automation_percentage: 0.8,
error_reduction: 0.9,
time_savings: 0.7,
quality_improvement: 0.95
},
implementation: {
complexity_score: 5,
integration_points: 3,
training_hours: 20
}
}
],
implementation_costs: {
software_licenses: 50000,
development_hours: 500,
training_costs: 10000,
infrastructure: 20000,
ongoing_monthly: 5000
},
timeline_months: 12,
confidence_level: 0.85,
enable_benchmarks: false
};
beforeEach(() => {
// Mock database responses
(mcpDb as any).rpc = jest.fn()
.mockResolvedValueOnce({ data: { project_id: 'proj-123' }, error: null })
.mockResolvedValueOnce({ data: { projection_id: 'proj-123' }, error: null });
});
it('should execute predict_roi successfully with valid input', async () => {
const result = await transport.callTool('predict_roi', validInput);
expect(result).toHaveProperty('content');
const content = JSON.parse(result.content[0].text);
expect(content).toHaveProperty('summary');
expect(content).toHaveProperty('financial_metrics');
expect(content).toHaveProperty('use_cases');
expect(content.summary).toHaveProperty('expected_roi');
expect(content.summary).toHaveProperty('payback_period_months');
});
it('should handle validation errors gracefully', async () => {
const invalidInput = {
...validInput,
timeline_months: -5 // Invalid negative timeline
};
const result = await transport.callTool('predict_roi', invalidInput);
expect(result.isError).toBe(true);
expect(result.content[0].text).toContain('Validation Error');
});
it('should handle database errors gracefully', async () => {
(mcpDb as any).rpc = jest.fn()
.mockResolvedValueOnce({
data: null,
error: { message: 'Database connection failed' }
});
const result = await transport.callTool('predict_roi', validInput);
expect(result.isError).toBe(true);
expect(result.content[0].text).toContain('Error');
});
it('should apply Dutch market validation when enabled', async () => {
const inputWithBenchmarks = {
...validInput,
enable_benchmarks: true
};
// Mock Dutch validator
jest.mock('../../../src/services/dutch-benchmark-validator.js', () => ({
DutchBenchmarkValidator: {
validateFinancialMetrics: jest.fn().mockResolvedValue({
isValid: true,
adjustmentsMade: 0,
validationIssues: [],
marketInsights: []
})
}
}));
const result = await transport.callTool('predict_roi', inputWithBenchmarks);
const content = JSON.parse(result.content[0].text);
expect(content.metadata).toHaveProperty('dutch_validation_applied', true);
});
});
describe('Performance', () => {
it('should complete within reasonable time', async () => {
const startTime = Date.now();
await transport.callTool('predict_roi', validInput);
const duration = Date.now() - startTime;
expect(duration).toBeLessThan(5000); // Should complete within 5 seconds
});
});
});