Files
Projektarbeit-MYP/backend/static/js/api-validation-test.js

372 lines
13 KiB
JavaScript

/**
* Test-Script für API-Response-Validierung
* Dieses Script testet die validateApiResponse() Funktion in verschiedenen Szenarien
*/
// Globale Test-Ergebnisse
window.apiValidationTestResults = {
passed: 0,
failed: 0,
tests: []
};
/**
* Mock Response für Tests erstellen
*/
function createMockResponse(body, status = 200, headers = {}) {
const defaultHeaders = {
'content-type': 'application/json',
...headers
};
return new Response(body, {
status: status,
statusText: getStatusText(status),
headers: defaultHeaders
});
}
function getStatusText(status) {
const statusTexts = {
200: 'OK',
400: 'Bad Request',
401: 'Unauthorized',
403: 'Forbidden',
404: 'Not Found',
429: 'Too Many Requests',
500: 'Internal Server Error',
503: 'Service Unavailable'
};
return statusTexts[status] || 'Unknown';
}
/**
* Test-Framework Funktionen
*/
function assert(condition, message) {
if (condition) {
console.log(`✅ PASS: ${message}`);
window.apiValidationTestResults.passed++;
window.apiValidationTestResults.tests.push({ test: message, result: 'PASS' });
} else {
console.error(`❌ FAIL: ${message}`);
window.apiValidationTestResults.failed++;
window.apiValidationTestResults.tests.push({ test: message, result: 'FAIL' });
}
}
async function assertThrows(asyncFn, expectedErrorPattern, message) {
try {
await asyncFn();
console.error(`❌ FAIL: ${message} - Expected error but none was thrown`);
window.apiValidationTestResults.failed++;
window.apiValidationTestResults.tests.push({ test: message, result: 'FAIL - No error thrown' });
} catch (error) {
if (expectedErrorPattern.test(error.message)) {
console.log(`✅ PASS: ${message} - Correct error: ${error.message}`);
window.apiValidationTestResults.passed++;
window.apiValidationTestResults.tests.push({ test: message, result: 'PASS' });
} else {
console.error(`❌ FAIL: ${message} - Wrong error: ${error.message}`);
window.apiValidationTestResults.failed++;
window.apiValidationTestResults.tests.push({ test: message, result: `FAIL - Wrong error: ${error.message}` });
}
}
}
/**
* Test-Funktion für validateApiResponse
* Diese Funktion erwartet, dass validateApiResponse global verfügbar ist
*/
async function testValidateApiResponse() {
console.log('🧪 Starte API-Response-Validierung Tests...\n');
// Test 1: Erfolgreiche JSON-Response
console.log('📋 Test 1: Erfolgreiche JSON-Response');
try {
const mockResponse = createMockResponse(
JSON.stringify({ success: true, data: { message: 'Hello World' } })
);
const result = await validateApiResponse(mockResponse, 'Test 1');
assert(result.success === true, 'JSON-Response korrekt geparst');
assert(result.data.message === 'Hello World', 'Daten korrekt extrahiert');
} catch (error) {
console.error(`❌ FAIL: Test 1 - Unexpected error: ${error.message}`);
window.apiValidationTestResults.failed++;
}
// Test 2: HTTP 404 Fehler
console.log('\n📋 Test 2: HTTP 404 Fehler');
await assertThrows(
() => validateApiResponse(createMockResponse('Not Found', 404), 'Test 2'),
/Ressource nicht gefunden \(Test 2\)/,
'HTTP 404 korrekt behandelt'
);
// Test 3: HTTP 401 Fehler
console.log('\n📋 Test 3: HTTP 401 Fehler');
await assertThrows(
() => validateApiResponse(createMockResponse('Unauthorized', 401), 'Test 3'),
/Authentifizierung fehlgeschlagen \(Test 3\)/,
'HTTP 401 korrekt behandelt'
);
// Test 4: HTTP 500 Fehler
console.log('\n📋 Test 4: HTTP 500 Fehler');
await assertThrows(
() => validateApiResponse(createMockResponse('Internal Server Error', 500), 'Test 4'),
/Serverfehler \(Test 4\)/,
'HTTP 500 korrekt behandelt'
);
// Test 5: Falscher Content-Type
console.log('\n📋 Test 5: Falscher Content-Type');
await assertThrows(
() => validateApiResponse(
createMockResponse('Plain text response', 200, { 'content-type': 'text/plain' }),
'Test 5'
),
/Ungültiger Content-Type.*Test 5/,
'Falscher Content-Type korrekt behandelt'
);
// Test 6: HTML-Fehlerseite
console.log('\n📋 Test 6: HTML-Fehlerseite');
await assertThrows(
() => validateApiResponse(
createMockResponse('<!DOCTYPE html><html><body>Error</body></html>', 200, { 'content-type': 'text/html' }),
'Test 6'
),
/Server-Fehlerseite erhalten statt JSON-Response \(Test 6\)/,
'HTML-Fehlerseite korrekt erkannt'
);
// Test 7: Ungültiges JSON
console.log('\n📋 Test 7: Ungültiges JSON');
await assertThrows(
() => validateApiResponse(
createMockResponse('{ invalid json }'),
'Test 7'
),
/Ungültige JSON-Response.*Test 7/,
'Ungültiges JSON korrekt behandelt'
);
// Test 8: Leere Response
console.log('\n📋 Test 8: Leere Response (null)');
await assertThrows(
() => validateApiResponse(
createMockResponse('null'),
'Test 8'
),
/Leere Response erhalten \(Test 8\)/,
'Null-Response korrekt behandelt'
);
// Test 9: API-Fehler mit success: false
console.log('\n📋 Test 9: API-Fehler mit success: false');
await assertThrows(
() => validateApiResponse(
createMockResponse(JSON.stringify({ success: false, error: 'Validation failed' })),
'Test 9'
),
/API-Fehler: Validation failed \(Test 9\)/,
'API-Fehler mit success: false korrekt behandelt'
);
// Test 10: JSON ohne success-Feld (sollte funktionieren)
console.log('\n📋 Test 10: JSON ohne success-Feld');
try {
const mockResponse = createMockResponse(
JSON.stringify({ data: [1, 2, 3], total: 3 })
);
const result = await validateApiResponse(mockResponse, 'Test 10');
assert(Array.isArray(result.data), 'JSON ohne success-Feld korrekt verarbeitet');
assert(result.total === 3, 'Daten korrekt extrahiert');
} catch (error) {
console.error(`❌ FAIL: Test 10 - Unexpected error: ${error.message}`);
window.apiValidationTestResults.failed++;
}
// Ergebnisse ausgeben
console.log('\n🏁 Test-Ergebnisse:');
console.log(`✅ Erfolgreiche Tests: ${window.apiValidationTestResults.passed}`);
console.log(`❌ Fehlgeschlagene Tests: ${window.apiValidationTestResults.failed}`);
console.log(`📊 Erfolgsrate: ${((window.apiValidationTestResults.passed / (window.apiValidationTestResults.passed + window.apiValidationTestResults.failed)) * 100).toFixed(1)}%`);
return window.apiValidationTestResults;
}
/**
* Live-Tests gegen echte API-Endpunkte
*/
async function testLiveAPI() {
console.log('\n🌐 Starte Live-API-Tests...\n');
// API Base URL Detection (wie in den anderen Dateien)
function detectApiBaseUrl() {
const currentPort = window.location.port;
const currentProtocol = window.location.protocol;
const currentHost = window.location.hostname;
if (currentPort === '5000') {
return `${currentProtocol}//${currentHost}:${currentPort}`;
}
if (currentPort === '443' || currentPort === '') {
return `${currentProtocol}//${currentHost}`;
}
return window.location.origin;
}
const apiBaseUrl = detectApiBaseUrl();
// Test 1: Live-API-Test - Stats-Endpunkt
console.log('📋 Live-Test 1: Stats-Endpunkt');
try {
const response = await fetch(`${apiBaseUrl}/api/stats`);
const data = await validateApiResponse(response, 'Live-Stats-Test');
assert(typeof data === 'object', 'Stats-API liefert gültiges JSON');
console.log('📊 Stats-Daten erhalten:', Object.keys(data));
} catch (error) {
console.warn(`⚠️ Live-Test 1 fehlgeschlagen (erwartet bei fehlendem Auth): ${error.message}`);
}
// Test 2: Live-API-Test - Nicht existierender Endpunkt (404)
console.log('\n📋 Live-Test 2: Nicht existierender Endpunkt');
try {
const response = await fetch(`${apiBaseUrl}/api/nonexistent-endpoint-12345`);
await validateApiResponse(response, 'Live-404-Test');
console.error('❌ FAIL: 404-Test - Sollte einen Fehler werfen');
} catch (error) {
if (error.message.includes('404') || error.message.includes('nicht gefunden')) {
console.log('✅ PASS: 404-Fehler korrekt behandelt');
} else {
console.log(`✅ PASS: Fehler korrekt behandelt: ${error.message}`);
}
}
console.log('\n🌐 Live-API-Tests abgeschlossen');
}
/**
* Integration-Tests für spezifische JavaScript-Dateien
*/
async function testIntegration() {
console.log('\n🔗 Starte Integration-Tests...\n');
// Test, ob validateApiResponse in verschiedenen Kontexten verfügbar ist
const testFiles = [
{ name: 'Admin Dashboard', check: () => window.adminDashboard && typeof window.adminDashboard.validateApiResponse === 'function' },
{ name: 'Printer Monitor', check: () => window.printerMonitor && typeof window.printerMonitor.validateApiResponse === 'function' },
{ name: 'Global validateApiResponse', check: () => typeof window.validateApiResponse === 'function' || typeof validateApiResponse === 'function' }
];
testFiles.forEach(test => {
try {
const isAvailable = test.check();
assert(isAvailable, `${test.name} - validateApiResponse verfügbar`);
} catch (error) {
console.warn(`⚠️ ${test.name} - Nicht geladen oder verfügbar: ${error.message}`);
}
});
console.log('\n🔗 Integration-Tests abgeschlossen');
}
/**
* Performance-Tests
*/
async function testPerformance() {
console.log('\n⚡ Starte Performance-Tests...\n');
const iterations = 100;
const startTime = performance.now();
for (let i = 0; i < iterations; i++) {
const mockResponse = createMockResponse(
JSON.stringify({ success: true, data: { iteration: i } })
);
await validateApiResponse(mockResponse, `Performance-Test-${i}`);
}
const endTime = performance.now();
const totalTime = endTime - startTime;
const avgTime = totalTime / iterations;
console.log(`📊 Performance-Ergebnisse:`);
console.log(` Gesamtzeit für ${iterations} Calls: ${totalTime.toFixed(2)}ms`);
console.log(` Durchschnittszeit pro Call: ${avgTime.toFixed(2)}ms`);
console.log(` Overhead pro Call: ${avgTime < 1 ? 'Sehr niedrig' : avgTime < 5 ? 'Niedrig' : 'Hoch'}`);
assert(avgTime < 5, 'Performance-Test - Durchschnittszeit unter 5ms');
console.log('\n⚡ Performance-Tests abgeschlossen');
}
/**
* Haupt-Test-Runner
*/
async function runAllTests() {
console.clear();
console.log('🚀 API-Response-Validierung Test-Suite\n');
console.log('=' * 50 + '\n');
// Reset Test-Ergebnisse
window.apiValidationTestResults = { passed: 0, failed: 0, tests: [] };
try {
// Basis-Tests
await testValidateApiResponse();
// Live-API-Tests
await testLiveAPI();
// Integration-Tests
await testIntegration();
// Performance-Tests
await testPerformance();
// Finale Statistiken
console.log('\n' + '=' * 50);
console.log('🏆 FINALE TEST-ERGEBNISSE:');
console.log(`✅ Gesamt erfolgreich: ${window.apiValidationTestResults.passed}`);
console.log(`❌ Gesamt fehlgeschlagen: ${window.apiValidationTestResults.failed}`);
const total = window.apiValidationTestResults.passed + window.apiValidationTestResults.failed;
const successRate = total > 0 ? (window.apiValidationTestResults.passed / total * 100).toFixed(1) : 0;
console.log(`📊 Erfolgsrate: ${successRate}%`);
if (window.apiValidationTestResults.failed === 0) {
console.log('🎉 ALLE TESTS ERFOLGREICH!');
} else {
console.log('⚠️ Einige Tests sind fehlgeschlagen. Siehe Details oben.');
}
return window.apiValidationTestResults;
} catch (error) {
console.error('💥 Test-Suite Fehler:', error);
return { error: error.message };
}
}
// Globale Funktionen verfügbar machen
window.runAllTests = runAllTests;
window.testValidateApiResponse = testValidateApiResponse;
window.testLiveAPI = testLiveAPI;
window.testIntegration = testIntegration;
window.testPerformance = testPerformance;
// Auto-Start wenn Test-Parameter in URL
if (window.location.search.includes('run-api-tests=true')) {
document.addEventListener('DOMContentLoaded', () => {
setTimeout(runAllTests, 1000); // 1 Sekunde warten bis alles geladen ist
});
}
console.log('📝 API-Validation-Test-Suite geladen');
console.log('💡 Verwendung: runAllTests() in der Browser-Console ausführen');
console.log('💡 Oder URL-Parameter ?run-api-tests=true verwenden für Auto-Start');