import { expect, tap } from '@git.zone/tstest/tapbundle'; import * as einvoice from '../../../ts/index.js'; import * as plugins from '../../plugins.js'; tap.test('PARSE-10: CDATA Section Handling in e-invoices', async () => { console.log('Testing CDATA section handling in e-invoices...\n'); // Test basic CDATA sections in invoice fields const cdataTests = [ { name: 'Simple CDATA content in notes', xml: ` CDATA-001 & " ']]> `, expectedNote: "This is plain text content with special chars: < > & \" '", description: 'Basic CDATA section preserves special characters' }, { name: 'CDATA with XML-like content', xml: ` CDATA-002 Invoice contains HTML markup]]> `, expectedNote: 'Invoice contains HTML markup', description: 'XML/HTML markup preserved as text in CDATA' }, { name: 'CDATA with line breaks and formatting', xml: ` CDATA-003 `, expectedSupplierName: 'Company & Co.\nSpecial Division\n"International Sales"', description: 'CDATA preserves line breaks and special chars in company names' }, { name: 'Empty CDATA section', xml: ` CDATA-004 `, expectedNote: '', description: 'Empty CDATA section is valid' }, { name: 'CDATA with code snippets', xml: ` CDATA-005 5) { discount = 0.1; }]]> `, expectedNote: 'if (price < 100 && quantity > 5) { discount = 0.1; }', description: 'Code snippets with operators preserved' } ]; for (const test of cdataTests) { console.log(`\n${test.name}:`); console.log(` Description: ${test.description}`); try { const invoice = new einvoice.EInvoice(); await invoice.fromXmlString(test.xml); console.log(' ✓ CDATA parsed successfully'); console.log(` Invoice ID: ${invoice.id}`); if (test.expectedNote !== undefined) { const actualNote = invoice.notes?.[0] || ''; console.log(` Expected note: "${test.expectedNote}"`); console.log(` Actual note: "${actualNote}"`); expect(actualNote).toEqual(test.expectedNote); } if (test.expectedSupplierName !== undefined) { const actualName = invoice.from?.name || ''; console.log(` Expected supplier: "${test.expectedSupplierName}"`); console.log(` Actual supplier: "${actualName}"`); expect(actualName).toEqual(test.expectedSupplierName); } } catch (error) { console.log(` ✗ Error: ${error.message}`); } } }); tap.test('PARSE-10: CDATA edge cases and security', async () => { console.log('\nTesting CDATA edge cases and security aspects...\n'); const edgeCases = [ { name: 'CDATA-like content (not actual CDATA)', xml: ` EDGE-001 Text with <![CDATA[ fake CDATA ]]> markers `, expectedNote: 'Text with markers', description: 'Escaped CDATA markers are just text' }, { name: 'Multiple CDATA sections', xml: ` EDGE-002 and `, expectedNote: 'Part 1 and Part 2', description: 'Multiple CDATA sections in one element' }, { name: 'CDATA with Unicode characters', xml: ` EDGE-003 `, expectedNote: 'Unicode: € £ ¥ © ® ™ 中文 العربية', description: 'Unicode characters in CDATA' } ]; for (const test of edgeCases) { console.log(`${test.name}:`); console.log(` Description: ${test.description}`); try { const invoice = new einvoice.EInvoice(); await invoice.fromXmlString(test.xml); const actualNote = invoice.notes?.[0] || ''; console.log(` Expected: "${test.expectedNote}"`); console.log(` Actual: "${actualNote}"`); if (test.expectedNote) { expect(actualNote).toEqual(test.expectedNote); console.log(' ✓ CDATA edge case handled correctly'); } } catch (error) { console.log(` ℹ Result: ${error.message}`); } } }); tap.test('PARSE-10: CDATA in real invoice scenarios', async () => { console.log('\nTesting CDATA usage in real invoice scenarios...\n'); // Test CDATA in various invoice contexts const realScenarios = [ { name: 'Legal disclaimer with special formatting', xml: ` REAL-001 `, description: 'Legal terms with special characters and formatting' }, { name: 'Product description with technical specs', xml: ` REAL-002 1 Technical Component `, description: 'Technical specifications with symbols' }, { name: 'Address with special formatting', xml: ` REAL-003 `, description: 'Company name and address with special characters' } ]; for (const scenario of realScenarios) { console.log(`${scenario.name}:`); console.log(` Use case: ${scenario.description}`); try { const invoice = new einvoice.EInvoice(); await invoice.fromXmlString(scenario.xml); console.log(` ✓ Invoice parsed: ID ${invoice.id}`); if (invoice.notes?.length > 0) { console.log(` Notes found: ${invoice.notes.length}`); } if (invoice.items?.length > 0) { console.log(` Line items: ${invoice.items.length}`); } if (invoice.from?.name) { console.log(` Supplier: ${invoice.from.name}`); } } catch (error) { console.log(` ✗ Error: ${error.message}`); } } }); tap.test('PARSE-10: CDATA performance with large content', async () => { console.log('\nTesting CDATA performance with large content...\n'); // Generate invoices with varying CDATA content sizes const sizes = [ { name: 'Small', chars: 100 }, { name: 'Medium', chars: 1000 }, { name: 'Large', chars: 10000 } ]; for (const size of sizes) { // Generate content with special characters that would need escaping const content = Array(size.chars / 10).fill('Text with <>&" chars ').join(''); const xml = ` PERF-${size.name} `; const startTime = Date.now(); try { const invoice = new einvoice.EInvoice(); await invoice.fromXmlString(xml); const parseTime = Date.now() - startTime; console.log(`${size.name} CDATA (${size.chars} chars):`); console.log(` Parse time: ${parseTime}ms`); console.log(` Note length: ${invoice.notes?.[0]?.length || 0} chars`); console.log(` ✓ Successfully parsed`); } catch (error) { console.log(` ✗ Error: ${error.message}`); } } }); // Run the tests tap.start();