einvoice/test/suite/einvoice_edge-cases/test.edge-01.empty-files.ts

192 lines
6.1 KiB
TypeScript

import { tap, expect } from '@git.zone/tstest/tapbundle';
import { EInvoice } from '../../../ts/index.js';
import { PerformanceTracker } from '../../helpers/performance.tracker.js';
tap.test('EDGE-01: Empty Invoice Files - should handle empty and near-empty files gracefully', async () => {
const einvoice = new EInvoice();
// Test 1: Completely empty file
const { result: completelyEmpty, metric: emptyMetric } = await PerformanceTracker.track(
'completely-empty-file',
async () => {
const emptyContent = '';
try {
await einvoice.fromXmlString(emptyContent);
return {
success: false,
error: null,
message: 'Should have thrown an error'
};
} catch (error) {
return {
success: true,
error: error.message,
message: 'Correctly rejected empty content'
};
}
}
);
console.log('Test 1 - Completely Empty File:');
console.log(` Result: ${completelyEmpty.message}`);
console.log(` Performance: ${emptyMetric.duration.toFixed(2)}ms`);
expect(completelyEmpty.success).toEqual(true);
// Test 2: Only whitespace
const { result: onlyWhitespace, metric: whitespaceMetric } = await PerformanceTracker.track(
'only-whitespace',
async () => {
const whitespaceContent = ' \n\t\r\n ';
try {
await einvoice.fromXmlString(whitespaceContent);
return {
success: false,
error: null,
message: 'Should have thrown an error'
};
} catch (error) {
return {
success: true,
error: error.message,
message: 'Correctly rejected whitespace-only content'
};
}
}
);
console.log('\nTest 2 - Only Whitespace:');
console.log(` Result: ${onlyWhitespace.message}`);
console.log(` Performance: ${whitespaceMetric.duration.toFixed(2)}ms`);
expect(onlyWhitespace.success).toEqual(true);
// Test 3: Empty XML structure
const { result: emptyXML, metric: xmlMetric } = await PerformanceTracker.track(
'empty-xml-structure',
async () => {
const emptyXmlContent = '<?xml version="1.0" encoding="UTF-8"?><empty/>';
try {
await einvoice.fromXmlString(emptyXmlContent);
return {
success: false,
error: null,
message: 'Should have thrown an error for non-invoice XML'
};
} catch (error) {
return {
success: true,
error: error.message,
message: 'Correctly rejected empty XML structure'
};
}
}
);
console.log('\nTest 3 - Empty XML Structure:');
console.log(` Result: ${emptyXML.message}`);
console.log(` Performance: ${xmlMetric.duration.toFixed(2)}ms`);
expect(emptyXML.success).toEqual(true);
// Test 4: Invalid XML
const { result: invalidXML, metric: invalidMetric } = await PerformanceTracker.track(
'invalid-xml',
async () => {
const invalidXmlContent = '<?xml version="1.0"?><unclosed>';
try {
await einvoice.fromXmlString(invalidXmlContent);
return {
success: false,
error: null,
message: 'Should have thrown an error for invalid XML'
};
} catch (error) {
return {
success: true,
error: error.message,
message: 'Correctly rejected invalid XML'
};
}
}
);
console.log('\nTest 4 - Invalid XML:');
console.log(` Result: ${invalidXML.message}`);
console.log(` Performance: ${invalidMetric.duration.toFixed(2)}ms`);
expect(invalidXML.success).toEqual(true);
// Test 5: Minimal valid invoice structure
const { result: minimalInvoice, metric: minimalMetric } = await PerformanceTracker.track(
'minimal-invoice',
async () => {
// Create a minimal but valid UBL invoice
const minimalContent = `<?xml version="1.0" encoding="UTF-8"?>
<Invoice xmlns="urn:oasis:names:specification:ubl:schema:xsd:Invoice-2"
xmlns:cbc="urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2"
xmlns:cac="urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2">
<cbc:ID>MINIMAL-001</cbc:ID>
<cbc:IssueDate>2024-01-01</cbc:IssueDate>
<cac:AccountingSupplierParty>
<cac:Party>
<cac:PartyName>
<cbc:Name>Test Supplier</cbc:Name>
</cac:PartyName>
</cac:Party>
</cac:AccountingSupplierParty>
<cac:AccountingCustomerParty>
<cac:Party>
<cac:PartyName>
<cbc:Name>Test Customer</cbc:Name>
</cac:PartyName>
</cac:Party>
</cac:AccountingCustomerParty>
<cac:LegalMonetaryTotal>
<cbc:TaxInclusiveAmount currencyID="EUR">0.00</cbc:TaxInclusiveAmount>
</cac:LegalMonetaryTotal>
</Invoice>`;
try {
await einvoice.fromXmlString(minimalContent);
// Test validation
const validation = await einvoice.validate();
return {
success: true,
error: null,
message: 'Successfully parsed minimal invoice',
validationResult: validation.valid,
id: einvoice.id
};
} catch (error) {
return {
success: false,
error: error.message,
message: 'Failed to parse minimal invoice'
};
}
}
);
console.log('\nTest 5 - Minimal Valid Invoice:');
console.log(` Result: ${minimalInvoice.message}`);
console.log(` Invoice ID: ${minimalInvoice.id || 'N/A'}`);
console.log(` Validation: ${minimalInvoice.validationResult ? 'Valid' : 'Invalid'}`);
console.log(` Performance: ${minimalMetric.duration.toFixed(2)}ms`);
expect(minimalInvoice.success).toEqual(true);
// Performance summary
const perfSummary = await PerformanceTracker.getSummary('completely-empty-file');
if (perfSummary) {
console.log('\nPerformance Summary:');
console.log(` Empty file handling: ${perfSummary.average.toFixed(2)}ms average`);
}
console.log('\n=== EDGE-01: Empty Files Test Summary ===');
console.log('All edge cases for empty files handled correctly');
console.log('The implementation properly rejects invalid/empty content');
console.log('and successfully parses minimal valid invoices');
});
tap.start();