- Fixed UTF-8 encoding test (ENC-01) to accept multiple encoding declarations - Fixed UTF-16 encoding test (ENC-02) by rewriting with correct API usage - Fixed ISO-8859-1 encoding test (ENC-03) with proper address fields and methods - All three encoding tests now pass successfully - Updated edge-cases tests (EDGE-02 through EDGE-07) with new test structure
566 lines
19 KiB
TypeScript
566 lines
19 KiB
TypeScript
import { tap, expect } from '@git.zone/tstest/tapbundle';
|
|
import { EInvoice } from '../../../ts/index.js';
|
|
|
|
tap.test('EDGE-10: Time Zone Edge Cases - should handle complex timezone scenarios', async () => {
|
|
console.log('Testing timezone edge cases...\n');
|
|
|
|
// Test 1: Various date/time formats in UBL
|
|
const testUblDateFormats = async () => {
|
|
const dateFormats = [
|
|
{
|
|
name: 'UTC with Z',
|
|
xml: `<?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:ID>TZ-001</cbc:ID>
|
|
<cbc:IssueDate>2025-01-25</cbc:IssueDate>
|
|
<cbc:IssueTime>14:30:00Z</cbc:IssueTime>
|
|
<cbc:InvoiceTypeCode>380</cbc:InvoiceTypeCode>
|
|
<cbc:DocumentCurrencyCode>EUR</cbc:DocumentCurrencyCode>
|
|
<cac:AccountingSupplierParty>
|
|
<cac:Party>
|
|
<cac:PartyName>
|
|
<cbc:Name>Timezone Test Supplier</cbc:Name>
|
|
</cac:PartyName>
|
|
<cac:PostalAddress>
|
|
<cbc:StreetName>Test Street</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>Customer</cbc:Name>
|
|
</cac:PartyName>
|
|
<cac:PostalAddress>
|
|
<cbc:StreetName>Customer Street</cbc:StreetName>
|
|
<cbc:CityName>Customer City</cbc:CityName>
|
|
<cbc:PostalZone>54321</cbc:PostalZone>
|
|
<cac:Country>
|
|
<cbc:IdentificationCode>DE</cbc:IdentificationCode>
|
|
</cac:Country>
|
|
</cac:PostalAddress>
|
|
</cac:Party>
|
|
</cac:AccountingCustomerParty>
|
|
<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 Item</cbc:Name>
|
|
</cac:Item>
|
|
</cac:InvoiceLine>
|
|
</Invoice>`,
|
|
expectedTime: '14:30:00Z'
|
|
},
|
|
{
|
|
name: 'UTC with +00:00',
|
|
xml: `<?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:ID>TZ-002</cbc:ID>
|
|
<cbc:IssueDate>2025-01-25</cbc:IssueDate>
|
|
<cbc:IssueTime>14:30:00+00:00</cbc:IssueTime>
|
|
<cbc:InvoiceTypeCode>380</cbc:InvoiceTypeCode>
|
|
<cbc:DocumentCurrencyCode>EUR</cbc:DocumentCurrencyCode>
|
|
<cac:AccountingSupplierParty>
|
|
<cac:Party>
|
|
<cac:PartyName>
|
|
<cbc:Name>Timezone Test Supplier</cbc:Name>
|
|
</cac:PartyName>
|
|
<cac:PostalAddress>
|
|
<cbc:StreetName>Test Street</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>Customer</cbc:Name>
|
|
</cac:PartyName>
|
|
<cac:PostalAddress>
|
|
<cbc:StreetName>Customer Street</cbc:StreetName>
|
|
<cbc:CityName>Customer City</cbc:CityName>
|
|
<cbc:PostalZone>54321</cbc:PostalZone>
|
|
<cac:Country>
|
|
<cbc:IdentificationCode>DE</cbc:IdentificationCode>
|
|
</cac:Country>
|
|
</cac:PostalAddress>
|
|
</cac:Party>
|
|
</cac:AccountingCustomerParty>
|
|
<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 Item</cbc:Name>
|
|
</cac:Item>
|
|
</cac:InvoiceLine>
|
|
</Invoice>`,
|
|
expectedTime: '14:30:00+00:00'
|
|
},
|
|
{
|
|
name: 'Positive timezone offset',
|
|
xml: `<?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:ID>TZ-003</cbc:ID>
|
|
<cbc:IssueDate>2025-01-25</cbc:IssueDate>
|
|
<cbc:IssueTime>20:30:00+08:00</cbc:IssueTime>
|
|
<cbc:InvoiceTypeCode>380</cbc:InvoiceTypeCode>
|
|
<cbc:DocumentCurrencyCode>EUR</cbc:DocumentCurrencyCode>
|
|
<cac:AccountingSupplierParty>
|
|
<cac:Party>
|
|
<cac:PartyName>
|
|
<cbc:Name>Timezone Test Supplier</cbc:Name>
|
|
</cac:PartyName>
|
|
<cac:PostalAddress>
|
|
<cbc:StreetName>Test Street</cbc:StreetName>
|
|
<cbc:CityName>Test City</cbc:CityName>
|
|
<cbc:PostalZone>12345</cbc:PostalZone>
|
|
<cac:Country>
|
|
<cbc:IdentificationCode>SG</cbc:IdentificationCode>
|
|
</cac:Country>
|
|
</cac:PostalAddress>
|
|
</cac:Party>
|
|
</cac:AccountingSupplierParty>
|
|
<cac:AccountingCustomerParty>
|
|
<cac:Party>
|
|
<cac:PartyName>
|
|
<cbc:Name>Customer</cbc:Name>
|
|
</cac:PartyName>
|
|
<cac:PostalAddress>
|
|
<cbc:StreetName>Customer Street</cbc:StreetName>
|
|
<cbc:CityName>Customer City</cbc:CityName>
|
|
<cbc:PostalZone>54321</cbc:PostalZone>
|
|
<cac:Country>
|
|
<cbc:IdentificationCode>DE</cbc:IdentificationCode>
|
|
</cac:Country>
|
|
</cac:PostalAddress>
|
|
</cac:Party>
|
|
</cac:AccountingCustomerParty>
|
|
<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 Item</cbc:Name>
|
|
</cac:Item>
|
|
</cac:InvoiceLine>
|
|
</Invoice>`,
|
|
expectedTime: '20:30:00+08:00'
|
|
}
|
|
];
|
|
|
|
const results = [];
|
|
for (const test of dateFormats) {
|
|
try {
|
|
const einvoice = await EInvoice.fromXml(test.xml);
|
|
results.push({
|
|
name: test.name,
|
|
parsed: true,
|
|
hasDate: !!einvoice.date,
|
|
invoiceId: einvoice.id,
|
|
format: einvoice.getFormat()
|
|
});
|
|
} catch (error) {
|
|
results.push({
|
|
name: test.name,
|
|
parsed: false,
|
|
error: error.message
|
|
});
|
|
}
|
|
}
|
|
|
|
return results;
|
|
};
|
|
|
|
const ublDateResults = await testUblDateFormats();
|
|
console.log('Test 1 - UBL date/time formats:');
|
|
ublDateResults.forEach(result => {
|
|
console.log(` ${result.name}: ${result.parsed ? `Parsed (${result.invoiceId})` : 'Failed'}`);
|
|
});
|
|
expect(ublDateResults.every(r => r.parsed)).toEqual(true);
|
|
|
|
// Test 2: Date edge cases
|
|
const testDateEdgeCases = async () => {
|
|
const edgeCases = [
|
|
{
|
|
name: 'Leap year date',
|
|
date: '2024-02-29',
|
|
description: 'February 29th in leap year'
|
|
},
|
|
{
|
|
name: 'Year boundary',
|
|
date: '2024-12-31',
|
|
description: 'Last day of year'
|
|
},
|
|
{
|
|
name: 'DST transition',
|
|
date: '2025-03-30',
|
|
description: 'Daylight saving time transition date'
|
|
},
|
|
{
|
|
name: 'Far future date',
|
|
date: '2099-12-31',
|
|
description: 'Date far in the future'
|
|
}
|
|
];
|
|
|
|
const results = [];
|
|
for (const testCase of edgeCases) {
|
|
const xml = `<?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:ID>DATE-EDGE-${testCase.name.toUpperCase().replace(/\s+/g, '-')}</cbc:ID>
|
|
<cbc:IssueDate>${testCase.date}</cbc:IssueDate>
|
|
<cbc:InvoiceTypeCode>380</cbc:InvoiceTypeCode>
|
|
<cbc:DocumentCurrencyCode>EUR</cbc:DocumentCurrencyCode>
|
|
<cac:AccountingSupplierParty>
|
|
<cac:Party>
|
|
<cac:PartyName>
|
|
<cbc:Name>Date Test Supplier</cbc:Name>
|
|
</cac:PartyName>
|
|
<cac:PostalAddress>
|
|
<cbc:StreetName>Test Street</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>Customer</cbc:Name>
|
|
</cac:PartyName>
|
|
<cac:PostalAddress>
|
|
<cbc:StreetName>Customer Street</cbc:StreetName>
|
|
<cbc:CityName>Customer City</cbc:CityName>
|
|
<cbc:PostalZone>54321</cbc:PostalZone>
|
|
<cac:Country>
|
|
<cbc:IdentificationCode>DE</cbc:IdentificationCode>
|
|
</cac:Country>
|
|
</cac:PostalAddress>
|
|
</cac:Party>
|
|
</cac:AccountingCustomerParty>
|
|
<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 Item</cbc:Name>
|
|
</cac:Item>
|
|
</cac:InvoiceLine>
|
|
</Invoice>`;
|
|
|
|
try {
|
|
const einvoice = await EInvoice.fromXml(xml);
|
|
const dateValid = einvoice.date && !isNaN(einvoice.date);
|
|
results.push({
|
|
name: testCase.name,
|
|
parsed: true,
|
|
dateValid,
|
|
date: new Date(einvoice.date).toISOString()
|
|
});
|
|
} catch (error) {
|
|
results.push({
|
|
name: testCase.name,
|
|
parsed: false,
|
|
error: error.message
|
|
});
|
|
}
|
|
}
|
|
|
|
return results;
|
|
};
|
|
|
|
const dateEdgeResults = await testDateEdgeCases();
|
|
console.log('\nTest 2 - Date edge cases:');
|
|
dateEdgeResults.forEach(result => {
|
|
console.log(` ${result.name}: ${result.parsed ? `Valid (${result.date})` : 'Failed'}`);
|
|
});
|
|
expect(dateEdgeResults.every(r => r.parsed && r.dateValid)).toEqual(true);
|
|
|
|
// Test 3: Invalid date formats
|
|
const testInvalidDateFormats = async () => {
|
|
const invalidFormats = [
|
|
{
|
|
name: 'Invalid date',
|
|
date: '2025-02-30',
|
|
description: 'February 30th does not exist'
|
|
},
|
|
{
|
|
name: 'Wrong format',
|
|
date: '25/01/2025',
|
|
description: 'DD/MM/YYYY instead of YYYY-MM-DD'
|
|
},
|
|
{
|
|
name: 'Incomplete date',
|
|
date: '2025-01',
|
|
description: 'Missing day'
|
|
},
|
|
{
|
|
name: 'Text date',
|
|
date: 'January 25, 2025',
|
|
description: 'Text format instead of ISO'
|
|
}
|
|
];
|
|
|
|
const results = [];
|
|
for (const testCase of invalidFormats) {
|
|
const xml = `<?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:ID>INVALID-DATE-${testCase.name.toUpperCase().replace(/\s+/g, '-')}</cbc:ID>
|
|
<cbc:IssueDate>${testCase.date}</cbc:IssueDate>
|
|
<cbc:InvoiceTypeCode>380</cbc:InvoiceTypeCode>
|
|
<cbc:DocumentCurrencyCode>EUR</cbc:DocumentCurrencyCode>
|
|
<cac:AccountingSupplierParty>
|
|
<cac:Party>
|
|
<cac:PartyName>
|
|
<cbc:Name>Date Test Supplier</cbc:Name>
|
|
</cac:PartyName>
|
|
<cac:PostalAddress>
|
|
<cbc:StreetName>Test Street</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>Customer</cbc:Name>
|
|
</cac:PartyName>
|
|
<cac:PostalAddress>
|
|
<cbc:StreetName>Customer Street</cbc:StreetName>
|
|
<cbc:CityName>Customer City</cbc:CityName>
|
|
<cbc:PostalZone>54321</cbc:PostalZone>
|
|
<cac:Country>
|
|
<cbc:IdentificationCode>DE</cbc:IdentificationCode>
|
|
</cac:Country>
|
|
</cac:PostalAddress>
|
|
</cac:Party>
|
|
</cac:AccountingCustomerParty>
|
|
<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 Item</cbc:Name>
|
|
</cac:Item>
|
|
</cac:InvoiceLine>
|
|
</Invoice>`;
|
|
|
|
try {
|
|
const einvoice = await EInvoice.fromXml(xml);
|
|
// Check if date was parsed or set to current date as fallback
|
|
const dateSet = einvoice.date > 0;
|
|
results.push({
|
|
name: testCase.name,
|
|
handled: true,
|
|
dateSet,
|
|
invoiceId: einvoice.id
|
|
});
|
|
} catch (error) {
|
|
results.push({
|
|
name: testCase.name,
|
|
handled: false,
|
|
errorInformative: error.message.includes('date') ||
|
|
error.message.includes('Date') ||
|
|
error.message.includes('validation')
|
|
});
|
|
}
|
|
}
|
|
|
|
return results;
|
|
};
|
|
|
|
const invalidDateResults = await testInvalidDateFormats();
|
|
console.log('\nTest 3 - Invalid date formats:');
|
|
invalidDateResults.forEach(result => {
|
|
console.log(` ${result.name}: ${result.handled ? 'Handled gracefully' : 'Failed'} ${result.errorInformative ? '[Informative error]' : ''}`);
|
|
});
|
|
expect(invalidDateResults.every(r => r.handled || r.errorInformative)).toEqual(true);
|
|
|
|
// Test 4: CII date formats
|
|
const testCiiDateFormats = async () => {
|
|
const ciiXml = `<?xml version="1.0" encoding="UTF-8"?>
|
|
<rsm:CrossIndustryInvoice xmlns:rsm="urn:un:unece:uncefact:data:standard:CrossIndustryInvoice:100"
|
|
xmlns:ram="urn:un:unece:uncefact:data:standard:ReusableAggregateBusinessInformationEntity:100"
|
|
xmlns:udt="urn:un:unece:uncefact:data:standard:UnqualifiedDataType:100">
|
|
<rsm:ExchangedDocumentContext>
|
|
<ram:GuidelineSpecifiedDocumentContextParameter>
|
|
<ram:ID>urn:cen.eu:en16931:2017</ram:ID>
|
|
</ram:GuidelineSpecifiedDocumentContextParameter>
|
|
</rsm:ExchangedDocumentContext>
|
|
<rsm:ExchangedDocument>
|
|
<ram:ID>CII-TZ-001</ram:ID>
|
|
<ram:TypeCode>380</ram:TypeCode>
|
|
<ram:IssueDateTime>
|
|
<udt:DateTimeString format="102">20250125</udt:DateTimeString>
|
|
</ram:IssueDateTime>
|
|
</rsm:ExchangedDocument>
|
|
<rsm:SupplyChainTradeTransaction>
|
|
<ram:ApplicableHeaderTradeAgreement>
|
|
<ram:SellerTradeParty>
|
|
<ram:Name>CII Timezone Supplier</ram:Name>
|
|
<ram:PostalTradeAddress>
|
|
<ram:LineOne>Test Street 1</ram:LineOne>
|
|
<ram:CityName>Test City</ram:CityName>
|
|
<ram:PostcodeCode>12345</ram:PostcodeCode>
|
|
<ram:CountryID>DE</ram:CountryID>
|
|
</ram:PostalTradeAddress>
|
|
</ram:SellerTradeParty>
|
|
<ram:BuyerTradeParty>
|
|
<ram:Name>CII Customer</ram:Name>
|
|
<ram:PostalTradeAddress>
|
|
<ram:LineOne>Customer Street 2</ram:LineOne>
|
|
<ram:CityName>Customer City</ram:CityName>
|
|
<ram:PostcodeCode>54321</ram:PostcodeCode>
|
|
<ram:CountryID>DE</ram:CountryID>
|
|
</ram:PostalTradeAddress>
|
|
</ram:BuyerTradeParty>
|
|
</ram:ApplicableHeaderTradeAgreement>
|
|
<ram:ApplicableHeaderTradeSettlement>
|
|
<ram:InvoiceCurrencyCode>EUR</ram:InvoiceCurrencyCode>
|
|
</ram:ApplicableHeaderTradeSettlement>
|
|
</rsm:SupplyChainTradeTransaction>
|
|
</rsm:CrossIndustryInvoice>`;
|
|
|
|
try {
|
|
const einvoice = await EInvoice.fromXml(ciiXml);
|
|
return {
|
|
parsed: true,
|
|
format: einvoice.getFormat(),
|
|
hasDate: !!einvoice.date,
|
|
invoiceId: einvoice.id
|
|
};
|
|
} catch (error) {
|
|
return {
|
|
parsed: false,
|
|
error: error.message
|
|
};
|
|
}
|
|
};
|
|
|
|
const ciiResult = await testCiiDateFormats();
|
|
console.log('\nTest 4 - CII date format:');
|
|
console.log(` CII with format 102: ${ciiResult.parsed ? `Parsed (${ciiResult.invoiceId})` : 'Failed'}`);
|
|
expect(ciiResult.parsed).toEqual(true);
|
|
|
|
// Test 5: Different timezone representations
|
|
const testTimezoneRepresentations = async () => {
|
|
const timezones = [
|
|
{ tz: '-11:00', name: 'Extreme negative offset' },
|
|
{ tz: '-05:00', name: 'EST' },
|
|
{ tz: '+01:00', name: 'CET' },
|
|
{ tz: '+05:30', name: 'IST (half hour offset)' },
|
|
{ tz: '+13:00', name: 'Extreme positive offset' },
|
|
{ tz: '+14:00', name: 'Maximum positive offset' }
|
|
];
|
|
|
|
const results = [];
|
|
for (const { tz, name } of timezones) {
|
|
const xml = `<?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:ID>TZ-${tz.replace(/[+:-]/g, '')}</cbc:ID>
|
|
<cbc:IssueDate>2025-01-25</cbc:IssueDate>
|
|
<cbc:IssueTime>12:00:00${tz}</cbc:IssueTime>
|
|
<cbc:InvoiceTypeCode>380</cbc:InvoiceTypeCode>
|
|
<cbc:DocumentCurrencyCode>EUR</cbc:DocumentCurrencyCode>
|
|
<cac:AccountingSupplierParty>
|
|
<cac:Party>
|
|
<cac:PartyName>
|
|
<cbc:Name>TZ Test Supplier</cbc:Name>
|
|
</cac:PartyName>
|
|
<cac:PostalAddress>
|
|
<cbc:StreetName>Test Street</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>Customer</cbc:Name>
|
|
</cac:PartyName>
|
|
<cac:PostalAddress>
|
|
<cbc:StreetName>Customer Street</cbc:StreetName>
|
|
<cbc:CityName>Customer City</cbc:CityName>
|
|
<cbc:PostalZone>54321</cbc:PostalZone>
|
|
<cac:Country>
|
|
<cbc:IdentificationCode>DE</cbc:IdentificationCode>
|
|
</cac:Country>
|
|
</cac:PostalAddress>
|
|
</cac:Party>
|
|
</cac:AccountingCustomerParty>
|
|
<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 Item</cbc:Name>
|
|
</cac:Item>
|
|
</cac:InvoiceLine>
|
|
</Invoice>`;
|
|
|
|
try {
|
|
const einvoice = await EInvoice.fromXml(xml);
|
|
results.push({
|
|
timezone: tz,
|
|
name,
|
|
parsed: true,
|
|
hasDate: !!einvoice.date
|
|
});
|
|
} catch (error) {
|
|
results.push({
|
|
timezone: tz,
|
|
name,
|
|
parsed: false,
|
|
error: error.message
|
|
});
|
|
}
|
|
}
|
|
|
|
return results;
|
|
};
|
|
|
|
const timezoneResults = await testTimezoneRepresentations();
|
|
console.log('\nTest 5 - Timezone representations:');
|
|
timezoneResults.forEach(result => {
|
|
console.log(` ${result.name} (${result.timezone}): ${result.parsed ? 'Parsed' : 'Failed'}`);
|
|
});
|
|
expect(timezoneResults.every(r => r.parsed)).toEqual(true);
|
|
|
|
console.log('\n✓ All timezone edge cases handled appropriately');
|
|
});
|
|
|
|
tap.start(); |