314 lines
11 KiB
TypeScript
314 lines
11 KiB
TypeScript
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(); |