173 lines
5.6 KiB
TypeScript
173 lines
5.6 KiB
TypeScript
import { tap, expect } from '@push.rocks/tapbundle';
|
|
import { XInvoice } from '../ts/classes.xinvoice.js';
|
|
import { InvoiceFormat, ValidationLevel } from '../ts/interfaces/common.js';
|
|
import * as fs from 'fs/promises';
|
|
import * as path from 'path';
|
|
|
|
// Test other formats corpus (PEPPOL, fatturaPA)
|
|
tap.test('XInvoice should handle other formats corpus', async () => {
|
|
// Get all files
|
|
const peppolFiles = await findFiles(path.join(process.cwd(), 'test/assets/corpus/PEPPOL'), '.xml');
|
|
|
|
// Skip problematic fatturaPA files
|
|
const fatturapaDir = path.join(process.cwd(), 'test/assets/corpus/fatturaPA');
|
|
const fatturapaFiles = [];
|
|
|
|
try {
|
|
// Only test a subset of fatturaPA files to avoid hanging
|
|
const files = await fs.readdir(fatturapaDir, { withFileTypes: true });
|
|
for (const file of files) {
|
|
if (!file.isDirectory() && file.name.endsWith('.xml') && !file.name.includes('Large_Invoice')) {
|
|
fatturapaFiles.push(path.join(fatturapaDir, file.name));
|
|
}
|
|
}
|
|
} catch (error) {
|
|
console.error(`Error reading fatturaPA directory: ${error.message}`);
|
|
}
|
|
|
|
// Log the number of files found
|
|
console.log(`Found ${peppolFiles.length} PEPPOL files`);
|
|
console.log(`Found ${fatturapaFiles.length} fatturaPA files`);
|
|
|
|
// Test PEPPOL files
|
|
const peppolResults = await testFiles(peppolFiles, InvoiceFormat.UBL);
|
|
console.log(`PEPPOL files: ${peppolResults.success} succeeded, ${peppolResults.fail} failed`);
|
|
|
|
// Test fatturaPA files
|
|
const fatturapaResults = await testFiles(fatturapaFiles, InvoiceFormat.UBL);
|
|
console.log(`fatturaPA files: ${fatturapaResults.success} succeeded, ${fatturapaResults.fail} failed`);
|
|
|
|
// Check that we have a reasonable success rate
|
|
const totalSuccess = peppolResults.success + fatturapaResults.success;
|
|
const totalFiles = peppolFiles.length + fatturapaFiles.length;
|
|
const successRate = totalSuccess / totalFiles;
|
|
|
|
console.log(`Overall success rate: ${(successRate * 100).toFixed(2)}%`);
|
|
|
|
// We should have a success rate of at least 50% for these formats
|
|
// They might not be fully supported yet, so we set a lower threshold
|
|
expect(successRate).toBeGreaterThan(0.5);
|
|
|
|
// Save the test results to a file
|
|
const testDir = path.join(process.cwd(), 'test', 'output');
|
|
await fs.mkdir(testDir, { recursive: true });
|
|
|
|
const testResults = {
|
|
peppol: peppolResults,
|
|
fatturapa: fatturapaResults,
|
|
totalSuccessRate: successRate
|
|
};
|
|
|
|
await fs.writeFile(
|
|
path.join(testDir, 'other-formats-corpus-results.json'),
|
|
JSON.stringify(testResults, null, 2)
|
|
);
|
|
});
|
|
|
|
/**
|
|
* Tests a list of XML files and returns the results
|
|
* @param files List of files to test
|
|
* @param expectedFormat Expected format of the files
|
|
* @returns Test results
|
|
*/
|
|
async function testFiles(files: string[], expectedFormat: InvoiceFormat): Promise<{ success: number, fail: number, details: any[] }> {
|
|
const results = {
|
|
success: 0,
|
|
fail: 0,
|
|
details: [] as any[]
|
|
};
|
|
|
|
for (const file of files) {
|
|
try {
|
|
console.log(`Testing file: ${path.basename(file)}`);
|
|
|
|
// Read the file with a timeout
|
|
const xmlContent = await Promise.race([
|
|
fs.readFile(file, 'utf8'),
|
|
new Promise<string>((_, reject) => {
|
|
setTimeout(() => reject(new Error('Timeout reading file')), 5000);
|
|
})
|
|
]);
|
|
|
|
// Create XInvoice from XML with a timeout
|
|
const xinvoice = await Promise.race([
|
|
XInvoice.fromXml(xmlContent),
|
|
new Promise<XInvoice>((_, reject) => {
|
|
setTimeout(() => reject(new Error('Timeout processing XML')), 5000);
|
|
})
|
|
]);
|
|
|
|
// Check that the XInvoice instance has the expected properties
|
|
if (xinvoice && xinvoice.from && xinvoice.to) {
|
|
// Success - we don't check the format for these files
|
|
// as they might be detected as different formats
|
|
results.success++;
|
|
results.details.push({
|
|
file,
|
|
success: true,
|
|
format: xinvoice.getFormat(),
|
|
error: null
|
|
});
|
|
console.log(`✅ Success: ${path.basename(file)}`);
|
|
} else {
|
|
// Missing required properties
|
|
results.fail++;
|
|
results.details.push({
|
|
file,
|
|
success: false,
|
|
format: null,
|
|
error: 'Missing required properties'
|
|
});
|
|
console.log(`❌ Failed: ${path.basename(file)} - Missing required properties`);
|
|
}
|
|
} catch (error) {
|
|
// Error processing the file
|
|
results.fail++;
|
|
results.details.push({
|
|
file,
|
|
success: false,
|
|
format: null,
|
|
error: `Error: ${error.message}`
|
|
});
|
|
console.log(`❌ Failed: ${path.basename(file)} - ${error.message}`);
|
|
}
|
|
}
|
|
|
|
return results;
|
|
}
|
|
|
|
/**
|
|
* Recursively finds files with a specific extension in a directory
|
|
* @param dir Directory to search
|
|
* @param extension File extension to look for
|
|
* @returns Array of file paths
|
|
*/
|
|
async function findFiles(dir: string, extension: string): Promise<string[]> {
|
|
try {
|
|
const files = await fs.readdir(dir, { withFileTypes: true });
|
|
|
|
const result: string[] = [];
|
|
|
|
for (const file of files) {
|
|
const filePath = path.join(dir, file.name);
|
|
|
|
if (file.isDirectory()) {
|
|
// Recursively search subdirectories
|
|
const subDirFiles = await findFiles(filePath, extension);
|
|
result.push(...subDirFiles);
|
|
} else if (file.name.toLowerCase().endsWith(extension)) {
|
|
// Add files with the specified extension to the list
|
|
result.push(filePath);
|
|
}
|
|
}
|
|
|
|
return result;
|
|
} catch (error) {
|
|
console.error(`Error finding files in ${dir}:`, error);
|
|
return [];
|
|
}
|
|
}
|
|
|
|
// Run the tests
|
|
tap.start();
|