493 lines
17 KiB
TypeScript
493 lines
17 KiB
TypeScript
|
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';
|
||
|
|
||
|
tap.test('VAL-06: Cross-Reference Validation - should validate references between invoice elements', async () => {
|
||
|
// Test files that should have proper cross-references
|
||
|
const ublFiles = await CorpusLoader.getFiles('UBL_XMLRECHNUNG');
|
||
|
const ciiFiles = await CorpusLoader.getFiles('CII_XMLRECHNUNG');
|
||
|
|
||
|
const testFiles = [...ublFiles.slice(0, 3), ...ciiFiles.slice(0, 3)];
|
||
|
console.log(`Testing cross-reference validation on ${testFiles.length} files`);
|
||
|
|
||
|
const { EInvoice } = await import('../../../ts/index.js');
|
||
|
|
||
|
let validReferences = 0;
|
||
|
let invalidReferences = 0;
|
||
|
let errorCount = 0;
|
||
|
const referenceIssues: { file: string; issues: string[] }[] = [];
|
||
|
|
||
|
for (const filePath of testFiles) {
|
||
|
const fileName = path.basename(filePath);
|
||
|
|
||
|
try {
|
||
|
const xmlContent = await fs.readFile(filePath, 'utf-8');
|
||
|
|
||
|
const { result: einvoice } = await PerformanceTracker.track(
|
||
|
'cross-ref-xml-loading',
|
||
|
async () => await EInvoice.fromXml(xmlContent)
|
||
|
);
|
||
|
|
||
|
const { result: validation } = await PerformanceTracker.track(
|
||
|
'cross-reference-validation',
|
||
|
async () => {
|
||
|
return await einvoice.validate(/* ValidationLevel.SEMANTIC */);
|
||
|
},
|
||
|
{ file: fileName }
|
||
|
);
|
||
|
|
||
|
if (validation.valid) {
|
||
|
validReferences++;
|
||
|
console.log(`✓ ${fileName}: Cross-references valid`);
|
||
|
} else {
|
||
|
invalidReferences++;
|
||
|
|
||
|
// Look for reference-specific errors
|
||
|
const refErrors = validation.errors ? validation.errors.filter(e =>
|
||
|
e.message && (
|
||
|
e.message.toLowerCase().includes('reference') ||
|
||
|
e.message.toLowerCase().includes('missing') ||
|
||
|
e.message.toLowerCase().includes('invalid') ||
|
||
|
e.message.toLowerCase().includes('link') ||
|
||
|
e.code && e.code.includes('REF')
|
||
|
)
|
||
|
) : [];
|
||
|
|
||
|
if (refErrors.length > 0) {
|
||
|
console.log(`○ ${fileName}: Reference issues found (${refErrors.length})`);
|
||
|
referenceIssues.push({
|
||
|
file: fileName,
|
||
|
issues: refErrors.map(e => `${e.code}: ${e.message}`)
|
||
|
});
|
||
|
} else {
|
||
|
console.log(`○ ${fileName}: Invalid but no specific reference errors`);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
} catch (error) {
|
||
|
errorCount++;
|
||
|
console.log(`✗ ${fileName}: Error - ${error.message}`);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
console.log('\n=== CROSS-REFERENCE VALIDATION SUMMARY ===');
|
||
|
console.log(`Valid references: ${validReferences}`);
|
||
|
console.log(`Invalid references: ${invalidReferences}`);
|
||
|
console.log(`Processing errors: ${errorCount}`);
|
||
|
|
||
|
// Show sample reference issues
|
||
|
if (referenceIssues.length > 0) {
|
||
|
console.log('\nSample reference issues:');
|
||
|
referenceIssues.slice(0, 3).forEach(item => {
|
||
|
console.log(` ${item.file}:`);
|
||
|
item.issues.slice(0, 2).forEach(issue => {
|
||
|
console.log(` - ${issue}`);
|
||
|
});
|
||
|
});
|
||
|
}
|
||
|
|
||
|
// Performance summary
|
||
|
const perfSummary = await PerformanceTracker.getSummary('cross-reference-validation');
|
||
|
if (perfSummary) {
|
||
|
console.log(`\nCross-Reference Validation Performance:`);
|
||
|
console.log(` Average: ${perfSummary.average.toFixed(2)}ms`);
|
||
|
console.log(` P95: ${perfSummary.p95.toFixed(2)}ms`);
|
||
|
}
|
||
|
|
||
|
// Expect files to be processed successfully
|
||
|
expect(validReferences + invalidReferences).toBeGreaterThan(0);
|
||
|
});
|
||
|
|
||
|
tap.test('VAL-06: Party Reference Validation - should validate party references and IDs', async () => {
|
||
|
const { EInvoice } = await import('../../../ts/index.js');
|
||
|
|
||
|
const partyReferenceTests = [
|
||
|
{
|
||
|
name: 'Valid party references',
|
||
|
xml: `<?xml version="1.0"?>
|
||
|
<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:ID>PARTY-REF-001</cbc:ID>
|
||
|
<cac:AccountingSupplierParty>
|
||
|
<cac:Party>
|
||
|
<cac:PartyIdentification>
|
||
|
<cbc:ID schemeID="0088">1234567890123</cbc:ID>
|
||
|
</cac:PartyIdentification>
|
||
|
<cac:PartyName>
|
||
|
<cbc:Name>Supplier Company Ltd</cbc:Name>
|
||
|
</cac:PartyName>
|
||
|
</cac:Party>
|
||
|
</cac:AccountingSupplierParty>
|
||
|
<cac:AccountingCustomerParty>
|
||
|
<cac:Party>
|
||
|
<cac:PartyIdentification>
|
||
|
<cbc:ID schemeID="0088">9876543210987</cbc:ID>
|
||
|
</cac:PartyIdentification>
|
||
|
<cac:PartyName>
|
||
|
<cbc:Name>Customer Company Ltd</cbc:Name>
|
||
|
</cac:PartyName>
|
||
|
</cac:Party>
|
||
|
</cac:AccountingCustomerParty>
|
||
|
</Invoice>`,
|
||
|
shouldBeValid: true,
|
||
|
description: 'Parties with proper identification'
|
||
|
},
|
||
|
{
|
||
|
name: 'Missing party identification',
|
||
|
xml: `<?xml version="1.0"?>
|
||
|
<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:ID>PARTY-REF-002</cbc:ID>
|
||
|
<cac:AccountingSupplierParty>
|
||
|
<cac:Party>
|
||
|
<cac:PartyName>
|
||
|
<cbc:Name>Supplier Without ID</cbc:Name>
|
||
|
</cac:PartyName>
|
||
|
</cac:Party>
|
||
|
</cac:AccountingSupplierParty>
|
||
|
</Invoice>`,
|
||
|
shouldBeValid: false,
|
||
|
description: 'Missing required party identification'
|
||
|
},
|
||
|
{
|
||
|
name: 'Invalid party ID scheme',
|
||
|
xml: `<?xml version="1.0"?>
|
||
|
<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:ID>PARTY-REF-003</cbc:ID>
|
||
|
<cac:AccountingSupplierParty>
|
||
|
<cac:Party>
|
||
|
<cac:PartyIdentification>
|
||
|
<cbc:ID schemeID="INVALID">123456</cbc:ID>
|
||
|
</cac:PartyIdentification>
|
||
|
<cac:PartyName>
|
||
|
<cbc:Name>Supplier Company</cbc:Name>
|
||
|
</cac:PartyName>
|
||
|
</cac:Party>
|
||
|
</cac:AccountingSupplierParty>
|
||
|
</Invoice>`,
|
||
|
shouldBeValid: false,
|
||
|
description: 'Invalid party identification scheme'
|
||
|
}
|
||
|
];
|
||
|
|
||
|
for (const test of partyReferenceTests) {
|
||
|
try {
|
||
|
const { result: validation } = await PerformanceTracker.track(
|
||
|
'party-reference-test',
|
||
|
async () => {
|
||
|
const einvoice = await EInvoice.fromXml(test.xml);
|
||
|
return await einvoice.validate();
|
||
|
}
|
||
|
);
|
||
|
|
||
|
console.log(`${test.name}: ${validation.valid ? 'VALID' : 'INVALID'}`);
|
||
|
console.log(` ${test.description}`);
|
||
|
|
||
|
if (!test.shouldBeValid && !validation.valid) {
|
||
|
console.log(` ✓ Correctly detected party reference issues`);
|
||
|
if (validation.errors) {
|
||
|
const partyErrors = validation.errors.filter(e =>
|
||
|
e.message && (
|
||
|
e.message.toLowerCase().includes('party') ||
|
||
|
e.message.toLowerCase().includes('identification') ||
|
||
|
e.message.toLowerCase().includes('scheme')
|
||
|
)
|
||
|
);
|
||
|
console.log(` Party reference errors: ${partyErrors.length}`);
|
||
|
}
|
||
|
} else if (test.shouldBeValid && validation.valid) {
|
||
|
console.log(` ✓ Correctly validated party references`);
|
||
|
} else {
|
||
|
console.log(` ○ Unexpected result (party reference validation may need implementation)`);
|
||
|
}
|
||
|
|
||
|
} catch (error) {
|
||
|
console.log(`${test.name}: Error - ${error.message}`);
|
||
|
}
|
||
|
}
|
||
|
});
|
||
|
|
||
|
tap.test('VAL-06: Tax Category Reference Validation - should validate tax category references', async () => {
|
||
|
const { EInvoice } = await import('../../../ts/index.js');
|
||
|
|
||
|
const taxReferenceTests = [
|
||
|
{
|
||
|
name: 'Valid tax category references',
|
||
|
xml: `<?xml version="1.0"?>
|
||
|
<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:ID>TAX-REF-001</cbc:ID>
|
||
|
<cac:TaxTotal>
|
||
|
<cbc:TaxAmount currencyID="EUR">190.00</cbc:TaxAmount>
|
||
|
<cac:TaxSubtotal>
|
||
|
<cbc:TaxableAmount currencyID="EUR">1000.00</cbc:TaxableAmount>
|
||
|
<cbc:TaxAmount currencyID="EUR">190.00</cbc:TaxAmount>
|
||
|
<cac:TaxCategory>
|
||
|
<cbc:ID>S</cbc:ID>
|
||
|
<cbc:Percent>19</cbc:Percent>
|
||
|
<cac:TaxScheme>
|
||
|
<cbc:ID>VAT</cbc:ID>
|
||
|
</cac:TaxScheme>
|
||
|
</cac:TaxCategory>
|
||
|
</cac:TaxSubtotal>
|
||
|
</cac:TaxTotal>
|
||
|
<cac:InvoiceLine>
|
||
|
<cbc:ID>1</cbc:ID>
|
||
|
<cac:Item>
|
||
|
<cac:ClassifiedTaxCategory>
|
||
|
<cbc:ID>S</cbc:ID>
|
||
|
<cbc:Percent>19</cbc:Percent>
|
||
|
<cac:TaxScheme>
|
||
|
<cbc:ID>VAT</cbc:ID>
|
||
|
</cac:TaxScheme>
|
||
|
</cac:ClassifiedTaxCategory>
|
||
|
</cac:Item>
|
||
|
</cac:InvoiceLine>
|
||
|
</Invoice>`,
|
||
|
shouldBeValid: true,
|
||
|
description: 'Tax categories properly referenced between totals and line items'
|
||
|
},
|
||
|
{
|
||
|
name: 'Mismatched tax category references',
|
||
|
xml: `<?xml version="1.0"?>
|
||
|
<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:ID>TAX-REF-002</cbc:ID>
|
||
|
<cac:TaxTotal>
|
||
|
<cac:TaxSubtotal>
|
||
|
<cac:TaxCategory>
|
||
|
<cbc:ID>S</cbc:ID>
|
||
|
<cbc:Percent>19</cbc:Percent>
|
||
|
<cac:TaxScheme>
|
||
|
<cbc:ID>VAT</cbc:ID>
|
||
|
</cac:TaxScheme>
|
||
|
</cac:TaxCategory>
|
||
|
</cac:TaxSubtotal>
|
||
|
</cac:TaxTotal>
|
||
|
<cac:InvoiceLine>
|
||
|
<cbc:ID>1</cbc:ID>
|
||
|
<cac:Item>
|
||
|
<cac:ClassifiedTaxCategory>
|
||
|
<cbc:ID>E</cbc:ID>
|
||
|
<cbc:Percent>0</cbc:Percent>
|
||
|
<cac:TaxScheme>
|
||
|
<cbc:ID>VAT</cbc:ID>
|
||
|
</cac:TaxScheme>
|
||
|
</cac:ClassifiedTaxCategory>
|
||
|
</cac:Item>
|
||
|
</cac:InvoiceLine>
|
||
|
</Invoice>`,
|
||
|
shouldBeValid: false,
|
||
|
description: 'Tax category mismatch: S in total vs E in line item'
|
||
|
}
|
||
|
];
|
||
|
|
||
|
for (const test of taxReferenceTests) {
|
||
|
try {
|
||
|
const { result: validation } = await PerformanceTracker.track(
|
||
|
'tax-reference-test',
|
||
|
async () => {
|
||
|
const einvoice = await EInvoice.fromXml(test.xml);
|
||
|
return await einvoice.validate();
|
||
|
}
|
||
|
);
|
||
|
|
||
|
console.log(`${test.name}: ${validation.valid ? 'VALID' : 'INVALID'}`);
|
||
|
console.log(` ${test.description}`);
|
||
|
|
||
|
if (!test.shouldBeValid && !validation.valid) {
|
||
|
console.log(` ✓ Correctly detected tax reference mismatch`);
|
||
|
if (validation.errors) {
|
||
|
const taxErrors = validation.errors.filter(e =>
|
||
|
e.message && (
|
||
|
e.message.toLowerCase().includes('tax') ||
|
||
|
e.message.toLowerCase().includes('category') ||
|
||
|
e.message.toLowerCase().includes('mismatch')
|
||
|
)
|
||
|
);
|
||
|
console.log(` Tax reference errors: ${taxErrors.length}`);
|
||
|
}
|
||
|
} else if (test.shouldBeValid && validation.valid) {
|
||
|
console.log(` ✓ Correctly validated tax references`);
|
||
|
} else {
|
||
|
console.log(` ○ Unexpected result (tax reference validation may need implementation)`);
|
||
|
}
|
||
|
|
||
|
} catch (error) {
|
||
|
console.log(`${test.name}: Error - ${error.message}`);
|
||
|
}
|
||
|
}
|
||
|
});
|
||
|
|
||
|
tap.test('VAL-06: Payment Terms Reference Validation - should validate payment terms consistency', async () => {
|
||
|
const { EInvoice } = await import('../../../ts/index.js');
|
||
|
|
||
|
const paymentTermsTests = [
|
||
|
{
|
||
|
name: 'Consistent payment terms',
|
||
|
xml: `<?xml version="1.0"?>
|
||
|
<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:ID>PAY-TERMS-001</cbc:ID>
|
||
|
<cbc:IssueDate>2024-01-01</cbc:IssueDate>
|
||
|
<cbc:DueDate>2024-01-31</cbc:DueDate>
|
||
|
<cac:PaymentTerms>
|
||
|
<cbc:Note>Payment due within 30 days</cbc:Note>
|
||
|
</cac:PaymentTerms>
|
||
|
<cac:PaymentMeans>
|
||
|
<cbc:PaymentMeansCode>58</cbc:PaymentMeansCode>
|
||
|
<cac:PayeeFinancialAccount>
|
||
|
<cbc:ID>DE89370400440532013000</cbc:ID>
|
||
|
</cac:PayeeFinancialAccount>
|
||
|
</cac:PaymentMeans>
|
||
|
</Invoice>`,
|
||
|
shouldBeValid: true,
|
||
|
description: 'Due date matches payment terms (30 days)'
|
||
|
},
|
||
|
{
|
||
|
name: 'Inconsistent payment terms',
|
||
|
xml: `<?xml version="1.0"?>
|
||
|
<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:ID>PAY-TERMS-002</cbc:ID>
|
||
|
<cbc:IssueDate>2024-01-01</cbc:IssueDate>
|
||
|
<cbc:DueDate>2024-02-15</cbc:DueDate>
|
||
|
<cac:PaymentTerms>
|
||
|
<cbc:Note>Payment due within 14 days</cbc:Note>
|
||
|
</cac:PaymentTerms>
|
||
|
</Invoice>`,
|
||
|
shouldBeValid: false,
|
||
|
description: 'Due date (45 days) does not match payment terms (14 days)'
|
||
|
}
|
||
|
];
|
||
|
|
||
|
for (const test of paymentTermsTests) {
|
||
|
try {
|
||
|
const { result: validation } = await PerformanceTracker.track(
|
||
|
'payment-terms-test',
|
||
|
async () => {
|
||
|
const einvoice = await EInvoice.fromXml(test.xml);
|
||
|
return await einvoice.validate();
|
||
|
}
|
||
|
);
|
||
|
|
||
|
console.log(`${test.name}: ${validation.valid ? 'VALID' : 'INVALID'}`);
|
||
|
console.log(` ${test.description}`);
|
||
|
|
||
|
if (!test.shouldBeValid && !validation.valid) {
|
||
|
console.log(` ✓ Correctly detected payment terms inconsistency`);
|
||
|
if (validation.errors) {
|
||
|
const paymentErrors = validation.errors.filter(e =>
|
||
|
e.message && (
|
||
|
e.message.toLowerCase().includes('payment') ||
|
||
|
e.message.toLowerCase().includes('due') ||
|
||
|
e.message.toLowerCase().includes('terms')
|
||
|
)
|
||
|
);
|
||
|
console.log(` Payment terms errors: ${paymentErrors.length}`);
|
||
|
}
|
||
|
} else if (test.shouldBeValid && validation.valid) {
|
||
|
console.log(` ✓ Correctly validated payment terms`);
|
||
|
} else {
|
||
|
console.log(` ○ Unexpected result (payment terms validation may need implementation)`);
|
||
|
}
|
||
|
|
||
|
} catch (error) {
|
||
|
console.log(`${test.name}: Error - ${error.message}`);
|
||
|
}
|
||
|
}
|
||
|
});
|
||
|
|
||
|
tap.test('VAL-06: Document Reference Validation - should validate document references and IDs', async () => {
|
||
|
const { EInvoice } = await import('../../../ts/index.js');
|
||
|
|
||
|
const documentReferenceTests = [
|
||
|
{
|
||
|
name: 'Valid document references',
|
||
|
xml: `<?xml version="1.0"?>
|
||
|
<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:ID>DOC-REF-001</cbc:ID>
|
||
|
<cac:OrderReference>
|
||
|
<cbc:ID>PO-2024-001</cbc:ID>
|
||
|
</cac:OrderReference>
|
||
|
<cac:ContractDocumentReference>
|
||
|
<cbc:ID>CONTRACT-2024-001</cbc:ID>
|
||
|
</cac:ContractDocumentReference>
|
||
|
<cac:AdditionalDocumentReference>
|
||
|
<cbc:ID>DELIVERY-NOTE-001</cbc:ID>
|
||
|
<cbc:DocumentTypeCode>130</cbc:DocumentTypeCode>
|
||
|
</cac:AdditionalDocumentReference>
|
||
|
</Invoice>`,
|
||
|
shouldBeValid: true,
|
||
|
description: 'Proper document references with valid IDs'
|
||
|
},
|
||
|
{
|
||
|
name: 'Empty document references',
|
||
|
xml: `<?xml version="1.0"?>
|
||
|
<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:ID>DOC-REF-002</cbc:ID>
|
||
|
<cac:OrderReference>
|
||
|
<cbc:ID></cbc:ID>
|
||
|
</cac:OrderReference>
|
||
|
<cac:AdditionalDocumentReference>
|
||
|
<!-- Missing ID -->
|
||
|
<cbc:DocumentTypeCode>130</cbc:DocumentTypeCode>
|
||
|
</cac:AdditionalDocumentReference>
|
||
|
</Invoice>`,
|
||
|
shouldBeValid: false,
|
||
|
description: 'Empty or missing document reference IDs'
|
||
|
}
|
||
|
];
|
||
|
|
||
|
for (const test of documentReferenceTests) {
|
||
|
try {
|
||
|
const { result: validation } = await PerformanceTracker.track(
|
||
|
'document-reference-test',
|
||
|
async () => {
|
||
|
const einvoice = await EInvoice.fromXml(test.xml);
|
||
|
return await einvoice.validate();
|
||
|
}
|
||
|
);
|
||
|
|
||
|
console.log(`${test.name}: ${validation.valid ? 'VALID' : 'INVALID'}`);
|
||
|
console.log(` ${test.description}`);
|
||
|
|
||
|
if (!test.shouldBeValid && !validation.valid) {
|
||
|
console.log(` ✓ Correctly detected document reference issues`);
|
||
|
if (validation.errors) {
|
||
|
const docErrors = validation.errors.filter(e =>
|
||
|
e.message && (
|
||
|
e.message.toLowerCase().includes('document') ||
|
||
|
e.message.toLowerCase().includes('reference') ||
|
||
|
e.message.toLowerCase().includes('empty')
|
||
|
)
|
||
|
);
|
||
|
console.log(` Document reference errors: ${docErrors.length}`);
|
||
|
}
|
||
|
} else if (test.shouldBeValid && validation.valid) {
|
||
|
console.log(` ✓ Correctly validated document references`);
|
||
|
} else {
|
||
|
console.log(` ○ Unexpected result (document reference validation may need implementation)`);
|
||
|
}
|
||
|
|
||
|
} catch (error) {
|
||
|
console.log(`${test.name}: Error - ${error.message}`);
|
||
|
}
|
||
|
}
|
||
|
});
|
||
|
|
||
|
tap.start();
|