import { expect, tap } from '@git.zone/tstest/tapbundle'; import { promises as fs } from 'fs'; import * as path from 'path'; import { CorpusLoader } from '../../helpers/corpus.loader.js'; import { PerformanceTracker } from '../../helpers/performance.tracker.js'; tap.test('FD-02: CII Format Detection - should correctly identify CII-based invoices', async () => { // Get CII test files from corpus const ciiFiles = await CorpusLoader.getFiles('CII_XMLRECHNUNG'); const en16931CiiFiles = await CorpusLoader.getFiles('EN16931_CII'); const allCiiFiles = [...ciiFiles, ...en16931CiiFiles]; console.log(`Testing ${allCiiFiles.length} CII invoice files`); let successCount = 0; let failureCount = 0; const failures: { file: string; error: string }[] = []; // Import the format detector const { FormatDetector } = await import('../../../ts/formats/utils/format.detector.js'); for (const filePath of allCiiFiles) { try { // Read the file const xmlContent = await fs.readFile(filePath, 'utf-8'); // Track performance of format detection const { result: format } = await PerformanceTracker.track( 'cii-format-detection', async () => { return FormatDetector.detectFormat(xmlContent); }, { file: path.basename(filePath) } ); // Verify it's detected as CII or CII-based format (Factur-X/ZUGFeRD are profiles of CII) // Also accept XRechnung for files that might be dual-format if (format === 'cii' || format === 'facturx' || format === 'zugferd' || format === 'xrechnung' || format === 'CII' || format === 'FACTURX' || format === 'ZUGFERD' || format === 'XRECHNUNG' || format.toString().toLowerCase() === 'cii' || format.toString().toLowerCase() === 'facturx' || format.toString().toLowerCase() === 'zugferd' || format.toString().toLowerCase() === 'xrechnung') { successCount++; } else { failureCount++; failures.push({ file: path.basename(filePath), error: `Detected as ${format} instead of CII-based format` }); } } catch (error) { failureCount++; failures.push({ file: path.basename(filePath), error: error.message }); } } // Report results console.log(`\nCII Format Detection Results:`); console.log(`✓ Success: ${successCount}/${allCiiFiles.length} (${(successCount/allCiiFiles.length*100).toFixed(1)}%)`); console.log(`✗ Failed: ${failureCount}/${allCiiFiles.length} (${(failureCount/allCiiFiles.length*100).toFixed(1)}%)`); if (failures.length > 0) { console.log(`\nFailures:`); failures.slice(0, 10).forEach(f => console.log(` - ${f.file}: ${f.error}`)); if (failures.length > 10) { console.log(` ... and ${failures.length - 10} more`); } } // Performance summary const perfSummary = await PerformanceTracker.getSummary('cii-format-detection'); if (perfSummary) { console.log(`\nPerformance Summary:`); console.log(` Average: ${perfSummary.average.toFixed(2)}ms`); console.log(` Min: ${perfSummary.min.toFixed(2)}ms`); console.log(` Max: ${perfSummary.max.toFixed(2)}ms`); console.log(` P95: ${perfSummary.p95.toFixed(2)}ms`); } // Expect high success rate (allow some failures for edge cases) expect(successCount / allCiiFiles.length).toBeGreaterThan(0.8); }); tap.test('FD-02: CII Namespace Detection - should detect CII by namespace', async () => { const ciiNamespaces = [ 'urn:un:unece:uncefact:data:standard:CrossIndustryInvoice:100', 'urn:un:unece:uncefact:data:standard:ReusableAggregateBusinessInformationEntity:100' ]; const { FormatDetector } = await import('../../../ts/formats/utils/format.detector.js'); for (const namespace of ciiNamespaces) { const testXml = ` `; const { result: format } = await PerformanceTracker.track( 'cii-namespace-detection', async () => FormatDetector.detectFormat(testXml) ); console.log(`Namespace ${namespace} detected as: ${format}`); // Accept CII or CII-based formats (Factur-X/ZUGFeRD) expect(['cii', 'facturx', 'zugferd', 'CII', 'FACTURX', 'ZUGFERD', 'CrossIndustryInvoice'].includes(format) || format.toString().toLowerCase() === 'cii' || format.toString().toLowerCase() === 'facturx' || format.toString().toLowerCase() === 'zugferd').toEqual(true); } }); tap.start();