import { tap, expect } from '@git.zone/tstest/tapbundle'; import { EInvoice } from '../../../ts/index.js'; import { PerformanceTracker } from '../../helpers/performance.tracker.js'; import { ValidationLevel } from '../../../ts/interfaces/common.js'; tap.test('EDGE-03: Deeply Nested XML Structures - should handle extremely nested XML', async () => { console.log('Testing deeply nested XML structures...'); // Test 1: Invoice with deeply nested item structure console.log('\nTest 1: Creating invoice with deeply nested item names'); const { result: deeplyNestedResult, metric: deeplyNestedMetric } = await PerformanceTracker.track( 'deeply-nested-items', async () => { const einvoice = new EInvoice(); // Set basic invoice data einvoice.id = 'NESTED-001'; einvoice.issueDate = new Date('2024-01-01'); einvoice.currency = 'EUR'; // Set supplier with nested address structure einvoice.from = { type: 'company', name: 'Deep Nesting Test GmbH - Company with Complex Structure and Subsidiaries', description: 'Main company > Division A > Department X > Team Alpha > Project Nested', address: { streetName: 'Very Long Street Name with Multiple Parts and Building Complex A Wing B Floor 3', houseNumber: '123A-B-C', postalCode: '12345', city: 'City Name with District > Subdistrict > Neighborhood > Block', country: 'DE' }, status: 'active', foundedDate: { year: 2020, month: 1, day: 1 }, registrationDetails: { vatId: 'DE123456789', registrationId: 'HRB 12345 / SubReg 67890 / Dept ABC', registrationName: 'Berlin Registry > Commercial Court > Division B' } }; // Set customer with nested structure einvoice.to = { type: 'company', name: 'Customer Corporation > European Division > German Branch > Berlin Office', description: 'Subsidiary of Parent > Holding > Group > Corporation > Conglomerate', address: { streetName: 'Customer Avenue Section A Subsection B Part C', houseNumber: '456-X-Y-Z', postalCode: '54321', city: 'Munich > Central District > Business Quarter > Tech Park', country: 'DE' }, status: 'active', foundedDate: { year: 2018, month: 6, day: 15 }, registrationDetails: { vatId: 'DE987654321', registrationId: 'HRB 54321 > SubID 09876', registrationName: 'Munich Registry > Division C > Subdiv 3' } }; // Create items with deeply nested descriptions in their names einvoice.items = []; const nestingLevels = 5; for (let i = 0; i < nestingLevels; i++) { let itemName = 'Product'; for (let j = 0; j <= i; j++) { itemName += ` > Level ${j + 1}`; if (j === i) { itemName += ` > Category ${String.fromCharCode(65 + j)} > Subcategory ${j + 1} > Type ${j * 10 + 1}`; } } einvoice.items.push({ position: i + 1, name: itemName + ' > Final Product Description with Technical Specifications > Version 1.0 > Revision 3', articleNumber: `NESTED-${i + 1}-${String.fromCharCode(65 + i)}-${(i + 1) * 100}`, unitType: 'EA', unitQuantity: (i + 1) * 2, unitNetPrice: 100 + (i * 50), vatPercentage: 19 }); } // Test XML generation with nested structure const xmlString = await einvoice.toXmlString('ubl'); // Test parsing back const parsedInvoice = new EInvoice(); await parsedInvoice.fromXmlString(xmlString); // Test validation const validationResult = await parsedInvoice.validate(ValidationLevel.SYNTAX); return { itemCount: einvoice.items.length, xmlSize: Buffer.byteLength(xmlString, 'utf8'), deepestItemNameLength: Math.max(...einvoice.items.map(item => item.name.length)), preservedItems: parsedInvoice.items?.length || 0, validationResult, xmlNestingDepth: (xmlString.match(/>/g) || []).length }; } ); console.log(` Created ${deeplyNestedResult.itemCount} items with nested structures`); console.log(` XML size: ${(deeplyNestedResult.xmlSize / 1024).toFixed(2)} KB`); console.log(` Deepest item name: ${deeplyNestedResult.deepestItemNameLength} chars`); console.log(` XML nesting depth: ${deeplyNestedResult.xmlNestingDepth} tags`); console.log(` Processing time: ${deeplyNestedMetric.duration}ms`); expect(deeplyNestedResult.itemCount).toEqual(5); expect(deeplyNestedResult.preservedItems).toEqual(5); expect(deeplyNestedResult.validationResult.valid).toBeTrue(); // Test 2: Invoice with deeply nested XML namespace structure console.log('\nTest 2: Testing XML with multiple namespace levels'); const { result: namespaceResult, metric: namespaceMetric } = await PerformanceTracker.track( 'namespace-nesting', async () => { // Create a complex CII XML with multiple namespaces const complexXml = ` urn:cen.eu:en16931:2017 NAMESPACE-TEST-001 380 20240101 Namespace Test Seller Test Street 1 12345 Berlin DE DE123456789 Namespace Test Buyer Market Street 2 54321 Munich DE EUR `; // Parse the complex XML const invoice = new EInvoice(); await invoice.fromXmlString(complexXml); // Count namespace declarations const namespaceCount = (complexXml.match(/xmlns:/g) || []).length; const elementCount = (complexXml.match(/<[^/][^>]*>/g) || []).length; return { parsedId: invoice.id, namespaceCount, elementCount, fromName: invoice.from?.name, toName: invoice.to?.name }; } ); console.log(` Parsed invoice ID: ${namespaceResult.parsedId}`); console.log(` Namespace declarations: ${namespaceResult.namespaceCount}`); console.log(` XML elements: ${namespaceResult.elementCount}`); console.log(` Processing time: ${namespaceMetric.duration}ms`); expect(namespaceResult.parsedId).toEqual('NAMESPACE-TEST-001'); expect(namespaceResult.namespaceCount).toBeGreaterThan(3); // Test 3: Round-trip with nested structures console.log('\nTest 3: Round-trip conversion with nested data'); const { result: roundTripResult, metric: roundTripMetric } = await PerformanceTracker.track( 'nested-round-trip', async () => { const invoice = new EInvoice(); // Create complex nested structure invoice.id = 'ROUND-TRIP-NESTED-001'; invoice.issueDate = new Date('2024-01-01'); invoice.currency = 'EUR'; invoice.from = { type: 'company', name: 'Company A > Division B > Department C', description: 'Nested company structure test', address: { streetName: 'Street > Section > Block', houseNumber: '1A-2B-3C', postalCode: '12345', city: 'City > District > Zone', country: 'DE' }, status: 'active', foundedDate: { year: 2020, month: 1, day: 1 }, registrationDetails: { vatId: 'DE123456789', registrationId: 'HRB 12345', registrationName: 'Registry > Division' } }; invoice.to = { type: 'person', name: 'John', surname: 'Doe', salutation: 'Mr' as const, sex: 'male' as const, title: 'Doctor' as const, description: 'Individual customer', address: { streetName: 'Simple Street', houseNumber: '1', postalCode: '54321', city: 'Simple City', country: 'DE' } }; // Add nested items invoice.items = [{ position: 1, name: 'Service > Category > Subcategory > Item > Variant > Option', articleNumber: 'SRV-CAT-SUB-ITM-VAR-OPT', unitType: 'HUR', unitQuantity: 8, unitNetPrice: 250, vatPercentage: 19 }]; // Convert to both formats and back const ublXml = await invoice.toXmlString('ubl'); const ciiXml = await invoice.toXmlString('cii'); const fromUbl = new EInvoice(); await fromUbl.fromXmlString(ublXml); const fromCii = new EInvoice(); await fromCii.fromXmlString(ciiXml); return { originalItemName: invoice.items[0].name, ublPreservedName: fromUbl.items?.[0]?.name, ciiPreservedName: fromCii.items?.[0]?.name, ublXmlSize: Buffer.byteLength(ublXml, 'utf8'), ciiXmlSize: Buffer.byteLength(ciiXml, 'utf8') }; } ); console.log(` Original item name: ${roundTripResult.originalItemName}`); console.log(` UBL preserved: ${roundTripResult.ublPreservedName === roundTripResult.originalItemName ? '✓' : '✗'}`); console.log(` CII preserved: ${roundTripResult.ciiPreservedName === roundTripResult.originalItemName ? '✓' : '✗'}`); console.log(` UBL XML size: ${(roundTripResult.ublXmlSize / 1024).toFixed(2)} KB`); console.log(` CII XML size: ${(roundTripResult.ciiXmlSize / 1024).toFixed(2)} KB`); console.log(` Processing time: ${roundTripMetric.duration}ms`); expect(roundTripResult.ublPreservedName).toEqual(roundTripResult.originalItemName); expect(roundTripResult.ciiPreservedName).toEqual(roundTripResult.originalItemName); console.log('\n✓ All deeply nested XML tests completed successfully'); }); tap.start();