import assert from "node:assert/strict" import { Readable } from "node:stream" import test from "node:test" import { PDFDocument, PDFPage } from "pdf-lib" import { createInvoicePDF } from "../src/utils/pdf" import { initS3, s3 } from "../src/utils/s3" const createDocumentData = (type: string) => { const item = (pos: string) => ({ mode: "normal", pos, text: `Artikel ${pos}`, quantity: "1", unit: "Stk", taxPercent: 19, price: "25,00 €", rowAmount: "25,00 €", }) return { type, adressLine: "Musterfirma, Musterweg 1, 12345 Musterstadt", recipient: ["Musterkunde"], info: [], title: type === "packingSlips" ? "Packschein" : type === "deliveryNotes" ? "Lieferschein" : "Rechnung", description: "Abschnitte mit Seitenumbruch", startText: "Ihre Artikel:", endText: "Vielen Dank.", rows: [ { mode: "title", pos: "1", text: "Abschnitt A" }, item("1.1"), { mode: "title", pos: "2", text: "Abschnitt B" }, item("2.1"), { mode: "pagebreak" }, { mode: "title", pos: "3", text: "Abschnitt C" }, item("3.1"), ], total: { titleSums: { "1 - Abschnitt A": "25,00 €", "2 - Abschnitt B": "25,00 €", "3 - Abschnitt C": "25,00 €", }, titleSumsTransfer: { "2 - Abschnitt B": "25,00 €", "3 - Abschnitt C": "50,00 €", }, }, totalArray: [{ label: "Nettobetrag", content: "75,00 €" }], } } for (const type of ["packingSlips", "deliveryNotes", "invoices"]) { test(`${type}: renders transfers only for priced documents, including before page breaks`, async t => { const background = await PDFDocument.create() background.addPage().drawText("Musterfirma", { x: 60, y: 800, size: 12 }) const backgroundBytes = await background.save() await initS3() t.mock.method(s3, "send", async () => ({ Body: Readable.from([backgroundBytes]) })) const drawText = t.mock.method(PDFPage.prototype, "drawText") const result = await createInvoicePDF(null, "base64", createDocumentData(type), "test-letterhead.pdf") assert.equal(result?.mimeType, "application/pdf") const pdf = await PDFDocument.load(Buffer.from(result!.base64, "base64")) assert.equal(pdf.getPageCount(), 2) const texts = drawText.mock.calls.map(call => call.arguments[0]) for (const text of ["Abschnitt A", "Abschnitt B", "Abschnitt C", "Artikel 1.1", "Artikel 2.1", "Artikel 3.1"]) { assert.ok(texts.includes(text), `Missing document content: ${text}`) } assert.equal(texts.filter(text => text === "1 Stk").length, 3) assert.equal(texts.filter(text => text === "Check").length, type === "packingSlips" ? 2 : 0) const transfers = texts.filter(text => text.startsWith("Übertrag:")) if (type === "invoices") { assert.deepEqual(transfers, ["Übertrag: 25,00 €", "Übertrag: 50,00 €"]) assert.ok(texts.includes("75,00 €")) assert.equal(texts.filter(text => text === "Einheitspreis").length, 2) } else { assert.deepEqual(transfers, []) assert.ok(texts.every(text => !text.includes("€")), "Delivery documents must not display monetary amounts") for (const label of ["Steuer", "Einheitspreis", "Gesamt", "Nettobetrag"]) { assert.ok(!texts.includes(label), `Unexpected price label: ${label}`) } } }) }