Files
einvoice/test/test.conformance-harness.ts

172 lines
6.0 KiB
TypeScript
Raw Normal View History

import { expect, tap } from '@git.zone/tstest/tapbundle/index.js';
import * as path from 'path';
import * as fs from 'fs';
// Import conformance harness
import { ConformanceTestHarness, runConformanceTests } from '../ts/formats/validation/conformance.harness.js';
tap.test('Conformance Test Harness - initialization', async () => {
const harness = new ConformanceTestHarness();
expect(harness).toBeInstanceOf(ConformanceTestHarness);
});
tap.test('Conformance Test Harness - load test samples', async () => {
const harness = new ConformanceTestHarness();
// Check if test-samples directory exists
const samplesDir = path.join(process.cwd(), 'test-samples');
if (fs.existsSync(samplesDir)) {
await harness.loadTestSamples(samplesDir);
console.log('Test samples loaded successfully');
} else {
console.log('Test samples directory not found - skipping');
}
});
tap.test('Conformance Test Harness - run minimal test', async (tools) => {
const harness = new ConformanceTestHarness();
// Create a minimal test sample
const minimalUBL = `<?xml version="1.0" encoding="UTF-8"?>
<Invoice xmlns="urn:oasis:names:specification:ubl:schema:xsd:Invoice-2"
xmlns:cac="urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2"
xmlns:cbc="urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2">
<cbc:CustomizationID>urn:cen.eu:en16931:2017</cbc:CustomizationID>
<cbc:ID>TEST-001</cbc:ID>
<cbc:IssueDate>2025-01-11</cbc:IssueDate>
<cbc:InvoiceTypeCode>380</cbc:InvoiceTypeCode>
<cbc:DocumentCurrencyCode>EUR</cbc:DocumentCurrencyCode>
<cac:AccountingSupplierParty>
<cac:Party>
<cac:PartyName>
<cbc:Name>Test Seller</cbc:Name>
</cac:PartyName>
<cac:PostalAddress>
<cbc:StreetName>Test Street 1</cbc:StreetName>
<cbc:CityName>Test City</cbc:CityName>
<cbc:PostalZone>12345</cbc:PostalZone>
<cac:Country>
<cbc:IdentificationCode>DE</cbc:IdentificationCode>
</cac:Country>
</cac:PostalAddress>
</cac:Party>
</cac:AccountingSupplierParty>
<cac:AccountingCustomerParty>
<cac:Party>
<cac:PartyName>
<cbc:Name>Test Buyer</cbc:Name>
</cac:PartyName>
<cac:PostalAddress>
<cbc:StreetName>Test Street 2</cbc:StreetName>
<cbc:CityName>Test City</cbc:CityName>
<cbc:PostalZone>54321</cbc:PostalZone>
<cac:Country>
<cbc:IdentificationCode>DE</cbc:IdentificationCode>
</cac:Country>
</cac:PostalAddress>
</cac:Party>
</cac:AccountingCustomerParty>
<cac:TaxTotal>
<cbc:TaxAmount currencyID="EUR">19.00</cbc:TaxAmount>
<cac:TaxSubtotal>
<cbc:TaxableAmount currencyID="EUR">100.00</cbc:TaxableAmount>
<cbc:TaxAmount currencyID="EUR">19.00</cbc:TaxAmount>
<cac:TaxCategory>
<cbc:ID>S</cbc:ID>
<cbc:Percent>19</cbc:Percent>
</cac:TaxCategory>
</cac:TaxSubtotal>
</cac:TaxTotal>
<cac:LegalMonetaryTotal>
<cbc:TaxExclusiveAmount currencyID="EUR">100.00</cbc:TaxExclusiveAmount>
<cbc:TaxInclusiveAmount currencyID="EUR">119.00</cbc:TaxInclusiveAmount>
</cac:LegalMonetaryTotal>
<cac:InvoiceLine>
<cbc:ID>1</cbc:ID>
<cbc:InvoicedQuantity unitCode="C62">1</cbc:InvoicedQuantity>
<cbc:LineExtensionAmount currencyID="EUR">100.00</cbc:LineExtensionAmount>
<cac:Item>
<cbc:Name>Test Product</cbc:Name>
<cac:ClassifiedTaxCategory>
<cbc:ID>S</cbc:ID>
<cbc:Percent>19</cbc:Percent>
</cac:ClassifiedTaxCategory>
</cac:Item>
<cac:Price>
<cbc:PriceAmount currencyID="EUR">100.00</cbc:PriceAmount>
</cac:Price>
</cac:InvoiceLine>
</Invoice>`;
// Create temporary test directory
const tempDir = path.join(process.cwd(), '.nogit', 'test-conformance');
if (!fs.existsSync(tempDir)) {
fs.mkdirSync(tempDir, { recursive: true });
}
// Write test file
const testFile = path.join(tempDir, 'minimal-test.xml');
fs.writeFileSync(testFile, minimalUBL);
// Create test sample metadata
const testSamples = [{
id: 'minimal-test',
name: 'minimal-test.xml',
path: testFile,
format: 'UBL' as const,
standard: 'EN16931',
expectedValid: false, // We expect some validation errors
description: 'Minimal test invoice'
}];
// Load test samples manually
(harness as any).testSamples = testSamples;
// Run conformance test
await harness.runConformanceTests();
// Generate coverage matrix
const coverage = harness.generateCoverageMatrix();
console.log(`Coverage: ${coverage.coveragePercentage.toFixed(1)}%`);
console.log(`Rules covered: ${coverage.coveredRules}/${coverage.totalRules}`);
// Clean up
fs.unlinkSync(testFile);
});
tap.test('Conformance Test Harness - coverage report generation', async () => {
const harness = new ConformanceTestHarness();
// Generate empty coverage report
const coverage = harness.generateCoverageMatrix();
expect(coverage.totalRules).toBeGreaterThan(100);
expect(coverage.coveredRules).toBeGreaterThanOrEqual(0);
expect(coverage.coveragePercentage).toBeGreaterThanOrEqual(0);
expect(coverage.byCategory.document.total).toBeGreaterThan(0);
expect(coverage.byCategory.calculation.total).toBeGreaterThan(0);
expect(coverage.byCategory.vat.total).toBeGreaterThan(0);
});
tap.test('Conformance Test Harness - full test suite', async (tools) => {
tools.timeout(60000); // 60 seconds timeout for full test
const samplesDir = path.join(process.cwd(), 'test-samples');
if (!fs.existsSync(samplesDir)) {
console.log('Test samples not found - skipping full conformance test');
console.log('Run: npm run download-test-samples');
return;
}
// Run full conformance test
console.log('\n=== Running Full Conformance Test Suite ===\n');
await runConformanceTests(samplesDir, true);
// Check if HTML report was generated
const reportPath = path.join(process.cwd(), 'coverage-report.html');
if (fs.existsSync(reportPath)) {
console.log(`\n✅ HTML report generated: ${reportPath}`);
}
});
export default tap;