import { expect, tap } from '@git.zone/tstest/tapbundle';
import { EInvoice } from '../../../ts/index.js';
tap.test('ENC-08: Mixed Content - should handle mixed text and element content', async () => {
console.log('Testing XML mixed content handling...\n');
// Test 1: Pure element content (structured only)
const testPureElementContent = async () => {
const einvoice = new EInvoice();
einvoice.id = 'MIXED-ELEMENT-TEST';
einvoice.issueDate = new Date(2025, 0, 25);
einvoice.subject = 'Pure element content test';
einvoice.from = {
type: 'company',
name: 'Test Company',
description: 'Testing pure element content',
address: {
streetName: 'Test Street',
houseNumber: '1',
postalCode: '12345',
city: 'Test City',
country: 'DE'
},
status: 'active',
foundedDate: { year: 2020, month: 1, day: 1 },
registrationDetails: {
vatId: 'DE123456789',
registrationId: 'HRB 12345',
registrationName: 'Commercial Register'
}
};
einvoice.to = {
type: 'person',
name: 'Test',
surname: 'Customer',
salutation: 'Mr' as const,
sex: 'male' as const,
title: 'Doctor' as const,
description: 'Test customer',
address: {
streetName: 'Customer Street',
houseNumber: '2',
postalCode: '54321',
city: 'Customer City',
country: 'DE'
}
};
einvoice.items = [{
position: 1,
name: 'Test Product',
articleNumber: 'MIXED-001',
unitType: 'EA',
unitQuantity: 1,
unitNetPrice: 100,
vatPercentage: 19
}];
// Generate XML and verify structure
const xmlString = await einvoice.toXmlString('ubl');
// Check for proper element structure without mixed content
const hasProperStructure = xmlString.includes('MIXED-ELEMENT-TEST') &&
xmlString.includes('') &&
xmlString.includes('');
// Verify round-trip works
const newInvoice = new EInvoice();
await newInvoice.fromXmlString(xmlString);
const roundTripSuccess = (newInvoice.id === 'MIXED-ELEMENT-TEST' ||
newInvoice.invoiceId === 'MIXED-ELEMENT-TEST' ||
newInvoice.accountingDocId === 'MIXED-ELEMENT-TEST');
console.log(`Test 1 - Pure element content:`);
console.log(` Proper XML structure: ${hasProperStructure ? 'Yes' : 'No'}`);
console.log(` Round-trip successful: ${roundTripSuccess ? 'Yes' : 'No'}`);
return { hasProperStructure, roundTripSuccess };
};
// Test 2: Mixed content with text and elements
const testMixedContent = async () => {
// XML with mixed content (text + elements combined)
const mixedContentXml = `
2.1
MIXED-CONTENT-TEST
2025-01-25
EUR
Company Name with Text
nested element and more text
1
This is a note with emphasis and additional text
1
Test Item
Item description with
detailed info
and more descriptive text
`;
try {
const einvoice = new EInvoice();
await einvoice.fromXmlString(mixedContentXml);
// Check if mixed content is handled appropriately
const mixedContentHandled = einvoice.from?.name !== undefined &&
einvoice.items?.[0]?.name !== undefined;
console.log(`\nTest 2 - Mixed content parsing:`);
console.log(` Mixed content XML parsed: ${mixedContentHandled ? 'Yes' : 'No'}`);
console.log(` Supplier name extracted: ${einvoice.from?.name ? 'Yes' : 'No'}`);
console.log(` Item data extracted: ${einvoice.items?.[0]?.name ? 'Yes' : 'No'}`);
return { mixedContentHandled };
} catch (error) {
console.log(`\nTest 2 - Mixed content parsing:`);
console.log(` Mixed content parsing failed: ${error.message}`);
return { mixedContentHandled: false };
}
};
// Test 3: CDATA sections with mixed content
const testCDataMixedContent = async () => {
const cdataMixedXml = `
2.1
CDATA-MIXED-TEST
2025-01-25
EUR
chars]]>
1
bold and italic text]]>
1
CDATA Test Item
markup preserved
and "special" characters & symbols
]]>
`;
try {
const einvoice = new EInvoice();
await einvoice.fromXmlString(cdataMixedXml);
const cdataHandled = einvoice.from?.name?.includes('&') &&
einvoice.from?.name?.includes('<') &&
einvoice.items?.[0]?.name === 'CDATA Test Item';
console.log(`\nTest 3 - CDATA mixed content:`);
console.log(` CDATA content preserved: ${cdataHandled ? 'Yes' : 'No'}`);
console.log(` Special characters handled: ${einvoice.from?.name?.includes('&') ? 'Yes' : 'No'}`);
return { cdataHandled };
} catch (error) {
console.log(`\nTest 3 - CDATA mixed content:`);
console.log(` CDATA parsing failed: ${error.message}`);
return { cdataHandled: false };
}
};
// Test 4: Whitespace handling in mixed content
const testWhitespaceHandling = async () => {
const whitespaceXml = `
2.1
WHITESPACE-TEST
2025-01-25
EUR
Company Name
1
1
Test Item
`;
try {
const einvoice = new EInvoice();
await einvoice.fromXmlString(whitespaceXml);
// Check how whitespace is handled
const whitespacePreserved = einvoice.from?.name === ' Company Name ';
const whitespaceNormalized = einvoice.from?.name?.trim() === 'Company Name';
console.log(`\nTest 4 - Whitespace handling:`);
console.log(` Whitespace preserved: ${whitespacePreserved ? 'Yes' : 'No'}`);
console.log(` Whitespace normalized: ${whitespaceNormalized ? 'Yes' : 'No'}`);
console.log(` Company name value: "${einvoice.from?.name}"`);
return { whitespacePreserved, whitespaceNormalized };
} catch (error) {
console.log(`\nTest 4 - Whitespace handling:`);
console.log(` Whitespace test failed: ${error.message}`);
return { whitespacePreserved: false, whitespaceNormalized: false };
}
};
// Run all tests
const elementResult = await testPureElementContent();
const mixedResult = await testMixedContent();
const cdataResult = await testCDataMixedContent();
const whitespaceResult = await testWhitespaceHandling();
console.log(`\n=== XML Mixed Content Test Summary ===`);
console.log(`Pure element content: ${elementResult.hasProperStructure ? 'Working' : 'Issues'}`);
console.log(`Mixed content parsing: ${mixedResult.mixedContentHandled ? 'Working' : 'Issues'}`);
console.log(`CDATA mixed content: ${cdataResult.cdataHandled ? 'Working' : 'Issues'}`);
console.log(`Whitespace handling: ${whitespaceResult.whitespaceNormalized ? 'Working' : 'Issues'}`);
console.log(`Round-trip consistency: ${elementResult.roundTripSuccess ? 'Working' : 'Issues'}`);
// Test passes if basic element content and mixed content parsing work
expect(elementResult.hasProperStructure).toBeTrue();
expect(elementResult.roundTripSuccess).toBeTrue();
});
// Run the test
tap.start();