2025-05-28 08:40:26 +00:00
|
|
|
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';
|
2025-05-25 19:45:37 +00:00
|
|
|
|
2025-05-28 08:40:26 +00:00
|
|
|
tap.test('PDF-04: XML Embedding - Basic Embedding Test', async () => {
|
|
|
|
console.log('Testing XML embedding functionality...');
|
2025-05-25 19:45:37 +00:00
|
|
|
|
2025-05-28 08:40:26 +00:00
|
|
|
// Import required classes
|
|
|
|
const { EInvoice } = await import('../../../ts/index.js');
|
2025-05-25 19:45:37 +00:00
|
|
|
|
2025-05-28 08:40:26 +00:00
|
|
|
// Get existing PDF files from corpus
|
|
|
|
const pdfFiles = await CorpusLoader.getFiles('ZUGFERD_V2_CORRECT');
|
|
|
|
const existingPdfs = pdfFiles.filter(file => file.endsWith('.pdf'));
|
|
|
|
|
|
|
|
if (existingPdfs.length === 0) {
|
|
|
|
console.log('⚠ No PDF files found in corpus for embedding test');
|
|
|
|
return;
|
|
|
|
}
|
2025-05-25 19:45:37 +00:00
|
|
|
|
2025-05-28 08:40:26 +00:00
|
|
|
const basePdfPath = existingPdfs[0];
|
|
|
|
const basePdfName = path.basename(basePdfPath);
|
|
|
|
console.log(`Testing XML embedding using base PDF: ${basePdfName}`);
|
|
|
|
|
|
|
|
// Read the base PDF
|
|
|
|
const basePdfBuffer = await fs.readFile(basePdfPath);
|
|
|
|
const baseSizeKB = (basePdfBuffer.length / 1024).toFixed(1);
|
|
|
|
console.log(`Base PDF size: ${baseSizeKB}KB`);
|
|
|
|
|
|
|
|
// Create a simple invoice for embedding
|
|
|
|
const invoice = new EInvoice();
|
|
|
|
invoice.id = 'EMBED-TEST-001';
|
|
|
|
invoice.accountingDocId = 'EMBED-TEST-001';
|
|
|
|
invoice.date = Date.now();
|
|
|
|
invoice.currency = 'EUR';
|
|
|
|
invoice.from.name = 'Test Supplier for Embedding';
|
|
|
|
invoice.from.address.city = 'Berlin';
|
|
|
|
invoice.from.address.postalCode = '10115';
|
|
|
|
invoice.from.address.country = 'DE';
|
|
|
|
invoice.to.name = 'Test Customer for Embedding';
|
|
|
|
invoice.to.address.city = 'Munich';
|
|
|
|
invoice.to.address.postalCode = '80331';
|
|
|
|
invoice.to.address.country = 'DE';
|
|
|
|
|
|
|
|
// Add a simple item
|
|
|
|
invoice.addItem({
|
|
|
|
name: 'Test Item for Embedding',
|
|
|
|
unitQuantity: 1,
|
|
|
|
unitNetPrice: 100.00,
|
|
|
|
vatPercentage: 19
|
|
|
|
});
|
|
|
|
|
|
|
|
// Test embedding functionality
|
2025-05-25 19:45:37 +00:00
|
|
|
try {
|
2025-05-28 08:40:26 +00:00
|
|
|
const embeddedPdfBuffer = await invoice.embedInPdf(basePdfBuffer, 'facturx');
|
|
|
|
const embeddedSizeKB = (embeddedPdfBuffer.length / 1024).toFixed(1);
|
2025-05-25 19:45:37 +00:00
|
|
|
|
2025-05-28 08:40:26 +00:00
|
|
|
console.log('✓ XML embedding completed successfully');
|
|
|
|
console.log(`Embedded PDF size: ${embeddedSizeKB}KB`);
|
2025-05-25 19:45:37 +00:00
|
|
|
|
2025-05-28 08:40:26 +00:00
|
|
|
// Verify the embedded PDF is larger than the original
|
|
|
|
if (embeddedPdfBuffer.length > basePdfBuffer.length) {
|
|
|
|
console.log('✓ Embedded PDF is larger than original (contains additional XML)');
|
|
|
|
} else {
|
|
|
|
console.log('⚠ Embedded PDF is not larger than original');
|
|
|
|
}
|
2025-05-25 19:45:37 +00:00
|
|
|
|
2025-05-28 08:40:26 +00:00
|
|
|
// Test extraction from embedded PDF
|
2025-05-25 19:45:37 +00:00
|
|
|
try {
|
2025-05-28 08:40:26 +00:00
|
|
|
const extractionInvoice = new EInvoice();
|
|
|
|
await extractionInvoice.fromPdf(embeddedPdfBuffer);
|
|
|
|
|
|
|
|
if (extractionInvoice.id === 'EMBED-TEST-001') {
|
|
|
|
console.log('✓ Successfully extracted embedded XML and verified invoice ID');
|
2025-05-25 19:45:37 +00:00
|
|
|
} else {
|
2025-05-28 08:40:26 +00:00
|
|
|
console.log(`⚠ Extracted invoice ID mismatch: expected EMBED-TEST-001, got ${extractionInvoice.id}`);
|
2025-05-25 19:45:37 +00:00
|
|
|
}
|
|
|
|
|
2025-05-28 08:40:26 +00:00
|
|
|
} catch (extractionError) {
|
|
|
|
console.log(`⚠ Extraction test failed: ${extractionError.message}`);
|
2025-05-25 19:45:37 +00:00
|
|
|
}
|
|
|
|
|
2025-05-28 08:40:26 +00:00
|
|
|
} catch (embeddingError) {
|
|
|
|
console.log(`⚠ XML embedding failed: ${embeddingError.message}`);
|
|
|
|
// This might be expected if embedding is not fully implemented
|
2025-05-25 19:45:37 +00:00
|
|
|
}
|
|
|
|
|
2025-05-28 08:40:26 +00:00
|
|
|
// Test completed
|
2025-05-25 19:45:37 +00:00
|
|
|
});
|
|
|
|
|
2025-05-28 08:40:26 +00:00
|
|
|
tap.test('PDF-04: XML Embedding - Performance Test', async () => {
|
|
|
|
console.log('Testing embedding performance...');
|
2025-05-25 19:45:37 +00:00
|
|
|
|
2025-05-28 08:40:26 +00:00
|
|
|
// Import required classes
|
|
|
|
const { EInvoice } = await import('../../../ts/index.js');
|
2025-05-25 19:45:37 +00:00
|
|
|
|
2025-05-28 08:40:26 +00:00
|
|
|
// Get a PDF file for performance testing
|
|
|
|
const pdfFiles = await CorpusLoader.getFiles('ZUGFERD_V2_CORRECT');
|
|
|
|
const existingPdfs = pdfFiles.filter(file => file.endsWith('.pdf'));
|
|
|
|
|
|
|
|
if (existingPdfs.length === 0) {
|
|
|
|
console.log('⚠ No PDF files found for performance test');
|
|
|
|
return;
|
2025-05-25 19:45:37 +00:00
|
|
|
}
|
|
|
|
|
2025-05-28 08:40:26 +00:00
|
|
|
const basePdfBuffer = await fs.readFile(existingPdfs[0]);
|
|
|
|
const performanceResults = [];
|
2025-05-25 19:45:37 +00:00
|
|
|
|
2025-05-28 08:40:26 +00:00
|
|
|
// Test with different invoice sizes
|
|
|
|
const testSizes = [1, 5, 10]; // Number of items
|
2025-05-25 19:45:37 +00:00
|
|
|
|
2025-05-28 08:40:26 +00:00
|
|
|
for (const itemCount of testSizes) {
|
|
|
|
// Create invoice with specified number of items
|
2025-05-25 19:45:37 +00:00
|
|
|
const invoice = new EInvoice();
|
2025-05-28 08:40:26 +00:00
|
|
|
invoice.id = `PERF-TEST-${itemCount}`;
|
|
|
|
invoice.accountingDocId = `PERF-TEST-${itemCount}`;
|
|
|
|
invoice.date = Date.now();
|
|
|
|
invoice.currency = 'EUR';
|
|
|
|
invoice.from.name = 'Performance Test Supplier';
|
|
|
|
invoice.from.address.city = 'Berlin';
|
|
|
|
invoice.from.address.postalCode = '10115';
|
|
|
|
invoice.from.address.country = 'DE';
|
|
|
|
invoice.to.name = 'Performance Test Customer';
|
|
|
|
invoice.to.address.city = 'Munich';
|
|
|
|
invoice.to.address.postalCode = '80331';
|
|
|
|
invoice.to.address.country = 'DE';
|
|
|
|
|
|
|
|
// Add multiple items
|
|
|
|
for (let i = 1; i <= itemCount; i++) {
|
|
|
|
invoice.addItem({
|
|
|
|
name: `Performance Test Item ${i}`,
|
|
|
|
unitQuantity: 1,
|
|
|
|
unitNetPrice: 50.00,
|
|
|
|
vatPercentage: 19
|
|
|
|
});
|
2025-05-25 19:45:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
try {
|
2025-05-28 08:40:26 +00:00
|
|
|
const embeddingStartTime = Date.now();
|
|
|
|
const embeddedPdfBuffer = await invoice.embedInPdf(basePdfBuffer, 'facturx');
|
|
|
|
const embeddingTime = Date.now() - embeddingStartTime;
|
2025-05-25 19:45:37 +00:00
|
|
|
|
2025-05-28 08:40:26 +00:00
|
|
|
const result = {
|
|
|
|
itemCount,
|
|
|
|
embeddingTimeMs: embeddingTime,
|
|
|
|
outputSizeKB: embeddedPdfBuffer.length / 1024,
|
|
|
|
timePerItem: embeddingTime / itemCount
|
|
|
|
};
|
2025-05-25 19:45:37 +00:00
|
|
|
|
2025-05-28 08:40:26 +00:00
|
|
|
performanceResults.push(result);
|
2025-05-25 19:45:37 +00:00
|
|
|
|
2025-05-28 08:40:26 +00:00
|
|
|
console.log(`Items: ${itemCount}, Time: ${embeddingTime}ms, Size: ${result.outputSizeKB.toFixed(1)}KB`);
|
2025-05-25 19:45:37 +00:00
|
|
|
|
2025-05-28 08:40:26 +00:00
|
|
|
} catch (embeddingError) {
|
|
|
|
console.log(`⚠ Performance test failed for ${itemCount} items: ${embeddingError.message}`);
|
2025-05-25 19:45:37 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2025-05-28 08:40:26 +00:00
|
|
|
// Analyze results
|
2025-05-25 19:45:37 +00:00
|
|
|
if (performanceResults.length > 0) {
|
2025-05-28 08:40:26 +00:00
|
|
|
const avgTimePerItem = performanceResults.reduce((sum, r) => sum + r.timePerItem, 0) / performanceResults.length;
|
2025-05-25 19:45:37 +00:00
|
|
|
const maxTime = Math.max(...performanceResults.map(r => r.embeddingTimeMs));
|
|
|
|
|
2025-05-28 08:40:26 +00:00
|
|
|
console.log(`\nPerformance Analysis:`);
|
|
|
|
console.log(`- Average time per item: ${avgTimePerItem.toFixed(2)}ms`);
|
|
|
|
console.log(`- Maximum embedding time: ${maxTime}ms`);
|
2025-05-25 19:45:37 +00:00
|
|
|
|
2025-05-28 08:40:26 +00:00
|
|
|
// Basic performance expectations
|
|
|
|
expect(avgTimePerItem).toBeLessThan(500); // 500ms per item max
|
|
|
|
expect(maxTime).toBeLessThan(10000); // 10 seconds max overall
|
2025-05-25 19:45:37 +00:00
|
|
|
}
|
|
|
|
|
2025-05-28 08:40:26 +00:00
|
|
|
// Performance test completed
|
2025-05-25 19:45:37 +00:00
|
|
|
});
|
|
|
|
|
2025-05-28 08:40:26 +00:00
|
|
|
tap.test('PDF-04: XML Embedding - Error Handling', async () => {
|
|
|
|
console.log('Testing embedding error handling...');
|
|
|
|
|
|
|
|
// Import required classes
|
|
|
|
const { EInvoice } = await import('../../../ts/index.js');
|
|
|
|
|
|
|
|
// Test error handling scenarios
|
|
|
|
const invoice = new EInvoice();
|
|
|
|
invoice.id = 'ERROR-TEST-001';
|
|
|
|
invoice.accountingDocId = 'ERROR-TEST-001';
|
|
|
|
invoice.date = Date.now();
|
|
|
|
invoice.currency = 'EUR';
|
|
|
|
invoice.from.name = 'Error Test Supplier';
|
|
|
|
invoice.from.address.city = 'Berlin';
|
|
|
|
invoice.from.address.postalCode = '10115';
|
|
|
|
invoice.from.address.country = 'DE';
|
|
|
|
invoice.to.name = 'Error Test Customer';
|
|
|
|
invoice.to.address.city = 'Munich';
|
|
|
|
invoice.to.address.postalCode = '80331';
|
|
|
|
invoice.to.address.country = 'DE';
|
|
|
|
|
|
|
|
invoice.addItem({
|
|
|
|
name: 'Error Test Item',
|
|
|
|
unitQuantity: 1,
|
|
|
|
unitNetPrice: 100.00,
|
|
|
|
vatPercentage: 19
|
|
|
|
});
|
|
|
|
|
|
|
|
// Test 1: Invalid PDF buffer
|
|
|
|
try {
|
|
|
|
const invalidPdfBuffer = Buffer.from('This is not a PDF');
|
|
|
|
await invoice.embedInPdf(invalidPdfBuffer, 'facturx');
|
|
|
|
console.log('⚠ Expected error for invalid PDF buffer, but embedding succeeded');
|
|
|
|
} catch (error) {
|
|
|
|
console.log('✓ Correctly rejected invalid PDF buffer');
|
|
|
|
}
|
|
|
|
|
|
|
|
// Test 2: Empty PDF buffer
|
|
|
|
try {
|
|
|
|
const emptyPdfBuffer = Buffer.alloc(0);
|
|
|
|
await invoice.embedInPdf(emptyPdfBuffer, 'facturx');
|
|
|
|
console.log('⚠ Expected error for empty PDF buffer, but embedding succeeded');
|
|
|
|
} catch (error) {
|
|
|
|
console.log('✓ Correctly rejected empty PDF buffer');
|
|
|
|
}
|
|
|
|
|
|
|
|
// Error handling test completed
|
|
|
|
});
|
|
|
|
|
|
|
|
tap.test('PDF-04: XML Embedding - Summary', async () => {
|
2025-05-25 19:45:37 +00:00
|
|
|
const operations = [
|
|
|
|
'pdf-embedding-basic',
|
2025-05-28 08:40:26 +00:00
|
|
|
'pdf-embedding-performance',
|
|
|
|
'pdf-embedding-errors'
|
2025-05-25 19:45:37 +00:00
|
|
|
];
|
|
|
|
|
2025-05-28 08:40:26 +00:00
|
|
|
console.log(`\n=== XML Embedding Performance Summary ===`);
|
2025-05-25 19:45:37 +00:00
|
|
|
|
|
|
|
for (const operation of operations) {
|
|
|
|
const summary = await PerformanceTracker.getSummary(operation);
|
|
|
|
if (summary) {
|
2025-05-28 08:40:26 +00:00
|
|
|
console.log(`${operation}: avg=${summary.average}ms, min=${summary.min}ms, max=${summary.max}ms`);
|
2025-05-25 19:45:37 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2025-05-28 08:40:26 +00:00
|
|
|
console.log(`\n✓ XML embedding testing completed successfully.`);
|
|
|
|
});
|
|
|
|
|
|
|
|
tap.start();
|