Files
proffesor-for-testing__agen…/tests/mcp/handlers/IntegrationTools.test.ts
Profa 5380421f1e docs: update implementation progress analysis - MCP server 100% complete
- Corrected MCP server implementation status from 0% to 100%
- Added details of 52 MCP tools across 8 categories
- Updated overall progress from 46% to 54% (7/13 areas complete)
- Added MCP server architecture details (357 lines server, 1836 lines tools, 60+ handlers)
- Updated integration metrics: MCP Tools 52/50 (104% - exceeded target)
- Removed MCP server from future work (already production-ready)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-06 17:50:41 +00:00

718 lines
22 KiB
TypeScript

import { describe, it, expect, beforeEach, jest } from '@jest/globals';
import { integrationTestOrchestrate } from '../../../src/mcp/handlers/integration/integration-test-orchestrate';
import { contractValidate } from '../../../src/mcp/handlers/integration/contract-validate';
import { dependencyCheck } from '../../../src/mcp/handlers/integration/dependency-check';
import type {
IntegrationTestOrchestrateParams,
ContractValidateParams,
DependencyCheckParams,
} from '../../../src/mcp/types/integration';
describe('Integration Testing MCP Tools', () => {
describe('integration_test_orchestrate', () => {
describe('Basic Orchestration', () => {
it('should orchestrate a simple integration test', async () => {
const params: IntegrationTestOrchestrateParams = {
services: ['auth-service', 'user-service'],
scenario: 'user-login-flow',
timeout: 30000,
};
const result = await integrationTestOrchestrate(params);
expect(result.success).toBe(true);
expect(result.scenario).toBe('user-login-flow');
expect(result.services).toEqual(['auth-service', 'user-service']);
expect(result.executionTime).toBeGreaterThan(0);
});
it('should handle multiple services orchestration', async () => {
const params: IntegrationTestOrchestrateParams = {
services: ['api-gateway', 'auth-service', 'user-service', 'notification-service'],
scenario: 'complete-user-registration',
timeout: 60000,
};
const result = await integrationTestOrchestrate(params);
expect(result.success).toBe(true);
expect(result.services).toHaveLength(4);
expect(result.testResults).toBeDefined();
});
it('should execute tests in sequence mode', async () => {
const params: IntegrationTestOrchestrateParams = {
services: ['service-a', 'service-b'],
scenario: 'sequential-test',
executionMode: 'sequential',
timeout: 30000,
};
const result = await integrationTestOrchestrate(params);
expect(result.success).toBe(true);
expect(result.executionMode).toBe('sequential');
});
it('should execute tests in parallel mode', async () => {
const params: IntegrationTestOrchestrateParams = {
services: ['service-a', 'service-b', 'service-c'],
scenario: 'parallel-test',
executionMode: 'parallel',
timeout: 30000,
};
const result = await integrationTestOrchestrate(params);
expect(result.success).toBe(true);
expect(result.executionMode).toBe('parallel');
expect(result.executionTime).toBeLessThan(30000);
});
});
describe('Environment Configuration', () => {
it('should use staging environment', async () => {
const params: IntegrationTestOrchestrateParams = {
services: ['auth-service'],
scenario: 'login-test',
environment: 'staging',
timeout: 30000,
};
const result = await integrationTestOrchestrate(params);
expect(result.success).toBe(true);
expect(result.environment).toBe('staging');
});
it('should use production environment with warning', async () => {
const params: IntegrationTestOrchestrateParams = {
services: ['auth-service'],
scenario: 'health-check',
environment: 'production',
timeout: 30000,
};
const result = await integrationTestOrchestrate(params);
expect(result.environment).toBe('production');
expect(result.warnings).toBeDefined();
});
it('should default to development environment', async () => {
const params: IntegrationTestOrchestrateParams = {
services: ['auth-service'],
scenario: 'basic-test',
timeout: 30000,
};
const result = await integrationTestOrchestrate(params);
expect(result.environment).toBe('development');
});
});
describe('Test Data Management', () => {
it('should use provided test data', async () => {
const params: IntegrationTestOrchestrateParams = {
services: ['user-service'],
scenario: 'user-creation',
testData: {
users: [{ email: 'test@example.com', password: 'test123' }],
},
timeout: 30000,
};
const result = await integrationTestOrchestrate(params);
expect(result.success).toBe(true);
expect(result.testData).toBeDefined();
});
it('should generate test data when not provided', async () => {
const params: IntegrationTestOrchestrateParams = {
services: ['user-service'],
scenario: 'user-creation',
timeout: 30000,
};
const result = await integrationTestOrchestrate(params);
expect(result.success).toBe(true);
expect(result.testData).toBeDefined();
});
});
describe('Error Handling', () => {
it('should handle service timeout', async () => {
const params: IntegrationTestOrchestrateParams = {
services: ['slow-service'],
scenario: 'timeout-test',
timeout: 100, // Very short timeout
};
const result = await integrationTestOrchestrate(params);
expect(result.success).toBe(false);
expect(result.error).toContain('timeout');
});
it('should handle invalid service names', async () => {
const params: IntegrationTestOrchestrateParams = {
services: ['non-existent-service'],
scenario: 'test',
timeout: 30000,
};
const result = await integrationTestOrchestrate(params);
expect(result.success).toBe(false);
expect(result.error).toBeDefined();
});
it('should handle missing required parameters', async () => {
const params = {
services: [],
scenario: '',
} as IntegrationTestOrchestrateParams;
await expect(integrationTestOrchestrate(params)).rejects.toThrow();
});
});
describe('Retry Logic', () => {
it('should retry failed tests', async () => {
const params: IntegrationTestOrchestrateParams = {
services: ['flaky-service'],
scenario: 'retry-test',
retryCount: 3,
timeout: 30000,
};
const result = await integrationTestOrchestrate(params);
expect(result.retries).toBeDefined();
expect(result.retries).toBeLessThanOrEqual(3);
});
it('should not retry when retryCount is 0', async () => {
const params: IntegrationTestOrchestrateParams = {
services: ['service-a'],
scenario: 'no-retry-test',
retryCount: 0,
timeout: 30000,
};
const result = await integrationTestOrchestrate(params);
expect(result.retries).toBe(0);
});
});
});
describe('contract_validate', () => {
describe('OpenAPI Contract Validation', () => {
it('should validate valid OpenAPI contract', async () => {
const params: ContractValidateParams = {
provider: 'user-service',
consumer: 'api-gateway',
contractType: 'openapi',
contractSpec: {
openapi: '3.0.0',
paths: {
'/users': {
get: {
responses: {
'200': { description: 'Success' },
},
},
},
},
},
};
const result = await contractValidate(params);
expect(result.valid).toBe(true);
expect(result.provider).toBe('user-service');
expect(result.consumer).toBe('api-gateway');
});
it('should detect invalid OpenAPI contract', async () => {
const params: ContractValidateParams = {
provider: 'user-service',
consumer: 'api-gateway',
contractType: 'openapi',
contractSpec: {
openapi: '3.0.0',
paths: {}, // Empty paths
},
};
const result = await contractValidate(params);
expect(result.valid).toBe(false);
expect(result.errors).toBeDefined();
expect(result.errors!.length).toBeGreaterThan(0);
});
it('should validate response schema', async () => {
const params: ContractValidateParams = {
provider: 'user-service',
consumer: 'api-gateway',
contractType: 'openapi',
contractSpec: {
openapi: '3.0.0',
paths: {
'/users/{id}': {
get: {
responses: {
'200': {
description: 'User found',
content: {
'application/json': {
schema: {
type: 'object',
properties: {
id: { type: 'string' },
email: { type: 'string' },
},
},
},
},
},
},
},
},
},
},
};
const result = await contractValidate(params);
expect(result.valid).toBe(true);
expect(result.validationDetails?.schemasValidated).toBeGreaterThan(0);
});
});
describe('GraphQL Contract Validation', () => {
it('should validate GraphQL schema', async () => {
const params: ContractValidateParams = {
provider: 'graphql-service',
consumer: 'frontend-app',
contractType: 'graphql',
contractSpec: {
schema: `
type Query {
user(id: ID!): User
}
type User {
id: ID!
email: String!
}
`,
},
};
const result = await contractValidate(params);
expect(result.valid).toBe(true);
expect(result.contractType).toBe('graphql');
});
it('should detect invalid GraphQL schema', async () => {
const params: ContractValidateParams = {
provider: 'graphql-service',
consumer: 'frontend-app',
contractType: 'graphql',
contractSpec: {
schema: 'invalid graphql schema',
},
};
const result = await contractValidate(params);
expect(result.valid).toBe(false);
expect(result.errors).toBeDefined();
});
});
describe('Message Queue Contract Validation', () => {
it('should validate message queue contract', async () => {
const params: ContractValidateParams = {
provider: 'order-service',
consumer: 'notification-service',
contractType: 'message-queue',
contractSpec: {
queue: 'order.created',
messageSchema: {
type: 'object',
properties: {
orderId: { type: 'string' },
userId: { type: 'string' },
total: { type: 'number' },
},
required: ['orderId', 'userId'],
},
},
};
const result = await contractValidate(params);
expect(result.valid).toBe(true);
expect(result.contractType).toBe('message-queue');
});
it('should detect missing required fields in message schema', async () => {
const params: ContractValidateParams = {
provider: 'order-service',
consumer: 'notification-service',
contractType: 'message-queue',
contractSpec: {
queue: 'order.created',
messageSchema: {
type: 'object',
properties: {},
required: ['orderId'],
},
},
};
const result = await contractValidate(params);
expect(result.valid).toBe(false);
expect(result.errors).toBeDefined();
});
});
describe('Contract Breaking Changes', () => {
it('should detect breaking changes', async () => {
const params: ContractValidateParams = {
provider: 'user-service',
consumer: 'api-gateway',
contractType: 'openapi',
contractSpec: {
openapi: '3.0.0',
paths: {
'/users': {
get: {
responses: {
'200': { description: 'Success' },
},
},
},
},
},
previousContract: {
openapi: '3.0.0',
paths: {
'/users': {
get: {
responses: {
'200': { description: 'Success' },
},
},
},
'/users/{id}': {
get: {
responses: {
'200': { description: 'User found' },
},
},
},
},
},
};
const result = await contractValidate(params);
expect(result.breakingChanges).toBeDefined();
expect(result.breakingChanges!.length).toBeGreaterThan(0);
});
it('should allow backward compatible changes', async () => {
const params: ContractValidateParams = {
provider: 'user-service',
consumer: 'api-gateway',
contractType: 'openapi',
contractSpec: {
openapi: '3.0.0',
paths: {
'/users': {
get: {
responses: {
'200': { description: 'Success' },
},
},
},
'/users/{id}': {
get: {
responses: {
'200': { description: 'User found' },
},
},
},
},
},
previousContract: {
openapi: '3.0.0',
paths: {
'/users': {
get: {
responses: {
'200': { description: 'Success' },
},
},
},
},
},
};
const result = await contractValidate(params);
expect(result.valid).toBe(true);
expect(result.breakingChanges || []).toHaveLength(0);
});
});
describe('Version Compatibility', () => {
it('should check version compatibility', async () => {
const params: ContractValidateParams = {
provider: 'user-service',
consumer: 'api-gateway',
contractType: 'openapi',
contractSpec: {
openapi: '3.0.0',
info: { version: '2.0.0', title: 'User API' },
paths: {},
},
consumerVersion: '1.0.0',
};
const result = await contractValidate(params);
expect(result.versionCompatible).toBeDefined();
});
});
describe('Strict Mode Validation', () => {
it('should enforce strict validation when enabled', async () => {
const params: ContractValidateParams = {
provider: 'user-service',
consumer: 'api-gateway',
contractType: 'openapi',
contractSpec: {
openapi: '3.0.0',
paths: {
'/users': {
get: {
responses: {
'200': { description: 'Success' },
},
},
},
},
},
strictMode: true,
};
const result = await contractValidate(params);
expect(result.strictMode).toBe(true);
});
});
});
describe('dependency_check', () => {
describe('Basic Health Checks', () => {
it('should check health of a single dependency', async () => {
const params: DependencyCheckParams = {
services: ['postgres-db'],
};
const result = await dependencyCheck(params);
expect(result.healthy).toBeDefined();
expect(result.dependencies).toHaveLength(1);
expect(result.dependencies[0].name).toBe('postgres-db');
expect(result.dependencies[0].status).toBeDefined();
});
it('should check multiple dependencies', async () => {
const params: DependencyCheckParams = {
services: ['postgres-db', 'redis-cache', 'rabbitmq'],
};
const result = await dependencyCheck(params);
expect(result.dependencies).toHaveLength(3);
expect(result.checkDuration).toBeGreaterThan(0);
});
it('should detect unhealthy dependency', async () => {
const params: DependencyCheckParams = {
services: ['unavailable-service'],
};
const result = await dependencyCheck(params);
expect(result.healthy).toBe(false);
expect(result.dependencies[0].status).toBe('unhealthy');
});
});
describe('Connection Timeout', () => {
it('should respect timeout settings', async () => {
const params: DependencyCheckParams = {
services: ['slow-service'],
timeout: 1000,
};
const result = await dependencyCheck(params);
expect(result.checkDuration).toBeLessThan(2000);
});
it('should handle timeout gracefully', async () => {
const params: DependencyCheckParams = {
services: ['very-slow-service'],
timeout: 100,
};
const result = await dependencyCheck(params);
expect(result.dependencies[0].status).toBe('timeout');
expect(result.dependencies[0].error).toContain('timeout');
});
});
describe('Detailed Health Information', () => {
it('should return detailed health info when requested', async () => {
const params: DependencyCheckParams = {
services: ['postgres-db'],
detailed: true,
};
const result = await dependencyCheck(params);
expect(result.dependencies[0].details).toBeDefined();
expect(result.dependencies[0].responseTime).toBeGreaterThan(0);
});
it('should include version information in detailed mode', async () => {
const params: DependencyCheckParams = {
services: ['redis-cache'],
detailed: true,
};
const result = await dependencyCheck(params);
expect(result.dependencies[0].details?.version).toBeDefined();
});
});
describe('Retry Logic', () => {
it('should retry failed health checks', async () => {
const params: DependencyCheckParams = {
services: ['flaky-service'],
retryCount: 3,
};
const result = await dependencyCheck(params);
expect(result.dependencies[0].retries).toBeDefined();
expect(result.dependencies[0].retries).toBeLessThanOrEqual(3);
});
it('should not retry when retryCount is 0', async () => {
const params: DependencyCheckParams = {
services: ['postgres-db'],
retryCount: 0,
};
const result = await dependencyCheck(params);
expect(result.dependencies[0].retries).toBe(0);
});
});
describe('Parallel Checks', () => {
it('should check dependencies in parallel', async () => {
const params: DependencyCheckParams = {
services: ['service-a', 'service-b', 'service-c'],
parallel: true,
};
const startTime = Date.now();
const result = await dependencyCheck(params);
const duration = Date.now() - startTime;
expect(result.dependencies).toHaveLength(3);
expect(result.parallel).toBe(true);
// Parallel should be faster than sequential
expect(duration).toBeLessThan(5000);
});
it('should check dependencies sequentially when parallel is false', async () => {
const params: DependencyCheckParams = {
services: ['service-a', 'service-b'],
parallel: false,
};
const result = await dependencyCheck(params);
expect(result.parallel).toBe(false);
});
});
describe('Critical Dependencies', () => {
it('should mark result as unhealthy if critical dependency fails', async () => {
const params: DependencyCheckParams = {
services: ['postgres-db', 'redis-cache'],
criticalServices: ['postgres-db'],
};
// Simulate postgres failure
const result = await dependencyCheck(params);
if (result.dependencies[0].name === 'postgres-db' && result.dependencies[0].status === 'unhealthy') {
expect(result.healthy).toBe(false);
expect(result.criticalFailures).toBeDefined();
}
});
it('should not mark as unhealthy if non-critical dependency fails', async () => {
const params: DependencyCheckParams = {
services: ['postgres-db', 'optional-cache'],
criticalServices: ['postgres-db'],
};
const result = await dependencyCheck(params);
// If only optional-cache fails, overall health should still be ok
const criticalHealthy = result.dependencies
.filter(d => params.criticalServices?.includes(d.name))
.every(d => d.status === 'healthy');
if (criticalHealthy) {
expect(result.healthy).toBe(true);
}
});
});
describe('Health Score Calculation', () => {
it('should calculate overall health score', async () => {
const params: DependencyCheckParams = {
services: ['service-a', 'service-b', 'service-c'],
};
const result = await dependencyCheck(params);
expect(result.healthScore).toBeDefined();
expect(result.healthScore).toBeGreaterThanOrEqual(0);
expect(result.healthScore).toBeLessThanOrEqual(100);
});
});
});
});