import { expect, tap } from '@git.zone/tstest/tapbundle'; import * as plugins from '../plugins.js'; import { EInvoice } from '../../../ts/index.js'; import { CorpusLoader } from '../corpus.loader.js'; import { PerformanceTracker } from '../performance.tracker.js'; tap.test('CONV-04: Field Mapping - should correctly map fields between formats', async (t) => { // CONV-04: Verify accurate field mapping during format conversion // This test ensures data is correctly transferred between different formats const performanceTracker = new PerformanceTracker('CONV-04: Field Mapping'); const corpusLoader = new CorpusLoader(); t.test('Basic field mapping UBL to CII', async () => { const startTime = performance.now(); // UBL invoice with comprehensive fields const ublInvoice = ` 2.1 urn:cen.eu:en16931:2017 urn:fdc:peppol.eu:2017:poacc:billing:01:1.0 FIELD-MAP-001 2025-01-25 2025-02-25 380 Field mapping test invoice 2025-01-25 EUR EUR PO-2025-001 ORDER-123 PREV-INV-001 2025-01-01 5790000435975 DK12345678 Supplier Company A/S Main Street 1 Copenhagen 1234 Capital Region DK DK12345678 VAT Supplier Company A/S DK12345678 John Doe +45 12345678 john@supplier.dk 5790000435982 DK87654321 Customer Company B/V Market Street 100 Aarhus 8000 DK DK87654321 VAT Jane Smith jane@customer.dk 30 PAY-2025-001 DK5000400440116243 Supplier Bank Account DANBDK22 Danske Bank `; const einvoice = new EInvoice(); await einvoice.loadFromString(ublInvoice); // Check if key fields are preserved const invoiceData = einvoice.getInvoiceData(); if (invoiceData) { // Basic fields expect(invoiceData.invoiceNumber).toBe('FIELD-MAP-001'); expect(invoiceData.issueDate).toContain('2025-01-25'); expect(invoiceData.dueDate).toContain('2025-02-25'); expect(invoiceData.currency).toBe('EUR'); // Supplier fields if (invoiceData.supplier) { expect(invoiceData.supplier.name).toContain('Supplier Company'); expect(invoiceData.supplier.vatNumber).toContain('DK12345678'); expect(invoiceData.supplier.address?.street).toContain('Main Street'); expect(invoiceData.supplier.address?.city).toBe('Copenhagen'); expect(invoiceData.supplier.address?.postalCode).toBe('1234'); expect(invoiceData.supplier.address?.country).toBe('DK'); } // Customer fields if (invoiceData.customer) { expect(invoiceData.customer.name).toContain('Customer Company'); expect(invoiceData.customer.vatNumber).toContain('DK87654321'); expect(invoiceData.customer.address?.city).toBe('Aarhus'); } console.log('Basic field mapping verified'); } else { console.log('Field mapping through invoice data not available'); } const elapsed = performance.now() - startTime; performanceTracker.addMeasurement('basic-mapping', elapsed); }); t.test('Complex nested field mapping', async () => { const startTime = performance.now(); // CII invoice with nested structures const ciiInvoice = ` urn:cen.eu:en16931:2017 NESTED-MAP-001 380 20250125 Complex nested structure test AAI Second note for testing REG 1 Line item note 1234567890123 PROD-001 CUST-PROD-001 Complex Product Product with multiple identifiers and attributes Color Blue Size Large PO-LINE-001 120.00 false 10.00 12.00 Volume discount 108.00 10 VAT S 19.00 1080.00 `; const einvoice = new EInvoice(); await einvoice.loadFromString(ciiInvoice); const xmlString = einvoice.getXmlString(); // Verify nested structures are preserved expect(xmlString).toContain('NESTED-MAP-001'); expect(xmlString).toContain('Complex nested structure test'); expect(xmlString).toContain('PROD-001'); expect(xmlString).toContain('1234567890123'); expect(xmlString).toContain('Color'); expect(xmlString).toContain('Blue'); expect(xmlString).toContain('Volume discount'); console.log('Complex nested field mapping tested'); const elapsed = performance.now() - startTime; performanceTracker.addMeasurement('nested-mapping', elapsed); }); t.test('Field mapping with missing optional fields', async () => { const startTime = performance.now(); // Minimal UBL invoice const minimalUbl = ` MINIMAL-001 2025-01-25 380 EUR Minimal Supplier Minimal Customer 100.00 `; const einvoice = new EInvoice(); await einvoice.loadFromString(minimalUbl); const invoiceData = einvoice.getInvoiceData(); // Verify mandatory fields are mapped expect(invoiceData?.invoiceNumber).toBe('MINIMAL-001'); expect(invoiceData?.issueDate).toContain('2025-01-25'); expect(invoiceData?.currency).toBe('EUR'); expect(invoiceData?.totalAmount).toBe(100.00); // Optional fields should be undefined or have defaults expect(invoiceData?.dueDate).toBeUndefined(); expect(invoiceData?.notes).toBeUndefined(); expect(invoiceData?.supplier?.vatNumber).toBeUndefined(); console.log('Minimal field mapping verified'); const elapsed = performance.now() - startTime; performanceTracker.addMeasurement('minimal-mapping', elapsed); }); t.test('Field type conversion mapping', async () => { const startTime = performance.now(); // Invoice with various data types const typeTestInvoice = ` TYPE-TEST-001 2025-01-25 14:30:00 380 EUR 5 2025-01-25 2025-01-01 2025-01-31 ORDER-123 SO-456 Type Test Supplier Type Test Customer false 0.05 50.00 1000.00 190.00 1000.00 190.00 S 19.00 VATEX-EU-O `; const einvoice = new EInvoice(); await einvoice.loadFromString(typeTestInvoice); const xmlString = einvoice.getXmlString(); // Verify different data types are preserved expect(xmlString).toContain('TYPE-TEST-001'); // String expect(xmlString).toContain('2025-01-25'); // Date expect(xmlString).toContain('14:30:00'); // Time expect(xmlString).toContain('5'); // Integer expect(xmlString).toContain('19.00'); // Decimal expect(xmlString).toContain('false'); // Boolean expect(xmlString).toContain('0.05'); // Float console.log('Field type conversion mapping verified'); const elapsed = performance.now() - startTime; performanceTracker.addMeasurement('type-conversion', elapsed); }); t.test('Array field mapping', async () => { const startTime = performance.now(); // Invoice with multiple repeated elements const arrayInvoice = ` ARRAY-TEST-001 2025-01-25 380 First note Second note Third note with special chars: €£¥ EUR DOC-001 Contract DOC-002 Purchase Order DOC-003 Delivery Note 1234567890123 DK12345678 123456789 Array Test Supplier Array Test Customer 30 PAY-001 31 PAY-002 `; const einvoice = new EInvoice(); await einvoice.loadFromString(arrayInvoice); const xmlString = einvoice.getXmlString(); // Verify arrays are preserved expect(xmlString).toContain('First note'); expect(xmlString).toContain('Second note'); expect(xmlString).toContain('Third note with special chars: €£¥'); expect(xmlString).toContain('DOC-001'); expect(xmlString).toContain('DOC-002'); expect(xmlString).toContain('DOC-003'); expect(xmlString).toContain('1234567890123'); expect(xmlString).toContain('DK12345678'); expect(xmlString).toContain('123456789'); console.log('Array field mapping verified'); const elapsed = performance.now() - startTime; performanceTracker.addMeasurement('array-mapping', elapsed); }); t.test('Cross-reference field mapping', async () => { const startTime = performance.now(); // Invoice with cross-references between sections const crossRefInvoice = ` XREF-TEST-001 2025-01-25 380 EUR PROJ-2025-001 Cross Reference Supplier Cross Reference Customer 2025-01-20 5790000435999 Delivery Street Copenhagen 1 Delivered to GLN: 5790000435999 10 1000.00 ORDER-LINE-001 Product for PROJ-2025-001 100.00 `; const einvoice = new EInvoice(); await einvoice.loadFromString(crossRefInvoice); const xmlString = einvoice.getXmlString(); // Verify cross-references are maintained expect(xmlString).toContain('PROJ-2025-001'); expect(xmlString).toContain('5790000435999'); expect(xmlString).toContain('Delivered to GLN: 5790000435999'); expect(xmlString).toContain('Product for PROJ-2025-001'); expect(xmlString).toContain('ORDER-LINE-001'); console.log('Cross-reference field mapping verified'); const elapsed = performance.now() - startTime; performanceTracker.addMeasurement('cross-reference', elapsed); }); t.test('Corpus field mapping validation', async () => { const startTime = performance.now(); let processedCount = 0; let mappingIssues = 0; const criticalFields = ['ID', 'IssueDate', 'DocumentCurrencyCode', 'AccountingSupplierParty', 'AccountingCustomerParty']; const files = await corpusLoader.getAllFiles(); const xmlFiles = files.filter(f => f.endsWith('.xml') && !f.includes('.pdf')); // Test field mapping on corpus files const sampleSize = Math.min(30, xmlFiles.length); const sample = xmlFiles.slice(0, sampleSize); for (const file of sample) { try { const content = await corpusLoader.readFile(file); const einvoice = new EInvoice(); if (typeof content === 'string') { await einvoice.loadFromString(content); } else { await einvoice.loadFromBuffer(content); } const xmlString = einvoice.getXmlString(); const invoiceData = einvoice.getInvoiceData(); // Check critical field mapping let hasIssue = false; if (invoiceData) { if (!invoiceData.invoiceNumber && xmlString.includes('')) { console.log(`${file}: Invoice number not mapped`); hasIssue = true; } if (!invoiceData.issueDate && xmlString.includes('')) { console.log(`${file}: Issue date not mapped`); hasIssue = true; } if (!invoiceData.currency && xmlString.includes('')) { console.log(`${file}: Currency not mapped`); hasIssue = true; } } if (hasIssue) mappingIssues++; processedCount++; } catch (error) { console.log(`Field mapping error in ${file}:`, error.message); } } console.log(`Corpus field mapping validation (${processedCount} files):`); console.log(`- Files with potential mapping issues: ${mappingIssues}`); const elapsed = performance.now() - startTime; performanceTracker.addMeasurement('corpus-validation', elapsed); }); // Print performance summary performanceTracker.printSummary(); // Performance assertions const avgTime = performanceTracker.getAverageTime(); expect(avgTime).toBeLessThan(300); // Field mapping should be reasonably fast }); tap.start();