mirror of
https://github.com/proffesor-for-testing/agentic-qe.git
synced 2026-09-19 08:45:47 +08:00
5380421f1e
- 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>
718 lines
22 KiB
TypeScript
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);
|
|
});
|
|
});
|
|
});
|
|
});
|