import { tap, expect } from '@push.rocks/tapbundle'; import * as getInvoices from './assets/getasset.js'; import { XInvoiceEncoder, XInvoiceDecoder } from '../ts/index.js'; import * as tsclass from '@tsclass/tsclass'; // Sample test letter data from our test assets const testLetterData = getInvoices.letterObjects.letter1.demoLetter; // Test for XInvoice/XRechnung XML format tap.test('Generate XInvoice XML from letter data', async () => { // Create the encoder const encoder = new XInvoiceEncoder(); // Generate XInvoice XML const xml = encoder.createXInvoiceXml(testLetterData); // Verify the XML was created properly expect(xml).toBeTypeOf('string'); expect(xml.length).toBeGreaterThan(100); // Check for UBL/XInvoice structure expect(xml).toInclude('oasis:names:specification:ubl'); expect(xml).toInclude('Invoice'); expect(xml).toInclude('cbc:ID'); expect(xml).toInclude(testLetterData.content.invoiceData.id); // Check for mandatory XRechnung elements expect(xml).toInclude('CustomizationID'); expect(xml).toInclude('xrechnung'); expect(xml).toInclude('cbc:UBLVersionID'); console.log('Successfully generated XInvoice XML'); }); // Test for special handling of credit notes tap.test('Generate XInvoice credit note XML', async () => { // Create a modified version of the test letter - change type to credit note const creditNoteLetter = {...testLetterData}; creditNoteLetter.content = {...testLetterData.content}; creditNoteLetter.content.invoiceData = {...testLetterData.content.invoiceData}; creditNoteLetter.content.invoiceData.type = 'creditnote'; creditNoteLetter.content.invoiceData.id = 'CN-' + testLetterData.content.invoiceData.id; // Create encoder const encoder = new XInvoiceEncoder(); // Generate XML for credit note const xml = encoder.createXInvoiceXml(creditNoteLetter); // Check that it's a credit note (type code 381) expect(xml).toInclude('cbc:InvoiceTypeCode'); expect(xml).toInclude('381'); expect(xml).toInclude(creditNoteLetter.content.invoiceData.id); console.log('Successfully generated XInvoice credit note XML'); }); // Test decoding XInvoice XML tap.test('Decode XInvoice XML to structured data', async () => { // First, create XML to test with const encoder = new XInvoiceEncoder(); const xml = encoder.createXInvoiceXml(testLetterData); // Create the decoder const decoder = new XInvoiceDecoder(xml); // Decode back to structured data const decodedLetter = await decoder.getLetterData(); // Verify we got a letter back expect(decodedLetter).toBeTypeOf('object'); expect(decodedLetter.content?.invoiceData).toBeDefined(); // Check that essential information was extracted expect(decodedLetter.content?.invoiceData?.id).toBeDefined(); expect(decodedLetter.content?.invoiceData?.billedBy).toBeDefined(); expect(decodedLetter.content?.invoiceData?.billedTo).toBeDefined(); console.log('Successfully decoded XInvoice XML'); }); // Test namespace handling for UBL tap.test('Handle UBL namespaces correctly', async () => { // Create valid UBL XML with namespaces const ublXml = ` 2.1 ${testLetterData.content.invoiceData.id} 2023-12-31 380 EUR ${testLetterData.content.invoiceData.billedBy.name} ${testLetterData.content.invoiceData.billedTo.name} `; // Create decoder for the UBL XML const decoder = new XInvoiceDecoder(ublXml); // Extract the data const decodedLetter = await decoder.getLetterData(); // Verify extraction worked with namespaces expect(decodedLetter.content?.invoiceData?.id).toBeDefined(); expect(decodedLetter.content?.invoiceData?.billedBy.name).toBeDefined(); console.log('Successfully handled UBL namespaces'); }); // Test extraction of invoice items tap.test('Extract invoice items from XInvoice XML', async () => { // Create an invoice with items const encoder = new XInvoiceEncoder(); const xml = encoder.createXInvoiceXml(testLetterData); // Decode the XML const decoder = new XInvoiceDecoder(xml); const decodedLetter = await decoder.getLetterData(); // Verify items were extracted expect(decodedLetter.content?.invoiceData?.items).toBeDefined(); if (decodedLetter.content?.invoiceData?.items) { // At least one item should be extracted expect(decodedLetter.content.invoiceData.items.length).toBeGreaterThan(0); // Check first item has needed properties const firstItem = decodedLetter.content.invoiceData.items[0]; expect(firstItem.name).toBeDefined(); expect(firstItem.unitQuantity).toBeDefined(); expect(firstItem.unitNetPrice).toBeDefined(); } console.log('Successfully extracted invoice items'); }); // Start the test suite tap.start();