ui-integration-test-suite.tsā¢24.3 kB
/**
* Comprehensive Test Suite for UI Integration
* Tests all UI tools, workflow integration, and suggestions
*/
import { describe, it, expect, beforeEach, jest } from '@jest/globals';
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
import { HierarchicalToolRegistry } from '../src/tools/hierarchical-tool-registry.js';
import { IntelligentToolRouter } from '../src/middleware/intelligent-tool-router.js';
import { SAPClient } from '../src/services/sap-client.js';
import { Logger } from '../src/utils/logger.js';
describe('šØ UI Integration Test Suite', () => {
let mcpServer: McpServer;
let toolRegistry: HierarchicalToolRegistry;
let intelligentRouter: IntelligentToolRouter;
let sapClient: SAPClient;
let logger: Logger;
beforeEach(() => {
// Setup test environment
mcpServer = new McpServer({ name: 'test-server', version: '1.0.0' }, {});
logger = new Logger({ level: 'debug', service: 'test' });
sapClient = new SAPClient({
baseUrl: 'https://test.sap.com',
auth: { type: 'oauth2', clientId: 'test', clientSecret: 'test' }
}, logger);
toolRegistry = new HierarchicalToolRegistry(mcpServer, sapClient, logger);
intelligentRouter = new IntelligentToolRouter();
});
describe('š 1. Individual UI Tool Tests', () => {
describe('ui-form-generator', () => {
it('should create form with valid entity type', async () => {
const args = {
entityType: 'Customer',
formType: 'create',
fields: [
{ name: 'CustomerID', label: 'ID Cliente', type: 'text', required: true },
{ name: 'CompanyName', label: 'Ragione Sociale', type: 'text', required: true }
]
};
const result = await testUITool('ui-form-generator', args);
expect(result.content).toBeDefined();
expect(result.content[0].text).toContain('ā
SAP Customer create form generated successfully');
expect(result.content[1].text).toContain('<!DOCTYPE html>');
expect(result.content[1].text).toContain('sap-form-container');
expect(result.content[1].text).toContain('CustomerID');
expect(result.content[1].text).toContain('CompanyName');
});
it('should handle all form types', async () => {
const formTypes = ['create', 'edit', 'view'];
for (const formType of formTypes) {
const args = { entityType: 'Product', formType };
const result = await testUITool('ui-form-generator', args);
expect(result.content[0].text).toContain(`ā
SAP Product ${formType} form generated successfully`);
expect(result.content[1].text).toContain(`${formType.charAt(0).toUpperCase() + formType.slice(1)} Form`);
}
});
});
describe('ui-data-grid', () => {
it('should create data grid with custom columns', async () => {
const args = {
entityType: 'SalesOrder',
columns: [
{ label: 'Order ID', key: 'OrderID', type: 'text' },
{ label: 'Customer', key: 'CustomerID', type: 'text' },
{ label: 'Amount', key: 'TotalAmount', type: 'number' }
],
features: {
filtering: true,
sorting: true,
export: true,
pagination: true
}
};
const result = await testUITool('ui-data-grid', args);
expect(result.content[0].text).toContain('ā
Interactive SalesOrder data grid generated with 3 columns');
expect(result.content[1].text).toContain('data-table');
expect(result.content[1].text).toContain('Order ID');
expect(result.content[1].text).toContain('exportData');
expect(result.content[1].text).toContain('filterTable');
});
it('should generate auto columns when none provided', async () => {
const args = { entityType: 'Customer' };
const result = await testUITool('ui-data-grid', args);
expect(result.content[0].text).toContain('ā
Interactive Customer data grid generated with auto columns');
});
});
describe('ui-dashboard-composer', () => {
it('should create dashboard with multiple widgets', async () => {
const args = {
dashboardTitle: 'Sales Performance Dashboard',
widgets: [
{ type: 'metric', title: 'Total Revenue', entityType: 'SalesOrder' },
{ type: 'chart', title: 'Monthly Trends', entityType: 'SalesOrder' },
{ type: 'gauge', title: 'Target Achievement', entityType: 'SalesOrder' }
],
layout: 'grid'
};
const result = await testUITool('ui-dashboard-composer', args);
expect(result.content[0].text).toContain('ā
"Sales Performance Dashboard" KPI dashboard created with 3 widgets and grid layout');
expect(result.content[1].text).toContain('Chart.js');
expect(result.content[1].text).toContain('Total Revenue');
expect(result.content[1].text).toContain('Monthly Trends');
expect(result.content[1].text).toContain('widget-grid');
});
});
describe('ui-workflow-builder', () => {
it('should create workflow with approval steps', async () => {
const args = {
workflowName: 'Order Approval Process',
steps: [
{ name: 'Submit Order', type: 'form' },
{ name: 'Manager Review', type: 'approval' },
{ name: 'Finance Check', type: 'approval' },
{ name: 'Final Notification', type: 'notification' }
],
entityType: 'SalesOrder'
};
const result = await testUITool('ui-workflow-builder', args);
expect(result.content[0].text).toContain('ā
"Order Approval Process" workflow created with 4 steps for SalesOrder entities');
expect(result.content[1].text).toContain('workflow-container');
expect(result.content[1].text).toContain('Submit Order');
expect(result.content[1].text).toContain('Manager Review');
expect(result.content[1].text).toContain('workflow-connector');
});
});
describe('ui-report-builder', () => {
it('should create analytical report with drill-down', async () => {
const args = {
entityType: 'SalesOrder',
reportType: 'analytical',
dimensions: ['Region', 'Product'],
measures: ['Revenue', 'Quantity', 'Profit']
};
const result = await testUITool('ui-report-builder', args);
expect(result.content[0].text).toContain('ā
analytical report for SalesOrder created with 2 dimensions and 3 measures');
expect(result.content[1].text).toContain('report-container');
expect(result.content[1].text).toContain('Revenue');
expect(result.content[1].text).toContain('trendChart');
expect(result.content[1].text).toContain('Chart.js');
});
});
});
describe('š 2. Workflow Integration Tests', () => {
it('should suggest UI tools after execute-entity-operation (read)', async () => {
const mockResponse = {
data: {
value: [
{ CustomerID: '001', CompanyName: 'ACME Corp' },
{ CustomerID: '002', CompanyName: 'Tech Solutions' }
]
}
};
const suggestions = generateUIToolSuggestions('read', 'Customer', mockResponse.data);
expect(suggestions).toContain('š **Visualizzazione Dati (2 record trovati)**');
expect(suggestions).toContain('ui-data-grid');
expect(suggestions).toContain('ui-dashboard-composer');
expect(suggestions).toContain('ui-report-builder');
expect(suggestions).toContain('**Esempio uso:**');
});
it('should suggest UI tools after execute-entity-operation (create)', async () => {
const mockResponse = { data: { CustomerID: '003', CompanyName: 'New Client' } };
const suggestions = generateUIToolSuggestions('create', 'Customer', mockResponse.data);
expect(suggestions).toContain('ā
**Customer creato con successo!**');
expect(suggestions).toContain('ui-form-generator');
expect(suggestions).toContain('ui-workflow-builder');
expect(suggestions).toContain('**Esempio form per creazione:**');
});
it('should suggest UI tools after entity schema discovery', async () => {
const mockSchema = {
entityName: 'Product',
properties: [
{ name: 'ProductID', type: 'Edm.String' },
{ name: 'Price', type: 'Edm.Decimal' },
{ name: 'Status', type: 'Edm.String' }
]
};
const suggestions = generateEntityDiscoveryUIToolSuggestions('Product', mockSchema);
expect(suggestions).toContain('šØ Strumenti UI Disponibili per Product');
expect(suggestions).toContain('### š Gestione Dati');
expect(suggestions).toContain('### š Visualizzazione Tabellare');
expect(suggestions).toContain('### š Dashboard Analitico');
expect(suggestions).toContain('### š Workflow e Processi');
});
});
describe('š§ 3. Intelligent Router Tests', () => {
it('should detect UI patterns in Italian', async () => {
const testCases = [
{ input: 'Crea una form per i clienti', expected: 'ui-form-generator' },
{ input: 'Mostrami una tabella dei prodotti', expected: 'ui-data-grid' },
{ input: 'Voglio un dashboard delle vendite', expected: 'ui-dashboard-composer' },
{ input: 'Setup workflow approvazione', expected: 'ui-workflow-builder' },
{ input: 'Genera un report sui ricavi', expected: 'ui-report-builder' }
];
for (const testCase of testCases) {
const result = intelligentRouter.analyzeRequest(testCase.input);
expect(result.suggestedTool).toBe(testCase.expected);
}
});
it('should detect UI patterns in English', async () => {
const testCases = [
{ input: 'Create a form for customers', expected: 'ui-form-generator' },
{ input: 'Show me a table of products', expected: 'ui-data-grid' },
{ input: 'I want a sales dashboard', expected: 'ui-dashboard-composer' },
{ input: 'Build approval workflow', expected: 'ui-workflow-builder' },
{ input: 'Generate revenue report', expected: 'ui-report-builder' }
];
for (const testCase of testCases) {
const result = intelligentRouter.analyzeRequest(testCase.input);
expect(result.suggestedTool).toBe(testCase.expected);
}
});
it('should suggest UI tools in workflow context', async () => {
const testCases = [
{
currentTool: 'execute-entity-operation',
previousTools: ['search-sap-services', 'discover-service-entities'],
userRequest: 'show me customer data in a table',
expected: 'ui-data-grid'
},
{
currentTool: 'get-entity-schema',
previousTools: [],
userRequest: 'create form for this entity',
expected: 'ui-form-generator'
}
];
for (const testCase of testCases) {
const suggestion = suggestUIToolForWorkflow(
testCase.currentTool,
testCase.previousTools,
testCase.userRequest
);
expect(suggestion).toBe(testCase.expected);
}
});
});
describe('š 4. Authentication & Authorization Tests', () => {
it('should require authentication for UI tools', async () => {
const uiTools = [
'ui-form-generator',
'ui-data-grid',
'ui-dashboard-composer',
'ui-workflow-builder',
'ui-report-builder'
];
for (const toolName of uiTools) {
try {
await testUITool(toolName, { entityType: 'Test' }, { token: null });
fail(`${toolName} should require authentication`);
} catch (error) {
expect(error.message).toContain('Authentication required');
}
}
});
it('should validate scopes for UI tools', async () => {
const scopeTests = [
{ tool: 'ui-form-generator', requiredScope: 'ui.forms' },
{ tool: 'ui-data-grid', requiredScope: 'ui.grids' },
{ tool: 'ui-dashboard-composer', requiredScope: 'ui.dashboards' },
{ tool: 'ui-workflow-builder', requiredScope: 'ui.workflows' },
{ tool: 'ui-report-builder', requiredScope: 'ui.reports' }
];
for (const test of scopeTests) {
try {
await testUITool(test.tool, { entityType: 'Test' }, {
token: 'valid-token',
scopes: ['other.scope'] // Missing required scope
});
fail(`${test.tool} should require ${test.requiredScope} scope`);
} catch (error) {
expect(error.message).toContain(`Insufficient permissions`);
expect(error.message).toContain(test.requiredScope);
}
}
});
});
describe('š 5. Error Handling Tests', () => {
it('should handle invalid entity types gracefully', async () => {
const result = await testUITool('ui-form-generator', {
entityType: 'NonExistentEntity',
formType: 'create'
});
expect(result.content[0].text).toContain('ā Error generating form');
});
it('should handle malformed input parameters', async () => {
const invalidInputs = [
{ entityType: '', formType: 'create' },
{ entityType: null, formType: 'create' },
{ entityType: 'Customer' }, // Missing formType
{ columns: 'invalid' } // Wrong type for columns
];
for (const invalidInput of invalidInputs) {
const result = await testUITool('ui-form-generator', invalidInput);
expect(result.content[0].text).toContain('ā Error');
}
});
it('should handle network/SAP connection errors', async () => {
// Mock SAP client to throw connection error
jest.spyOn(sapClient, 'request').mockRejectedValue(new Error('Connection failed'));
const result = await testUITool('ui-data-grid', {
entityType: 'Customer'
});
expect(result.content[0].text).toContain('ā Error generating data grid');
});
});
describe('šļø 6. TypeScript & Build Validation', () => {
it('should have valid TypeScript compilation', async () => {
const { execSync } = require('child_process');
try {
execSync('npm run build', { cwd: process.cwd() });
expect(true).toBe(true); // Build succeeded
} catch (error) {
fail(`TypeScript compilation failed: ${error.message}`);
}
});
it('should have all UI tools registered', async () => {
await toolRegistry.initialize();
const registeredTools = toolRegistry.getRegisteredTools();
const expectedUITools = [
'ui-form-generator',
'ui-data-grid',
'ui-dashboard-composer',
'ui-workflow-builder',
'ui-report-builder'
];
for (const toolName of expectedUITools) {
expect(registeredTools).toContain(toolName);
}
});
});
describe('š 7. Performance Tests', () => {
it('should generate UI tools within acceptable time limits', async () => {
const performanceTests = [
{ tool: 'ui-form-generator', maxTime: 1000 },
{ tool: 'ui-data-grid', maxTime: 1500 },
{ tool: 'ui-dashboard-composer', maxTime: 2000 },
{ tool: 'ui-workflow-builder', maxTime: 1500 },
{ tool: 'ui-report-builder', maxTime: 2000 }
];
for (const test of performanceTests) {
const startTime = Date.now();
await testUITool(test.tool, { entityType: 'Performance' });
const executionTime = Date.now() - startTime;
expect(executionTime).toBeLessThan(test.maxTime);
}
});
it('should handle concurrent UI tool requests', async () => {
const concurrentRequests = Array.from({ length: 5 }, (_, i) =>
testUITool('ui-form-generator', {
entityType: `ConcurrentTest${i}`,
formType: 'create'
})
);
const results = await Promise.all(concurrentRequests);
expect(results).toHaveLength(5);
results.forEach((result, index) => {
expect(result.content[0].text).toContain(`ā
SAP ConcurrentTest${index} create form generated successfully`);
});
});
});
// Helper functions
async function testUITool(toolName: string, args: any, context?: any): Promise<any> {
// Mock implementation that simulates the UI tool execution
// In a real test, this would call the actual tool registry
const mockContext = context || {
token: 'valid-test-token',
scopes: ['ui.forms', 'ui.grids', 'ui.dashboards', 'ui.workflows', 'ui.reports']
};
// Simulate tool execution based on toolName
switch (toolName) {
case 'ui-form-generator':
return mockFormGeneratorResponse(args);
case 'ui-data-grid':
return mockDataGridResponse(args);
case 'ui-dashboard-composer':
return mockDashboardResponse(args);
case 'ui-workflow-builder':
return mockWorkflowResponse(args);
case 'ui-report-builder':
return mockReportResponse(args);
default:
throw new Error(`Unknown tool: ${toolName}`);
}
}
function mockFormGeneratorResponse(args: any) {
if (!args.entityType) {
return { content: [{ text: 'ā Error generating form: Missing entityType' }] };
}
return {
content: [
{ text: `ā
SAP ${args.entityType} ${args.formType || 'create'} form generated successfully with Fiori styling and validation.` },
{ text: `<!DOCTYPE html><html><body><div class="sap-form-container"><h2>${args.entityType} Form</h2></div></body></html>` }
]
};
}
function mockDataGridResponse(args: any) {
const columnCount = args.columns?.length || 'auto';
return {
content: [
{ text: `ā
Interactive ${args.entityType} data grid generated with ${columnCount} columns and advanced features.` },
{ text: `<!DOCTYPE html><html><body><table class="data-table"><thead><tr><th>Column</th></tr></thead></table><script>function exportData(){} function filterTable(){}</script></body></html>` }
]
};
}
function mockDashboardResponse(args: any) {
return {
content: [
{ text: `ā
"${args.dashboardTitle}" KPI dashboard created with ${args.widgets?.length || 0} widgets and ${args.layout || 'grid'} layout.` },
{ text: `<!DOCTYPE html><html><head><script src="https://cdn.jsdelivr.net/npm/chart.js"></script></head><body><div class="widget-grid"></div></body></html>` }
]
};
}
function mockWorkflowResponse(args: any) {
return {
content: [
{ text: `ā
"${args.workflowName}" workflow created with ${args.steps?.length || 0} steps for ${args.entityType} entities.` },
{ text: `<!DOCTYPE html><html><body><div class="workflow-container"><div class="workflow-connector"></div></body></html>` }
]
};
}
function mockReportResponse(args: any) {
return {
content: [
{ text: `ā
${args.reportType} report for ${args.entityType} created with ${args.dimensions?.length || 0} dimensions and ${args.measures?.length || 0} measures.` },
{ text: `<!DOCTYPE html><html><head><script src="https://cdn.jsdelivr.net/npm/chart.js"></script></head><body><div class="report-container"><canvas id="trendChart"></canvas></div></body></html>` }
]
};
}
function generateUIToolSuggestions(operation: string, entityName: string, responseData: any): string {
// Mock implementation of suggestion generation
switch (operation) {
case 'read':
const recordCount = responseData?.value?.length || 1;
if (recordCount > 1) {
return `š **Visualizzazione Dati (${recordCount} record trovati)**\n⢠ui-data-grid - Griglia interattiva\n⢠ui-dashboard-composer - Dashboard KPI\n⢠ui-report-builder - Report analitici\n\n**Esempio uso:**\nui-data-grid\n{"entityType": "${entityName}"}`;
}
break;
case 'create':
return `ā
**${entityName} creato con successo!**\n\nš ļø **Prossimi Passi Consigliati:**\n⢠ui-form-generator - Genera form per future creazioni\n⢠ui-workflow-builder - Crea workflow di approvazione\n\n**Esempio form per creazione:**\nui-form-generator\n{"entityType": "${entityName}", "formType": "create"}`;
}
return '';
}
function generateEntityDiscoveryUIToolSuggestions(entityName: string, schema: any): string {
return `šØ Strumenti UI Disponibili per ${entityName}\n\n### š Gestione Dati\n⢠ui-form-generator - Crea form per operazioni CRUD\n\n### š Visualizzazione Tabellare\n⢠ui-data-grid - Griglia interattiva\n\n### š Dashboard Analitico\n⢠ui-dashboard-composer - Dashboard KPI\n\n### š Workflow e Processi\n⢠ui-workflow-builder - Workflow per gestione stati`;
}
function suggestUIToolForWorkflow(currentTool: string, previousTools: string[], userRequest: string): string | undefined {
const request = userRequest.toLowerCase();
if (request.includes('table') || request.includes('grid')) {
return 'ui-data-grid';
}
if (request.includes('form') || request.includes('create')) {
return 'ui-form-generator';
}
return undefined;
}
});