/**
* š INTEGRATION TESTS
* Tests for end-to-end integration scenarios and workflows
* Focus: Cross-system integration, workflows, data consistency, real-world scenarios
*/
import { describe, test, expect, beforeAll } from 'vitest';
import { MCPXppClient, MCPTestUtils } from './tools/mcp-xpp-client.js';
import { AppConfig } from '../build/modules/app-config.js';
// =============================================================================
// š INTEGRATION TEST CONFIGURATION
// =============================================================================
const INTEGRATION_CONFIG = {
timeouts: {
workflow: 120000, // 2 minutes for complete workflows
crossSystem: 60000, // 1 minute for cross-system operations
consistency: 30000, // 30 seconds for consistency checks
},
workflows: {
objectDiscoveryToCreation: ['search_objects_pattern', 'find_xpp_object', 'create_xpp_object'],
searchAndAnalyze: ['build_object_index', 'search_objects_pattern', 'get_current_config'],
fullDevelopmentCycle: ['get_current_config', 'search_objects_pattern', 'build_object_index', 'find_xpp_object']
}
};
let mcpClient;
// =============================================================================
// TEST SETUP
// =============================================================================
beforeAll(async () => {
await AppConfig.initialize();
mcpClient = await MCPTestUtils.createTestClient();
console.log(`
š INTEGRATION TEST SUITE LOADED
š Test Categories:
- End-to-End Workflows
- Cross-System Integration
- Data Consistency
- Real-World Scenarios
ā±ļø Timeouts:
- Complete workflows: ${INTEGRATION_CONFIG.timeouts.workflow}ms
- Cross-system ops: ${INTEGRATION_CONFIG.timeouts.crossSystem}ms
- Consistency checks: ${INTEGRATION_CONFIG.timeouts.consistency}ms
šÆ Focus: Real-world integration scenarios and workflows
`);
}, INTEGRATION_CONFIG.timeouts.workflow);
// Helper function to check integration test availability
const isIntegrationAvailable = async () => {
try {
const config = await mcpClient.executeTool('get_current_config');
return config && config.content;
} catch (error) {
console.log('āļø Integration tests skipped - MCP service not available');
return false;
}
};
// =============================================================================
// š END-TO-END WORKFLOW TESTS
// =============================================================================
describe('š End-to-End Workflows', () => {
test('should complete object discovery to analysis workflow', async () => {
if (!(await isIntegrationAvailable())) return;
console.log('š Testing complete object discovery to analysis workflow...');
const workflowSteps = [];
let workflowData = {};
// Step 1: Get current configuration
console.log(' Step 1: Getting current configuration...');
const configResult = await mcpClient.executeTool('get_current_config');
expect(configResult).toBeDefined();
expect(configResult.content).toBeDefined();
workflowSteps.push('get_current_config');
workflowData.config = configResult.content;
// Step 2: Discover object types using search pattern
console.log(' Step 2: Discovering object types...');
const discoveryResult = await mcpClient.executeTool('search_objects_pattern', {
pattern: '*',
format: 'json',
limit: 50
});
expect(discoveryResult).toBeDefined();
expect(discoveryResult.content).toBeDefined();
workflowSteps.push('search_objects_pattern');
workflowData.discovery = discoveryResult.content;
// Step 3: Build object index with SQLite
console.log(' Step 3: Building object index...');
const indexResult = await mcpClient.executeTool('build_object_index', {
mode: 'optimized',
useSqlite: true
});
expect(indexResult).toBeDefined();
workflowSteps.push('build_object_index');
workflowData.index = indexResult.content;
// Step 4: Query objects using the index
console.log(' Step 4: Querying objects from index...');
const queryResult = await mcpClient.executeTool('search_objects_pattern', {
pattern: '*',
objectType: 'AxClass',
limit: 20
});
expect(queryResult).toBeDefined();
workflowSteps.push('search_objects_pattern');
workflowData.query = queryResult.content;
console.log(`ā
Workflow completed successfully: ${workflowSteps.join(' ā ')}`);
// Validate workflow data consistency
expect(workflowData.config).toBeDefined();
expect(workflowData.discovery).toBeDefined();
expect(workflowData.index).toBeDefined();
expect(workflowData.query).toBeDefined();
console.log('š Complete object discovery to analysis workflow successful!');
}, INTEGRATION_CONFIG.timeouts.workflow);
test('should handle developer productivity workflow', async () => {
if (!(await isIntegrationAvailable())) return;
console.log('šØāš» Testing developer productivity workflow...');
const developerTasks = [];
// Task 1: Check development environment setup
console.log(' Task 1: Checking development environment...');
const envCheck = await mcpClient.executeTool('get_current_config');
expect(envCheck).toBeDefined();
developerTasks.push('Environment Check');
// Task 2: Explore existing objects for reference
console.log(' Task 2: Exploring existing objects...');
const exploreResult = await mcpClient.executeTool('search_objects_pattern', {
pattern: 'Customer*',
objectType: 'AxClass',
limit: 10
});
expect(exploreResult).toBeDefined();
developerTasks.push('Object Exploration');
// Task 3: Find similar patterns in codebase
console.log(' Task 3: Finding similar patterns...');
const patternResult = await mcpClient.executeTool('search_objects_pattern', {
pattern: '*Customer*',
objectType: 'AxTable',
limit: 5
});
expect(patternResult).toBeDefined();
developerTasks.push('Pattern Analysis');
// Task 4: Validate development readiness
console.log(' Task 4: Validating development readiness...');
const readinessCheck = await mcpClient.executeTool('get_current_config');
expect(readinessCheck).toBeDefined();
developerTasks.push('Readiness Validation');
console.log(`ā
Developer workflow completed: ${developerTasks.join(' ā ')}`);
console.log('š Developer productivity workflow successful!');
}, INTEGRATION_CONFIG.timeouts.workflow);
test('should support continuous integration workflow', async () => {
if (!(await isIntegrationAvailable())) return;
console.log('š Testing continuous integration workflow...');
const ciSteps = [];
// CI Step 1: Environment validation
console.log(' CI Step 1: Environment validation...');
const validation = await mcpClient.executeTool('get_current_config');
expect(validation).toBeDefined();
ciSteps.push('Environment Validation');
// CI Step 2: Index integrity check
console.log(' CI Step 2: Index integrity check...');
const indexCheck = await mcpClient.executeTool('build_object_index', {
mode: 'check',
useSqlite: true
});
expect(indexCheck).toBeDefined();
ciSteps.push('Index Integrity');
// CI Step 3: Sample data validation
console.log(' CI Step 3: Sample data validation...');
const dataValidation = await mcpClient.executeTool('search_objects_pattern', {
pattern: '*',
objectType: 'AxClass',
limit: 1
});
expect(dataValidation).toBeDefined();
ciSteps.push('Data Validation');
// CI Step 4: System health check
console.log(' CI Step 4: System health check...');
const healthCheck = await mcpClient.executeTool('get_current_config');
expect(healthCheck).toBeDefined();
ciSteps.push('Health Check');
console.log(`ā
CI workflow completed: ${ciSteps.join(' ā ')}`);
console.log('š Continuous integration workflow successful!');
}, INTEGRATION_CONFIG.timeouts.workflow);
});
// =============================================================================
// š CROSS-SYSTEM INTEGRATION TESTS
// =============================================================================
describe('š Cross-System Integration', () => {
test('should integrate MCP client with SQLite backend', async () => {
if (!(await isIntegrationAvailable())) return;
console.log('š Testing MCP client + SQLite backend integration...');
// Test that MCP client operations correctly use SQLite backend
const startTime = Date.now();
const result = await mcpClient.executeTool('search_objects_pattern', {
pattern: '*',
objectType: 'AxClass',
limit: 10
});
const endTime = Date.now();
const duration = endTime - startTime;
expect(result).toBeDefined();
expect(result.content).toBeDefined();
// SQLite backend should provide fast responses
expect(duration).toBeLessThan(1000); // 1 second max
console.log(`ā
MCP + SQLite integration successful (${duration}ms)`);
}, INTEGRATION_CONFIG.timeouts.crossSystem);
test('should integrate with VS2022 service through MCP', async () => {
if (!(await isIntegrationAvailable())) return;
console.log('š§ Testing MCP + VS2022 service integration...');
// Test configuration retrieval (which may include VS2022 service data)
const config = await mcpClient.executeTool('get_current_config');
expect(config).toBeDefined();
expect(config.content).toBeDefined();
const configStr = typeof config.content === 'string' ?
config.content : JSON.stringify(config.content);
// Should contain meaningful configuration data
expect(configStr.length).toBeGreaterThan(100);
console.log('ā
MCP + VS2022 service integration working');
}, INTEGRATION_CONFIG.timeouts.crossSystem);
test('should maintain data consistency across systems', async () => {
if (!(await isIntegrationAvailable())) return;
console.log('š Testing data consistency across systems...');
// Get configuration multiple times to test consistency
const configs = [];
for (let i = 0; i < 3; i++) {
const config = await mcpClient.executeTool('get_current_config');
configs.push(config);
}
// All configurations should be consistent
configs.forEach(config => {
expect(config).toBeDefined();
expect(config.content).toBeDefined();
});
// Test object listing consistency
const objectLists = [];
for (let i = 0; i < 2; i++) {
const list = await mcpClient.executeTool('search_objects_pattern', {
pattern: '*',
objectType: 'AxClass',
limit: 5
});
objectLists.push(list);
}
objectLists.forEach(list => {
expect(list).toBeDefined();
expect(list.content).toBeDefined();
});
console.log('ā
Data consistency maintained across systems');
}, INTEGRATION_CONFIG.timeouts.consistency);
});
// =============================================================================
// š DATA CONSISTENCY TESTS
// =============================================================================
describe('š Data Consistency', () => {
test('should maintain consistency between index builds', async () => {
if (!(await isIntegrationAvailable())) return;
console.log('š Testing index build consistency...');
// Build index twice and compare results
const firstBuild = await mcpClient.executeTool('build_object_index', {
mode: 'optimized',
useSqlite: true
});
expect(firstBuild).toBeDefined();
const secondBuild = await mcpClient.executeTool('build_object_index', {
mode: 'optimized',
useSqlite: true
});
expect(secondBuild).toBeDefined();
// Both builds should complete successfully
expect(firstBuild.content).toBeDefined();
expect(secondBuild.content).toBeDefined();
console.log('ā
Index builds are consistent');
}, INTEGRATION_CONFIG.timeouts.consistency);
test('should maintain query result consistency', async () => {
if (!(await isIntegrationAvailable())) return;
console.log('š Testing query result consistency...');
// Ensure index exists
await mcpClient.executeTool('build_object_index', { mode: 'check' });
// Run same query multiple times
const queryParams = {
pattern: '*',
objectType: 'AxClass',
limit: 10
};
const results = [];
for (let i = 0; i < 3; i++) {
const result = await mcpClient.executeTool('search_objects_pattern', queryParams);
results.push(result);
}
// All results should be defined and consistent
results.forEach(result => {
expect(result).toBeDefined();
expect(result.content).toBeDefined();
});
console.log('ā
Query results are consistent');
}, INTEGRATION_CONFIG.timeouts.consistency);
test('should handle concurrent operations consistently', async () => {
if (!(await isIntegrationAvailable())) return;
console.log('ā” Testing concurrent operation consistency...');
// Run multiple operations concurrently
const operations = [
mcpClient.executeTool('get_current_config'),
mcpClient.executeTool('search_objects_pattern', { pattern: '*', objectType: 'AxClass', limit: 5 }),
mcpClient.executeTool('search_objects_pattern', { pattern: '*', objectType: 'AxTable', limit: 5 })
];
const results = await Promise.all(operations);
// All operations should complete successfully
results.forEach(result => {
expect(result).toBeDefined();
expect(result.content).toBeDefined();
});
console.log('ā
Concurrent operations maintain consistency');
}, INTEGRATION_CONFIG.timeouts.consistency);
});
// =============================================================================
// š REAL-WORLD SCENARIO TESTS
// =============================================================================
describe('š Real-World Scenarios', () => {
test('should support typical developer workflow scenario', async () => {
if (!(await isIntegrationAvailable())) return;
console.log('šØāš» Testing real-world developer scenario...');
// Scenario: Developer needs to find customer-related objects for a new feature
console.log(' Scenario: Finding customer-related objects...');
// Step 1: Search for customer classes
const customerClasses = await mcpClient.executeTool('search_objects_pattern', {
pattern: '*Customer*',
objectType: 'AxClass',
limit: 10
});
expect(customerClasses).toBeDefined();
// Step 2: Search for customer tables
const customerTables = await mcpClient.executeTool('search_objects_pattern', {
pattern: '*Customer*',
objectType: 'AxTable',
limit: 10
});
expect(customerTables).toBeDefined();
// Step 3: Search for customer forms
const customerForms = await mcpClient.executeTool('search_objects_pattern', {
pattern: '*Customer*',
objectType: 'AxForm',
limit: 5
});
expect(customerForms).toBeDefined();
console.log('ā
Developer workflow scenario completed successfully');
}, INTEGRATION_CONFIG.timeouts.workflow);
test('should support enterprise search scenario', async () => {
if (!(await isIntegrationAvailable())) return;
console.log('š¢ Testing enterprise search scenario...');
// Scenario: Enterprise architect needs to analyze system architecture
console.log(' Scenario: Enterprise architecture analysis...');
// Step 1: Get system overview
const systemConfig = await mcpClient.executeTool('get_current_config');
expect(systemConfig).toBeDefined();
// Step 2: Search for standard object types
const objectTypes = await mcpClient.executeTool('search_objects_pattern', {
pattern: '*',
objectType: 'AxClass',
limit: 10,
format: 'json'
});
expect(objectTypes).toBeDefined();
// Step 3: Sample objects from major categories
const majorCategories = [
{ type: 'AxClass', pattern: '*' },
{ type: 'AxTable', pattern: '*' },
{ type: 'AxForm', pattern: '*' }
];
for (const category of majorCategories) {
const sample = await mcpClient.executeTool('search_objects_pattern', {
pattern: category.pattern,
objectType: category.type,
limit: 5
});
expect(sample).toBeDefined();
}
console.log('ā
Enterprise search scenario completed successfully');
}, INTEGRATION_CONFIG.timeouts.workflow);
test('should support performance monitoring scenario', async () => {
if (!(await isIntegrationAvailable())) return;
console.log('š Testing performance monitoring scenario...');
// Scenario: Operations team monitors system performance
console.log(' Scenario: System performance monitoring...');
const performanceMetrics = [];
// Monitor index build performance
const startTime = Date.now();
const indexResult = await mcpClient.executeTool('build_object_index', {
mode: 'check',
useSqlite: true
});
const indexDuration = Date.now() - startTime;
performanceMetrics.push({ operation: 'index_check', duration: indexDuration });
// Monitor search performance
const searchStartTime = Date.now();
const searchResult = await mcpClient.executeTool('search_objects_pattern', {
pattern: '*',
objectType: 'AxClass',
limit: 10
});
const searchDuration = Date.now() - searchStartTime;
performanceMetrics.push({ operation: 'search', duration: searchDuration });
// Validate all operations completed successfully
expect(indexResult).toBeDefined();
expect(searchResult).toBeDefined();
// Log performance metrics
performanceMetrics.forEach(metric => {
console.log(` ${metric.operation}: ${metric.duration}ms`);
});
console.log('ā
Performance monitoring scenario completed successfully');
}, INTEGRATION_CONFIG.timeouts.workflow);
});
console.log('š Integration Test Suite loaded and ready');