import { tap, expect } from '@push.rocks/tapbundle'; import * as fs from 'fs/promises'; import * as xinvoice from '../ts/index.js'; import * as getInvoices from './assets/getasset.js'; import { ZugferdXmlEncoder } from '../ts/classes.encoder.js'; import { ZUGFeRDXmlDecoder } from '../ts/classes.decoder.js'; // Group 1: Basic functionality tests for XInvoice class tap.test('XInvoice should initialize correctly', async () => { const xInvoice = new xinvoice.XInvoice(); expect(xInvoice).toBeTypeOf('object'); expect(xInvoice.addPdfBuffer).toBeTypeOf('function'); expect(xInvoice.addXmlString).toBeTypeOf('function'); expect(xInvoice.addLetterData).toBeTypeOf('function'); expect(xInvoice.getXInvoice).toBeTypeOf('function'); expect(xInvoice.getXmlData).toBeTypeOf('function'); expect(xInvoice.getParsedXmlData).toBeTypeOf('function'); }); // Group 2: XML validation test const basicXmlTest = tap.test('XInvoice should handle XML strings correctly', async () => { // Setup the XInvoice instance const xInvoice = new xinvoice.XInvoice(); // Create test XML string const xmlString = 'Test Invoice'; // Add XML string directly (no PDF needed) await xInvoice.addXmlString(xmlString); // Return the XML string for the next test return xmlString; }); // Group 3: XML parsing test tap.test('XInvoice should parse XML into structured data', async () => { const xmlResult = await basicXmlTest.testResultPromise as string; // Setup a new XInvoice instance const xInvoiceInstance = new xinvoice.XInvoice(); await xInvoiceInstance.addXmlString(xmlResult); // Parse the XML const parsedXml = await xInvoiceInstance.getParsedXmlData(); // Validate the parsed data structure expect(parsedXml).toBeTypeOf('object'); expect(parsedXml).toHaveProperty('InvoiceNumber'); expect(parsedXml).toHaveProperty('DateIssued'); expect(parsedXml).toHaveProperty('Seller'); expect(parsedXml).toHaveProperty('Buyer'); expect(parsedXml).toHaveProperty('Items'); expect(parsedXml).toHaveProperty('TotalAmount'); // Validate the structure of nested objects expect(parsedXml.Seller).toHaveProperty('Name'); expect(parsedXml.Seller).toHaveProperty('Address'); expect(parsedXml.Seller).toHaveProperty('Contact'); expect(parsedXml.Buyer).toHaveProperty('Name'); expect(parsedXml.Buyer).toHaveProperty('Address'); expect(parsedXml.Buyer).toHaveProperty('Contact'); // Validate Items is an array expect(parsedXml.Items).toBeTypeOf('object'); expect(Array.isArray(parsedXml.Items)).toEqual(true); if (parsedXml.Items.length > 0) { expect(parsedXml.Items[0]).toHaveProperty('Description'); expect(parsedXml.Items[0]).toHaveProperty('Quantity'); expect(parsedXml.Items[0]).toHaveProperty('UnitPrice'); expect(parsedXml.Items[0]).toHaveProperty('TotalPrice'); } }); // Group 4: XML and LetterData handling test tap.test('XInvoice should correctly handle XML and LetterData', async () => { // Setup the XInvoice instance const xInvoice = new xinvoice.XInvoice(); // Create test XML data const xmlString = 'Test XML data'; const letterData = getInvoices.letterObjects.letter1.demoLetter; // Add data to the XInvoice instance await xInvoice.addXmlString(xmlString); await xInvoice.addLetterData(letterData); // Check the data was properly stored expect(xInvoice['xmlString']).toEqual(xmlString); expect(xInvoice['letterData']).toEqual(letterData); }); // Group 5: Basic encoder test tap.test('ZugferdXmlEncoder instance should be created', async () => { const encoder = new ZugferdXmlEncoder(); expect(encoder).toBeTypeOf('object'); // Testing the existence of the method without calling it expect(encoder.createZugferdXml).toBeTypeOf('function'); }); // Group 6: Basic decoder test tap.test('ZUGFeRDXmlDecoder should be created correctly', async () => { // Create a simple XML to test with const simpleXml = 'Test Invoice'; // Create decoder instance const decoder = new ZUGFeRDXmlDecoder(simpleXml); // Check that the decoder is created correctly expect(decoder).toBeTypeOf('object'); expect(decoder.getLetterData).toBeTypeOf('function'); }); // Group 7: Error handling tests tap.test('XInvoice should throw errors for missing data', async () => { const xInvoice = new xinvoice.XInvoice(); // Test missing PDF buffer try { await xInvoice.getXmlData(); tap.fail('Should have thrown an error for missing PDF buffer'); } catch (error) { expect(error).toBeTypeOf('object'); expect(error instanceof Error).toEqual(true); } // Test missing XML string and letter data for embedding try { await xInvoice.addPdfBuffer(new Uint8Array(10)); await xInvoice.getXInvoice(); tap.fail('Should have thrown an error for missing XML string or letter data'); } catch (error) { expect(error).toBeTypeOf('object'); expect(error instanceof Error).toEqual(true); } // Test missing XML string for parsing try { await xInvoice.getParsedXmlData(); tap.fail('Should have thrown an error for missing XML string'); } catch (error) { expect(error).toBeTypeOf('object'); expect(error instanceof Error).toEqual(true); } }); // Group 8: Format detection test (simplified) tap.test('XInvoice should detect XML format', async () => { // Testing format identification logic directly rather than through PDF extraction // Create a sample of CII/ZUGFeRD XML const zugferdXml = ` urn:factur-x.eu:1p0:extended `; // Create a test instance and add the XML string const xInvoice = new xinvoice.XInvoice(); await xInvoice.addXmlString(zugferdXml); // Extract through the parseXmlToInvoice method const result = await xInvoice.getParsedXmlData(); // Just test we're getting the basic structure back expect(result).toBeTypeOf('object'); expect(result).toHaveProperty('InvoiceNumber'); }); tap.start(); // Run the test suite