import { expect, tap } from '@git.zone/tstest/tapbundle'; import { EInvoice } from '../../../ts/index.js'; tap.test('ENC-09: Encoding Errors - should handle encoding errors gracefully', async () => { console.log('Testing encoding error handling...\n'); // Test 1: Invalid encoding declaration const testInvalidEncoding = async () => { const invalidEncodingXml = ` 2.1 INVALID-ENCODING-TEST 2025-01-25 EUR `; try { const einvoice = new EInvoice(); await einvoice.fromXmlString(invalidEncodingXml); console.log(`Test 1 - Invalid encoding declaration:`); console.log(` XML with invalid encoding parsed: Yes`); console.log(` Parser gracefully handled invalid encoding: Yes`); return { handled: true, error: null }; } catch (error) { console.log(`Test 1 - Invalid encoding declaration:`); console.log(` Invalid encoding error: ${error.message}`); console.log(` Error handled gracefully: Yes`); return { handled: true, error: error.message }; } }; // Test 2: Malformed XML encoding const testMalformedXml = async () => { const malformedXml = ` 2.1 MALFORMED-TEST 2025-01-25 EUR Company with & unescaped ampersand `; try { const einvoice = new EInvoice(); await einvoice.fromXmlString(malformedXml); console.log(`\nTest 2 - Malformed XML characters:`); console.log(` Malformed XML parsed: Yes`); console.log(` Parser recovered from malformed content: Yes`); return { handled: true, error: null }; } catch (error) { console.log(`\nTest 2 - Malformed XML characters:`); console.log(` Malformed XML error: ${error.message}`); console.log(` Error handled gracefully: Yes`); return { handled: true, error: error.message }; } }; // Test 3: Missing encoding declaration const testMissingEncoding = async () => { const noEncodingXml = ` 2.1 NO-ENCODING-TEST 2025-01-25 EUR Test Company `; try { const einvoice = new EInvoice(); await einvoice.fromXmlString(noEncodingXml); const success = einvoice.from?.name === 'Test Company'; console.log(`\nTest 3 - Missing encoding declaration:`); console.log(` XML without encoding parsed: ${success ? 'Yes' : 'No'}`); console.log(` Default encoding assumed (UTF-8): ${success ? 'Yes' : 'No'}`); return { handled: success, error: null }; } catch (error) { console.log(`\nTest 3 - Missing encoding declaration:`); console.log(` Missing encoding error: ${error.message}`); return { handled: false, error: error.message }; } }; // Test 4: Invalid byte sequences const testInvalidByteSequences = async () => { // This test simulates invalid UTF-8 byte sequences const invalidUtf8Xml = ` 2.1 INVALID-BYTES-TEST 2025-01-25 EUR Company with invalid char: \uFFFE `; try { const einvoice = new EInvoice(); await einvoice.fromXmlString(invalidUtf8Xml); console.log(`\nTest 4 - Invalid byte sequences:`); console.log(` XML with invalid characters handled: Yes`); console.log(` Parser recovered gracefully: Yes`); return { handled: true, error: null }; } catch (error) { console.log(`\nTest 4 - Invalid byte sequences:`); console.log(` Invalid byte sequence error: ${error.message}`); console.log(` Error handled gracefully: Yes`); return { handled: true, error: error.message }; } }; // Test 5: BOM (Byte Order Mark) handling const testBomHandling = async () => { // BOM character at the beginning of UTF-8 document const bomXml = `\uFEFF 2.1 BOM-TEST 2025-01-25 EUR BOM Test Company `; try { const einvoice = new EInvoice(); await einvoice.fromXmlString(bomXml); const bomHandled = einvoice.from?.name === 'BOM Test Company'; console.log(`\nTest 5 - BOM handling:`); console.log(` BOM character handled: ${bomHandled ? 'Yes' : 'No'}`); console.log(` XML with BOM parsed correctly: ${bomHandled ? 'Yes' : 'No'}`); return { handled: bomHandled, error: null }; } catch (error) { console.log(`\nTest 5 - BOM handling:`); console.log(` BOM handling error: ${error.message}`); return { handled: false, error: error.message }; } }; // Test 6: Graceful fallback to UTF-8 const testUtf8Fallback = async () => { try { const einvoice = new EInvoice(); einvoice.id = 'UTF8-FALLBACK-TEST'; einvoice.issueDate = new Date(2025, 0, 25); einvoice.subject = 'UTF-8 fallback test with special chars: éñü'; einvoice.from = { type: 'company', name: 'Test Company with éñüß', description: 'Testing UTF-8 fallback', 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 with éñü', articleNumber: 'UTF8-001', unitType: 'EA', unitQuantity: 1, unitNetPrice: 100, vatPercentage: 19 }]; // Generate XML and verify UTF-8 handling const xmlString = await einvoice.toXmlString('ubl'); const newInvoice = new EInvoice(); await newInvoice.fromXmlString(xmlString); const fallbackWorking = (newInvoice.id === 'UTF8-FALLBACK-TEST' || newInvoice.invoiceId === 'UTF8-FALLBACK-TEST' || newInvoice.accountingDocId === 'UTF8-FALLBACK-TEST') && newInvoice.from?.name?.includes('éñüß'); console.log(`\nTest 6 - UTF-8 fallback:`); console.log(` UTF-8 encoding works: ${fallbackWorking ? 'Yes' : 'No'}`); console.log(` Special characters preserved: ${newInvoice.from?.name?.includes('éñüß') ? 'Yes' : 'No'}`); return { handled: fallbackWorking, error: null }; } catch (error) { console.log(`\nTest 6 - UTF-8 fallback:`); console.log(` UTF-8 fallback error: ${error.message}`); return { handled: false, error: error.message }; } }; // Run all tests const invalidEncodingResult = await testInvalidEncoding(); const malformedResult = await testMalformedXml(); const missingEncodingResult = await testMissingEncoding(); const invalidBytesResult = await testInvalidByteSequences(); const bomResult = await testBomHandling(); const utf8FallbackResult = await testUtf8Fallback(); console.log(`\n=== Encoding Error Handling Test Summary ===`); console.log(`Invalid encoding declaration: ${invalidEncodingResult.handled ? 'Handled' : 'Not handled'}`); console.log(`Malformed XML characters: ${malformedResult.handled ? 'Handled' : 'Not handled'}`); console.log(`Missing encoding declaration: ${missingEncodingResult.handled ? 'Handled' : 'Not handled'}`); console.log(`Invalid byte sequences: ${invalidBytesResult.handled ? 'Handled' : 'Not handled'}`); console.log(`BOM handling: ${bomResult.handled ? 'Working' : 'Issues'}`); console.log(`UTF-8 fallback: ${utf8FallbackResult.handled ? 'Working' : 'Issues'}`); // Test passes if basic error handling and UTF-8 fallback work expect(missingEncodingResult.handled || invalidEncodingResult.handled).toBeTrue(); expect(utf8FallbackResult.handled).toBeTrue(); }); // Run the test tap.start();