Skip to main content
Glama
test-enhanced-adapters.js24.8 kB
#!/usr/bin/env node /** * Enhanced Subject Adapters Test Suite * @description Comprehensive testing for PhysicsAdapter, ChemistryAdapter, HistoryAdapter, and AdapterFactory * @version 5.0.0-alpha */ import { BaseAdapter, PhysicsAdapter, ChemistryAdapter, HistoryAdapter, AdapterFactory, adapterFactory, createOptimalAdapter, generateEnhancedContent } from '../../src/content-generation/index.js'; class EnhancedAdaptersTestSuite { constructor() { this.totalTests = 0; this.passedTests = 0; this.failedTests = 0; this.testResults = []; this.startTime = Date.now(); } /** * Run all enhanced adapter tests */ async runAllTests() { console.log('🧪 Enhanced Subject Adapters Test Suite v5.0.0-alpha'); console.log('=' .repeat(60)); try { // Test individual enhanced adapters await this.testPhysicsAdapter(); await this.testChemistryAdapter(); await this.testHistoryAdapter(); // Test adapter factory system await this.testAdapterFactory(); await this.testAdapterSelection(); await this.testEnhancedContentGeneration(); // Test integration and performance await this.testIntegrationScenarios(); await this.testPerformanceMetrics(); // Test fallback mechanisms await this.testFallbackBehavior(); this.printTestSummary(); } catch (error) { console.error('❌ Test suite execution failed:', error); process.exit(1); } } /** * Test PhysicsAdapter functionality */ async testPhysicsAdapter() { console.log('\n📐 Testing PhysicsAdapter...'); // Test physics adapter instantiation await this.runTest('PhysicsAdapter instantiation', async () => { const adapter = new PhysicsAdapter(); this.assert(adapter instanceof PhysicsAdapter, 'PhysicsAdapter should be instantiated'); this.assert(adapter instanceof BaseAdapter, 'PhysicsAdapter should extend BaseAdapter'); this.assert(adapter.config.subject === 'física', 'Subject should be física'); this.assert(adapter.config.enhancedFeatures.includes('equations'), 'Should include equations feature'); }); // Test physics content generation await this.runTest('Physics content generation', async () => { const adapter = new PhysicsAdapter(); const analysis = await adapter.analyzeTopic('Movimento de projéteis e balística'); this.assert(analysis.subject === 'física', 'Should identify physics subject'); const content = await adapter.generateContent(analysis); this.assert(content.metadata.subject === 'física', 'Content should be marked as physics'); this.assert(content.metadata.enhancedFeatures.includes('equations'), 'Should include enhanced features'); this.assert(content.components.equations, 'Should include equations component'); this.assert(content.components.diagrams, 'Should include diagrams component'); this.assert(content.components.calculations, 'Should include calculations component'); }); // Test physics-specific enhancements await this.runTest('Physics enhanced features', async () => { const adapter = new PhysicsAdapter(); const analysis = await adapter.analyzeTopic('Leis de Newton e dinâmica'); const content = await adapter.generateContent(analysis); // Check equations component this.assert(content.components.equations.type === 'equations', 'Equations component should exist'); this.assert(Array.isArray(content.components.equations.equations), 'Should have equations array'); // Check physics problem types this.assert(content.metadata.physicsType, 'Should identify physics type'); // Check enhanced explanation this.assert( content.components.explanation.content.includes('Princípios Físicos'), 'Should include physics principles' ); }); } /** * Test ChemistryAdapter functionality */ async testChemistryAdapter() { console.log('\n🧪 Testing ChemistryAdapter...'); // Test chemistry adapter instantiation await this.runTest('ChemistryAdapter instantiation', async () => { const adapter = new ChemistryAdapter(); this.assert(adapter instanceof ChemistryAdapter, 'ChemistryAdapter should be instantiated'); this.assert(adapter instanceof BaseAdapter, 'ChemistryAdapter should extend BaseAdapter'); this.assert(adapter.config.subject === 'química', 'Subject should be química'); this.assert(adapter.config.enhancedFeatures.includes('molecular_structures'), 'Should include molecular structures'); }); // Test chemistry content generation await this.runTest('Chemistry content generation', async () => { const adapter = new ChemistryAdapter(); const analysis = await adapter.analyzeTopic('Ligações químicas e estrutura molecular'); this.assert(analysis.subject === 'química', 'Should identify chemistry subject'); const content = await adapter.generateContent(analysis); this.assert(content.metadata.subject === 'química', 'Content should be marked as chemistry'); this.assert(content.metadata.enhancedFeatures.includes('reactions'), 'Should include enhanced features'); this.assert(content.components.molecular_structures, 'Should include molecular structures component'); this.assert(content.components.reactions, 'Should include reactions component'); this.assert(content.components.periodic_table, 'Should include periodic table component'); this.assert(content.components.laboratory, 'Should include laboratory component'); }); // Test chemistry-specific enhancements await this.runTest('Chemistry enhanced features', async () => { const adapter = new ChemistryAdapter(); const analysis = await adapter.analyzeTopic('Reações orgânicas e mecanismos'); const content = await adapter.generateContent(analysis); // Check molecular structures component this.assert(content.components.molecular_structures.type === 'molecular_structures', 'Molecular component should exist'); this.assert(content.components.molecular_structures.aspects, 'Should have molecular aspects'); // Check chemistry type identification this.assert(content.metadata.chemistryType, 'Should identify chemistry type'); // Check enhanced explanation this.assert( content.components.explanation.content.includes('Princípios Químicos'), 'Should include chemistry principles' ); }); } /** * Test HistoryAdapter functionality */ async testHistoryAdapter() { console.log('\n📚 Testing HistoryAdapter...'); // Test history adapter instantiation await this.runTest('HistoryAdapter instantiation', async () => { const adapter = new HistoryAdapter(); this.assert(adapter instanceof HistoryAdapter, 'HistoryAdapter should be instantiated'); this.assert(adapter instanceof BaseAdapter, 'HistoryAdapter should extend BaseAdapter'); this.assert(adapter.config.subject === 'história', 'Subject should be história'); this.assert(adapter.config.enhancedFeatures.includes('timelines'), 'Should include timelines feature'); }); // Test history content generation await this.runTest('History content generation', async () => { const adapter = new HistoryAdapter(); const analysis = await adapter.analyzeTopic('Revolução Francesa e suas consequências'); this.assert(analysis.subject === 'história', 'Should identify history subject'); const content = await adapter.generateContent(analysis); this.assert(content.metadata.subject === 'história', 'Content should be marked as history'); this.assert(content.metadata.enhancedFeatures.includes('causality'), 'Should include enhanced features'); this.assert(content.components.timeline, 'Should include timeline component'); this.assert(content.components.causality, 'Should include causality component'); this.assert(content.components.cultural_context, 'Should include cultural context component'); this.assert(content.components.primary_sources, 'Should include primary sources component'); }); // Test history-specific enhancements await this.runTest('History enhanced features', async () => { const adapter = new HistoryAdapter(); const analysis = await adapter.analyzeTopic('Segunda Guerra Mundial e impactos sociais'); const content = await adapter.generateContent(analysis); // Check timeline component this.assert(content.components.timeline.type === 'timeline', 'Timeline component should exist'); this.assert(Array.isArray(content.components.timeline.events), 'Should have timeline events'); // Check historical period identification this.assert(content.metadata.historicalPeriod, 'Should identify historical period'); this.assert(content.metadata.historyType, 'Should identify history type'); // Check enhanced explanation this.assert( content.components.explanation.content.includes('Contexto Histórico'), 'Should include historical context' ); }); } /** * Test AdapterFactory functionality */ async testAdapterFactory() { console.log('\n🏭 Testing AdapterFactory...'); // Test adapter factory instantiation await this.runTest('AdapterFactory instantiation', async () => { const factory = new AdapterFactory(); this.assert(factory instanceof AdapterFactory, 'AdapterFactory should be instantiated'); this.assert(typeof factory.createAdapter === 'function', 'Should have createAdapter method'); this.assert(typeof factory.generateContentWithOptimalAdapter === 'function', 'Should have content generation method'); }); // Test available adapters await this.runTest('Available adapters listing', async () => { const factory = new AdapterFactory(); const adapters = factory.getAvailableAdapters(); this.assert(Array.isArray(adapters), 'Should return array of adapters'); this.assert(adapters.length >= 4, 'Should have at least 4 adapters (Base + 3 enhanced)'); const adapterNames = adapters.map(a => a.name); this.assert(adapterNames.includes('BaseAdapter'), 'Should include BaseAdapter'); this.assert(adapterNames.includes('PhysicsAdapter'), 'Should include PhysicsAdapter'); this.assert(adapterNames.includes('ChemistryAdapter'), 'Should include ChemistryAdapter'); this.assert(adapterNames.includes('HistoryAdapter'), 'Should include HistoryAdapter'); }); // Test subject pattern matching await this.runTest('Subject pattern matching', async () => { const factory = new AdapterFactory(); // Test physics patterns const physicsScore = factory.calculateSubjectScore( 'movimento projétil balística energia cinética', factory.subjectPatterns.physics ); this.assert(physicsScore > 0.5, 'Should detect physics patterns'); // Test chemistry patterns const chemistryScore = factory.calculateSubjectScore( 'reação química ligações moleculares átomos', factory.subjectPatterns.chemistry ); this.assert(chemistryScore > 0.5, 'Should detect chemistry patterns'); // Test history patterns const historyScore = factory.calculateSubjectScore( 'revolução francesa guerra independência', factory.subjectPatterns.history ); this.assert(historyScore > 0.5, 'Should detect history patterns'); }); } /** * Test adapter selection logic */ async testAdapterSelection() { console.log('\n🎯 Testing Adapter Selection...'); // Test physics adapter selection await this.runTest('Physics adapter selection', async () => { const physicsAdapter = await createOptimalAdapter('Leis de Newton e movimento de projéteis'); this.assert(physicsAdapter instanceof PhysicsAdapter, 'Should select PhysicsAdapter for physics topics'); }); // Test chemistry adapter selection await this.runTest('Chemistry adapter selection', async () => { const chemistryAdapter = await createOptimalAdapter('Estrutura atômica e ligações químicas'); this.assert(chemistryAdapter instanceof ChemistryAdapter, 'Should select ChemistryAdapter for chemistry topics'); }); // Test history adapter selection await this.runTest('History adapter selection', async () => { const historyAdapter = await createOptimalAdapter('Revolução Industrial e transformações sociais'); this.assert(historyAdapter instanceof HistoryAdapter, 'Should select HistoryAdapter for history topics'); }); // Test fallback to BaseAdapter await this.runTest('BaseAdapter fallback', async () => { const baseAdapter = await createOptimalAdapter('Técnicas de jardinagem e cultivo de plantas'); this.assert(baseAdapter instanceof BaseAdapter, 'Should fallback to BaseAdapter for non-specialized topics'); this.assert(!(baseAdapter instanceof PhysicsAdapter), 'Should not be PhysicsAdapter'); this.assert(!(baseAdapter instanceof ChemistryAdapter), 'Should not be ChemistryAdapter'); this.assert(!(baseAdapter instanceof HistoryAdapter), 'Should not be HistoryAdapter'); }); // Test adapter validation await this.runTest('Adapter selection validation', async () => { const validation = await adapterFactory.validateAdapterSelection('Mecânica quântica e física moderna'); this.assert(validation.selectedAdapter, 'Should have selected adapter'); this.assert(validation.confidence >= 0, 'Should have confidence score'); this.assert(validation.analysis, 'Should have analysis result'); this.assert(validation.recommendation, 'Should have recommendation'); this.assert(Array.isArray(validation.alternatives), 'Should have alternatives array'); }); } /** * Test enhanced content generation */ async testEnhancedContentGeneration() { console.log('\n✨ Testing Enhanced Content Generation...'); // Test physics enhanced content await this.runTest('Physics enhanced content', async () => { const content = await generateEnhancedContent('Balística e movimento de projéteis'); this.assert(content.metadata.adapterUsed === 'PhysicsAdapter', 'Should use PhysicsAdapter'); this.assert(Array.isArray(content.metadata.enhancedFeatures), 'Should have enhanced features'); this.assert(content.metadata.enhancedFeatures.includes('equations'), 'Should include equations'); this.assert(content.components.equations, 'Should have equations component'); }); // Test chemistry enhanced content await this.runTest('Chemistry enhanced content', async () => { const content = await generateEnhancedContent('Reações químicas e balanceamento'); this.assert(content.metadata.adapterUsed === 'ChemistryAdapter', 'Should use ChemistryAdapter'); this.assert(content.metadata.enhancedFeatures.includes('reactions'), 'Should include reactions'); this.assert(content.components.reactions, 'Should have reactions component'); }); // Test history enhanced content await this.runTest('History enhanced content', async () => { const content = await generateEnhancedContent('Idade Média e sistema feudal'); this.assert(content.metadata.adapterUsed === 'HistoryAdapter', 'Should use HistoryAdapter'); this.assert(content.metadata.enhancedFeatures.includes('timelines'), 'Should include timelines'); this.assert(content.components.timeline, 'Should have timeline component'); }); // Test universal content fallback await this.runTest('Universal content fallback', async () => { const content = await generateEnhancedContent('Técnicas de culinária e preparo de alimentos'); this.assert(content.metadata.adapterUsed === 'BaseAdapter', 'Should use BaseAdapter for universal topics'); this.assert(content.components.introduction, 'Should have basic components'); this.assert(content.components.explanation, 'Should have explanation'); this.assert(content.components.summary, 'Should have summary'); }); } /** * Test integration scenarios */ async testIntegrationScenarios() { console.log('\n🔗 Testing Integration Scenarios...'); // Test mixed subject detection await this.runTest('Mixed subject detection', async () => { const content = await generateEnhancedContent('Física nuclear e aplicações na medicina'); // Should prioritize physics given stronger physics indicators this.assert(content.metadata.adapterUsed === 'PhysicsAdapter', 'Should select primary subject adapter'); }); // Test English language fallback await this.runTest('English language fallback', async () => { const content = await generateEnhancedContent('Chemical bonds and molecular structure'); this.assert(content.metadata.adapterUsed === 'ChemistryAdapter', 'Should handle English chemistry topics'); }); // Test grade level adaptation in enhanced adapters await this.runTest('Grade level adaptation', async () => { const elementaryContent = await generateEnhancedContent( 'Força e movimento - 6º ano', { gradeLevel: 'fundamental-2' } ); this.assert(elementaryContent.metadata.gradeLevel === 'fundamental-2', 'Should adapt to grade level'); const advancedContent = await generateEnhancedContent( 'Mecânica quântica - ensino superior', { gradeLevel: 'superior' } ); this.assert(advancedContent.metadata.gradeLevel === 'superior', 'Should handle advanced levels'); }); } /** * Test performance metrics */ async testPerformanceMetrics() { console.log('\n⚡ Testing Performance Metrics...'); // Test generation speed await this.runTest('Enhanced adapter speed', async () => { const startTime = Date.now(); const content = await generateEnhancedContent('Termodinâmica e transferência de calor'); const endTime = Date.now(); const generationTime = endTime - startTime; this.assert(generationTime < 5000, `Generation should complete in <5s (took ${generationTime}ms)`); this.assert(content.components, 'Should generate complete content structure'); }); // Test content quality await this.runTest('Enhanced content quality', async () => { const content = await generateEnhancedContent('Evolução das espécies e seleção natural'); // Check content completeness this.assert(content.metadata, 'Should have metadata'); this.assert(content.components, 'Should have components'); this.assert(Object.keys(content.components).length >= 5, 'Should have multiple components'); // Check content substance const explanation = content.components.explanation; this.assert(explanation.content.length > 100, 'Should have substantial explanation content'); }); // Test memory usage (basic check) await this.runTest('Memory efficiency', async () => { const memBefore = process.memoryUsage().heapUsed; // Generate multiple contents for (let i = 0; i < 5; i++) { await generateEnhancedContent(`Test topic ${i}`); } const memAfter = process.memoryUsage().heapUsed; const memIncrease = memAfter - memBefore; this.assert(memIncrease < 50 * 1024 * 1024, `Memory increase should be <50MB (was ${Math.round(memIncrease / 1024 / 1024)}MB)`); }); } /** * Test fallback behavior */ async testFallbackBehavior() { console.log('\n🛡️ Testing Fallback Behavior...'); // Test graceful degradation await this.runTest('Graceful degradation', async () => { // Test with malformed input const content = await generateEnhancedContent(''); this.assert(content.metadata.adapterUsed === 'BaseAdapter', 'Should fallback for empty input'); this.assert(content.components, 'Should still generate content structure'); }); // Test error handling await this.runTest('Error handling', async () => { try { // Test with extremely long input const longInput = 'palavra '.repeat(1000); const content = await generateEnhancedContent(longInput); this.assert(content.components, 'Should handle long input gracefully'); } catch (error) { this.assert(error.message.includes('generation failed'), 'Should provide meaningful error messages'); } }); // Test adapter factory fallback await this.runTest('Factory fallback mechanism', async () => { const factory = new AdapterFactory(); // Mock an error scenario by creating invalid adapter analysis const invalidAnalysis = { subjectScores: {}, primarySubject: null, confidence: 0, specializationBenefit: 0, recommendedAdapter: 'NonExistentAdapter', fallbackRequired: true }; const selectedAdapter = factory.selectOptimalAdapter(invalidAnalysis); this.assert(selectedAdapter === 'BaseAdapter', 'Should fallback to BaseAdapter for invalid analysis'); }); } /** * Run individual test */ async runTest(testName, testFunction) { this.totalTests++; try { const startTime = Date.now(); await testFunction(); const endTime = Date.now(); const duration = endTime - startTime; this.passedTests++; this.testResults.push({ name: testName, status: 'PASS', duration: duration, error: null }); console.log(` ✅ ${testName} (${duration}ms)`); } catch (error) { this.failedTests++; this.testResults.push({ name: testName, status: 'FAIL', duration: 0, error: error.message }); console.log(` ❌ ${testName}: ${error.message}`); } } /** * Assert condition with message */ assert(condition, message) { if (!condition) { throw new Error(message || 'Assertion failed'); } } /** * Print comprehensive test summary */ printTestSummary() { const endTime = Date.now(); const totalDuration = endTime - this.startTime; const successRate = ((this.passedTests / this.totalTests) * 100).toFixed(1); console.log('\n' + '='.repeat(60)); console.log('📊 ENHANCED ADAPTERS TEST SUMMARY'); console.log('='.repeat(60)); console.log(`Total Tests: ${this.totalTests}`); console.log(`Passed: ${this.passedTests}`); console.log(`Failed: ${this.failedTests}`); console.log(`Success Rate: ${successRate}%`); console.log(`Total Duration: ${totalDuration}ms`); if (this.failedTests > 0) { console.log('\n❌ FAILED TESTS:'); this.testResults .filter(result => result.status === 'FAIL') .forEach(result => { console.log(` • ${result.name}: ${result.error}`); }); } console.log('\n📈 PERFORMANCE METRICS:'); const avgDuration = this.testResults .filter(r => r.status === 'PASS') .reduce((sum, r) => sum + r.duration, 0) / this.passedTests; console.log(`Average Test Duration: ${avgDuration.toFixed(1)}ms`); const maxDuration = Math.max(...this.testResults.map(r => r.duration)); const slowestTest = this.testResults.find(r => r.duration === maxDuration); console.log(`Slowest Test: ${slowestTest.name} (${maxDuration}ms)`); console.log('\n🎯 ENHANCED FEATURES VALIDATED:'); console.log(' ✅ PhysicsAdapter: equations, calculations, diagrams'); console.log(' ✅ ChemistryAdapter: molecular structures, reactions, periodic table'); console.log(' ✅ HistoryAdapter: timelines, causality, cultural context'); console.log(' ✅ AdapterFactory: intelligent selection, fallback mechanism'); console.log(' ✅ Integration: seamless BaseAdapter compatibility'); if (this.passedTests === this.totalTests) { console.log('\n🎉 ALL TESTS PASSED! Enhanced adapters are production-ready.'); process.exit(0); } else { console.log('\n⚠️ Some tests failed. Review failures before deployment.'); process.exit(1); } } } // Run tests if this file is executed directly if (import.meta.url === `file://${process.argv[1]}`) { const testSuite = new EnhancedAdaptersTestSuite(); await testSuite.runAllTests(); }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/rkm097git/euconquisto-composer-mcp-poc'

If you have feedback or need assistance with the MCP directory API, please join our Discord server