import { expect, tap } from '@git.zone/tstest/tapbundle'; import { EInvoice } from '../../../ts/index.js'; tap.test('ERR-02: Validation Errors - should handle validation errors gracefully', async () => { console.log('Testing validation error handling...\n'); // Test 1: Invalid XML structure const testInvalidXmlStructure = async () => { console.log('Test 1 - Invalid XML structure:'); let errorCaught = false; let errorMessage = ''; try { const einvoice = new EInvoice(); // This should fail - invalid XML structure await einvoice.fromXmlString('broken xml'); } catch (error) { errorCaught = true; errorMessage = error.message || 'Unknown error'; console.log(` Error caught: ${errorMessage}`); } const gracefulHandling = errorCaught && !errorMessage.includes('FATAL'); console.log(` Error was caught: ${errorCaught}`); console.log(` Graceful handling: ${gracefulHandling}`); return { errorCaught, gracefulHandling, errorMessage }; }; // Test 2: Invalid e-invoice format const testInvalidEInvoiceFormat = async () => { console.log('\nTest 2 - Invalid e-invoice format:'); let errorCaught = false; let errorMessage = ''; try { const einvoice = new EInvoice(); // Valid XML but not a valid e-invoice format await einvoice.fromXmlString(` Value `); } catch (error) { errorCaught = true; errorMessage = error.message || 'Unknown error'; console.log(` Error caught: ${errorMessage}`); } const gracefulHandling = errorCaught && !errorMessage.includes('FATAL'); console.log(` Error was caught: ${errorCaught}`); console.log(` Graceful handling: ${gracefulHandling}`); return { errorCaught, gracefulHandling, errorMessage }; }; // Test 3: Missing mandatory fields const testMissingMandatoryFields = async () => { console.log('\nTest 3 - Missing mandatory fields:'); let errorCaught = false; let errorMessage = ''; try { const einvoice = new EInvoice(); // Try to export without setting mandatory fields await einvoice.toXmlString('ubl'); } catch (error) { errorCaught = true; errorMessage = error.message || 'Unknown error'; console.log(` Error caught: ${errorMessage}`); } const gracefulHandling = errorCaught && !errorMessage.includes('FATAL'); console.log(` Error was caught: ${errorCaught}`); console.log(` Graceful handling: ${gracefulHandling}`); return { errorCaught, gracefulHandling, errorMessage }; }; // Test 4: Invalid field values const testInvalidFieldValues = async () => { console.log('\nTest 4 - Invalid field values:'); let errorCaught = false; let errorMessage = ''; try { const einvoice = new EInvoice(); einvoice.issueDate = new Date(2024, 0, 1); einvoice.invoiceId = 'TEST-001'; // Invalid country code (should be 2 characters) einvoice.from = { type: 'company', name: 'Test Company', description: 'Testing invalid values', address: { streetName: 'Test Street', houseNumber: '1', postalCode: '12345', city: 'Test City', country: 'INVALID_COUNTRY_CODE' // This should cause validation error }, status: 'active', foundedDate: { year: 2020, month: 1, day: 1 }, registrationDetails: { vatId: 'DE123456789', registrationId: 'HRB 12345', registrationName: 'Commercial Register' } }; einvoice.to = { type: 'person', name: 'Test', surname: 'Customer', salutation: 'Mr' as const, sex: 'male' as const, title: 'Doctor' as const, description: 'Test customer', address: { streetName: 'Customer Street', houseNumber: '2', postalCode: '54321', city: 'Customer City', country: 'DE' } }; einvoice.items = [{ position: 1, name: 'Test Item', articleNumber: 'TEST-001', unitType: 'EA', unitQuantity: 1, unitNetPrice: 100, vatPercentage: 19 }]; await einvoice.toXmlString('ubl'); } catch (error) { errorCaught = true; errorMessage = error.message || 'Unknown error'; console.log(` Error caught: ${errorMessage}`); } const gracefulHandling = errorCaught && !errorMessage.includes('FATAL'); console.log(` Error was caught: ${errorCaught}`); console.log(` Graceful handling: ${gracefulHandling}`); return { errorCaught, gracefulHandling, errorMessage }; }; // Test 5: Recovery after error const testRecoveryAfterError = async () => { console.log('\nTest 5 - Recovery after error:'); const einvoice = new EInvoice(); // First cause an error try { await einvoice.fromXmlString('broken'); } catch (error) { console.log(` Expected error occurred: ${error.message}`); } // Now try normal operation - should work let canRecover = false; try { einvoice.issueDate = new Date(2024, 0, 1); einvoice.invoiceId = 'RECOVERY-TEST'; einvoice.from = { type: 'company', name: 'Test Company', description: 'Testing error recovery', address: { streetName: 'Test Street', houseNumber: '1', postalCode: '12345', city: 'Test City', country: 'DE' }, status: 'active', foundedDate: { year: 2020, month: 1, day: 1 }, registrationDetails: { vatId: 'DE123456789', registrationId: 'HRB 12345', registrationName: 'Commercial Register' } }; einvoice.to = { type: 'person', name: 'Test', surname: 'Customer', salutation: 'Mr' as const, sex: 'male' as const, title: 'Doctor' as const, description: 'Test customer', address: { streetName: 'Customer Street', houseNumber: '2', postalCode: '54321', city: 'Customer City', country: 'DE' } }; einvoice.items = [{ position: 1, name: 'Test Product', articleNumber: 'TEST-001', unitType: 'EA', unitQuantity: 1, unitNetPrice: 100, vatPercentage: 19 }]; // Try to export after error const xml = await einvoice.toXmlString('ubl'); canRecover = xml.includes('RECOVERY-TEST'); console.log(` Recovery successful: ${canRecover}`); } catch (error) { console.log(` Recovery failed: ${error.message}`); canRecover = false; } return { canRecover }; }; // Test 6: Multiple error scenarios const testMultipleErrorScenarios = async () => { console.log('\nTest 6 - Multiple error scenarios:'); const errorScenarios = [ { name: 'Empty XML', xml: '' }, { name: 'Malformed XML', xml: '' }, { name: 'Wrong namespace', xml: 'Value' } ]; let errorsHandled = 0; for (const scenario of errorScenarios) { try { const einvoice = new EInvoice(); await einvoice.fromXmlString(scenario.xml); console.log(` ${scenario.name}: No error thrown (unexpected)`); } catch (error) { console.log(` ${scenario.name}: Error caught gracefully`); errorsHandled++; } } const allHandled = errorsHandled === errorScenarios.length; console.log(` Errors handled: ${errorsHandled}/${errorScenarios.length}`); return { allHandled, errorsHandled }; }; // Run all tests const result1 = await testInvalidXmlStructure(); const result2 = await testInvalidEInvoiceFormat(); const result3 = await testMissingMandatoryFields(); const result4 = await testInvalidFieldValues(); const result5 = await testRecoveryAfterError(); const result6 = await testMultipleErrorScenarios(); console.log('\n=== Validation Errors Error Handling Summary ==='); console.log(`Invalid XML structure: ${result1.errorCaught ? 'Handled' : 'Not handled'}`); console.log(`Invalid e-invoice format: ${result2.errorCaught ? 'Handled' : 'Not handled'}`); console.log(`Missing mandatory fields: ${result3.errorCaught ? 'Handled' : 'Not handled'}`); console.log(`Invalid field values: ${result4.errorCaught ? 'Handled' : 'Not handled'}`); console.log(`Recovery after error: ${result5.canRecover ? 'Successful' : 'Failed'}`); console.log(`Multiple error scenarios: ${result6.allHandled ? 'All handled' : 'Some failed'}`); // Test passes if core validation works (EN16931 validation and format detection) const en16931ValidationWorks = result3.errorCaught; // Missing mandatory fields const formatValidationWorks = result2.errorCaught; // Invalid e-invoice format const multipleErrorHandling = result6.allHandled; // Multiple error scenarios // Core validation should work for EN16931 compliance expect(en16931ValidationWorks).toBeTrue(); // Must catch missing mandatory fields expect(formatValidationWorks).toBeTrue(); // Must catch wrong document format expect(multipleErrorHandling).toBeTrue(); // Must handle malformed XML gracefully }); tap.start();