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-02: Gigabyte-Size Invoices - should handle extremely large invoice files', async () => { console.log('Testing large invoice handling...'); // Test 1: Invoice with many line items console.log('\nTest 1: Creating invoice with many line items'); const { result: largeInvoiceResult, metric: largeInvoiceMetric } = await PerformanceTracker.track( 'large-invoice-creation', async () => { const einvoice = new EInvoice(); // Set basic invoice data einvoice.id = 'LARGE-INVOICE-001'; einvoice.issueDate = new Date('2024-01-01'); einvoice.currency = 'EUR'; // Set supplier einvoice.from = { type: 'company', name: 'Test Supplier GmbH', description: 'Large invoice test supplier', address: { streetName: 'Test Street', houseNumber: '1', postalCode: '12345', city: 'Berlin', country: 'DE' }, status: 'active', foundedDate: { year: 2020, month: 1, day: 1 }, registrationDetails: { vatId: 'DE123456789', registrationId: 'HRB 12345', registrationName: 'Berlin Registry' } }; // Set customer einvoice.to = { type: 'company', name: 'Test Customer AG', description: 'Large invoice test customer', address: { streetName: 'Market Street', houseNumber: '42', postalCode: '54321', city: 'Munich', country: 'DE' }, status: 'active', foundedDate: { year: 2018, month: 6, day: 15 }, registrationDetails: { vatId: 'DE987654321', registrationId: 'HRB 54321', registrationName: 'Munich Registry' } }; // Create many line items const itemCount = 500; // Reasonable number for testing einvoice.items = []; for (let i = 0; i < itemCount; i++) { einvoice.items.push({ position: i + 1, name: `Product ${i + 1} - Detailed description including technical specifications, dimensions, weight, color variants, and other relevant information that makes this name quite lengthy to test memory handling`, articleNumber: `PROD-${i + 1}`, unitType: 'EA', unitQuantity: Math.floor(Math.random() * 10) + 1, unitNetPrice: 99.99, vatPercentage: 19 }); } // Test XML generation const xmlGenStart = Date.now(); const xmlString = await einvoice.toXmlString('ubl'); const xmlGenTime = Date.now() - xmlGenStart; // Test parsing back const parseStart = Date.now(); const parsedInvoice = new EInvoice(); await parsedInvoice.fromXmlString(xmlString); const parseTime = Date.now() - parseStart; // Test validation const validationStart = Date.now(); const validationResult = await parsedInvoice.validate(ValidationLevel.SYNTAX); const validationTime = Date.now() - validationStart; return { itemCount, xmlSize: Buffer.byteLength(xmlString, 'utf8'), xmlGenTime, parseTime, validationTime, validationResult, memoryUsed: process.memoryUsage().heapUsed }; } ); console.log(` Created invoice with ${largeInvoiceResult.itemCount} items`); console.log(` XML size: ${(largeInvoiceResult.xmlSize / 1024).toFixed(2)} KB`); console.log(` XML generation time: ${largeInvoiceResult.xmlGenTime}ms`); console.log(` Parse time: ${largeInvoiceResult.parseTime}ms`); console.log(` Validation time: ${largeInvoiceResult.validationTime}ms`); console.log(` Total processing time: ${largeInvoiceMetric.duration}ms`); console.log(` Memory used: ${(largeInvoiceResult.memoryUsed / 1024 / 1024).toFixed(2)} MB`); expect(largeInvoiceResult.itemCount).toEqual(500); expect(largeInvoiceResult.xmlSize).toBeGreaterThan(50000); // At least 50KB expect(largeInvoiceResult.validationResult.valid).toBeTrue(); // Test 2: Invoice with large text content console.log('\nTest 2: Creating invoice with very large descriptions'); const { result: largeTextResult, metric: largeTextMetric } = await PerformanceTracker.track( 'large-text-content', async () => { const einvoice = new EInvoice(); // Set basic invoice data einvoice.id = 'LARGE-TEXT-001'; einvoice.issueDate = new Date('2024-01-01'); einvoice.currency = 'EUR'; // Create a very large description const veryLongDescription = 'This is a test description. '.repeat(1000); // ~30KB per item einvoice.from = { type: 'company', name: 'Test Supplier with Very Long Company Name That Tests Field Length Limits GmbH & Co. KG', description: veryLongDescription.substring(0, 5000), // Limit to reasonable size address: { streetName: 'Very Long Street Name That Goes On And On Testing Field Limits', houseNumber: '999999', postalCode: '99999', city: 'City With Extremely Long Name Testing Municipality Name Length Limits', country: 'DE' }, status: 'active', foundedDate: { year: 2020, month: 1, day: 1 }, registrationDetails: { vatId: 'DE123456789', registrationId: 'HRB 12345', registrationName: 'Berlin Registry' } }; einvoice.to = { type: 'company', name: 'Customer Inc', description: 'Normal customer', address: { streetName: 'Main St', houseNumber: '1', postalCode: '12345', city: 'Berlin', country: 'DE' }, status: 'active', foundedDate: { year: 2019, month: 3, day: 10 }, registrationDetails: { vatId: 'DE987654321', registrationId: 'HRB 98765', registrationName: 'Berlin Registry' } }; // Add items with large descriptions einvoice.items = []; for (let i = 0; i < 10; i++) { einvoice.items.push({ position: i + 1, name: `Product with extremely long name that tests the limits of product name fields in various e-invoice formats ${i} - ${veryLongDescription.substring(0, 1000)}`, articleNumber: `LONG-${i + 1}`, unitType: 'EA', unitQuantity: 1, unitNetPrice: 100, vatPercentage: 19 }); } // Test XML generation const xmlString = await einvoice.toXmlString('ubl'); // Test parsing const parsedInvoice = new EInvoice(); await parsedInvoice.fromXmlString(xmlString); return { xmlSize: Buffer.byteLength(xmlString, 'utf8'), itemCount: parsedInvoice.items?.length || 0, fromNameLength: parsedInvoice.from?.name?.length || 0, itemNameLength: parsedInvoice.items?.[0]?.name?.length || 0 }; } ); console.log(` XML size with large text: ${(largeTextResult.xmlSize / 1024).toFixed(2)} KB`); console.log(` Processing time: ${largeTextMetric.duration}ms`); console.log(` Preserved ${largeTextResult.itemCount} items`); console.log(` Company name length: ${largeTextResult.fromNameLength} chars`); console.log(` Item name length: ${largeTextResult.itemNameLength} chars`); expect(largeTextResult.xmlSize).toBeGreaterThan(30000); // At least 30KB expect(largeTextResult.itemCount).toEqual(10); // Test 3: Memory efficiency test console.log('\nTest 3: Memory efficiency with multiple large invoices'); const memoryTestResult = await PerformanceTracker.track( 'memory-efficiency', async () => { const startMemory = process.memoryUsage().heapUsed; const invoices = []; // Create multiple invoices for (let i = 0; i < 10; i++) { const invoice = new EInvoice(); invoice.id = `MEMORY-TEST-${i}`; invoice.issueDate = new Date(); invoice.currency = 'EUR'; invoice.from = { type: 'company', name: `Supplier ${i}`, description: 'Test supplier', address: { streetName: 'Test St', houseNumber: '1', postalCode: '12345', city: 'Berlin', country: 'DE' }, status: 'active', foundedDate: { year: 2020, month: 1, day: 1 }, registrationDetails: { vatId: `DE12345678${i}`, registrationId: `HRB 1234${i}`, registrationName: 'Berlin Registry' } }; invoice.to = { type: 'company', name: `Customer ${i}`, description: 'Test customer', address: { streetName: 'Main St', houseNumber: '2', postalCode: '54321', city: 'Munich', country: 'DE' }, status: 'active', foundedDate: { year: 2019, month: 6, day: 1 }, registrationDetails: { vatId: `DE98765432${i}`, registrationId: `HRB 5432${i}`, registrationName: 'Munich Registry' } }; // Add 100 items each invoice.items = []; for (let j = 0; j < 100; j++) { invoice.items.push({ position: j + 1, name: `Product ${j} - Description for invoice ${i} item ${j}`, articleNumber: `MEM-${i}-${j}`, unitType: 'EA', unitQuantity: 2, unitNetPrice: 50, vatPercentage: 19 }); } invoices.push(invoice); } // Convert all to XML const xmlStrings = await Promise.all( invoices.map(inv => inv.toXmlString('ubl')) ); const endMemory = process.memoryUsage().heapUsed; const totalSize = xmlStrings.reduce((sum, xml) => sum + Buffer.byteLength(xml, 'utf8'), 0); return { invoiceCount: invoices.length, totalXmlSize: totalSize, memoryUsed: endMemory - startMemory, avgInvoiceSize: totalSize / invoices.length }; } ); console.log(` Created ${memoryTestResult.result.invoiceCount} invoices`); console.log(` Total XML size: ${(memoryTestResult.result.totalXmlSize / 1024 / 1024).toFixed(2)} MB`); console.log(` Memory used: ${(memoryTestResult.result.memoryUsed / 1024 / 1024).toFixed(2)} MB`); console.log(` Average invoice size: ${(memoryTestResult.result.avgInvoiceSize / 1024).toFixed(2)} KB`); console.log(` Processing time: ${memoryTestResult.metric.duration}ms`); expect(memoryTestResult.result.invoiceCount).toEqual(10); expect(memoryTestResult.result.totalXmlSize).toBeGreaterThan(500000); // At least 500KB total console.log('\n✓ All large invoice tests completed successfully'); }); tap.start();