test(pdf): add render smoke tests for PO PDF (covers VAT totals)

Co-authored-by: Orca <help@stably.ai>
This commit is contained in:
SJCoetz 2026-08-06 12:13:52 +02:00
parent 07900075a4
commit 180288e6e3

View file

@ -0,0 +1,187 @@
import { describe, it, expect } from "vitest";
import { renderPurchaseOrderPdf } from "./render";
import type { Letterhead } from "@/lib/letterhead";
import type { Order, OrderItem, PurchaseOrder, Supplier } from "@/lib/types";
/**
* Smoke tests for the supplier-facing PO PDF renderer. We don't
* render visually — we assert the binary is a well-formed PDF
* (magic bytes, sane size) so any regression in the render pipeline
* (style typo breaking JSX, dep misconfig, etc.) trips the test
* even without eyeballing output.
*
* The VAT-line correctness is covered by `format.test.ts`
* (poSubtotal + vatAmount helpers) and by inspection during code
* review — this file guards the integration.
*/
const baseLetterhead: Letterhead = {
id: "lh1",
collectionId: "pbc_letterhead",
collectionName: "letterhead_settings",
created: "2026-08-06T00:00:00.000Z",
updated: "2026-08-06T00:00:00.000Z",
display_name: "CNL Mining Supplies",
address: "47 Station Street\nCarletonville, Gauteng 2499",
phone: "+27 18 786 2897",
email: "quotes@wfsales.co.za",
vat_number: "4840229449",
registration_number: "2014/004024/07",
bank_name: "Standard Bank - Carletonville",
bank_account_number: "Current Account\n022196552",
bank_branch_code: "016141",
terms: "Terms and Conditions:\n1. Standard terms apply.",
default_markup_percent: 30,
footer_text: "",
logo: "",
is_active: true,
company: "CNL Mining Supplies (Pty) Ltd",
accent_color: "#738224",
};
const baseSupplier: Supplier = {
id: "sup1",
collectionId: "pbc_suppliers",
collectionName: "suppliers",
created: "2026-08-06T00:00:00.000Z",
updated: "2026-08-06T00:00:00.000Z",
suppliername: "Alpha Bearings (Pty) Ltd",
suppliernumber: "+27 11 555 0123",
supplieraddress: "12 Industrial Rd\nJohannesburg, Gauteng 2000",
email: "orders@alphabearings.co.za",
supply_tags: "",
coordinates: "",
closingtime: "",
};
const baseOrder: Order = {
id: "ord1",
collectionId: "pbc_orders",
collectionName: "orders",
created: "2026-08-06T00:00:00.000Z",
updated: "2026-08-06T00:00:00.000Z",
order_number: "SO-260001",
customer: "cust1",
company: "comp1",
quote: "",
notes: "",
quote_matching_attempted: false,
quote_match_confidence: 0,
potential_quote: "",
potential_quote_confidence: 0,
is_repair_order: false,
rep: "",
invoiced: false,
quote_reference_text: "",
quote_match_method: "",
contact_name: "",
email_subject: "",
email_sender: "",
};
const basePurchaseOrder: PurchaseOrder = {
id: "po1",
collectionId: "pbc_purchase_orders",
collectionName: "purchase_orders",
created: "2026-08-06T00:00:00.000Z",
updated: "2026-08-06T00:00:00.000Z",
po_number: "PO26000001",
order: "ord1",
supplier: "sup1",
status: "draft",
total_amount: 300,
documents: [],
documents_history: [],
email_message_id: "",
email_payload: { subject: "", body: "" },
email_error: "",
};
const baseItems: OrderItem[] = [
{
id: "oi1",
collectionId: "pbc_order_items",
collectionName: "order_items",
created: "2026-08-06T00:00:00.000Z",
updated: "2026-08-06T00:00:00.000Z",
order: "ord1",
description: "Wheel hub kit — 6-bolt pattern",
po_description: "Wheel hub kit — 6-bolt pattern",
quantity: 3,
order_qty: 3,
selling_price: 150,
supplier: "sup1",
cost_price: 100,
markup: 50,
purchase_order: "po1",
item_status: "processed",
in_stock: false,
notes: "",
sku: "WH-6B-001",
delivery_note_number: "",
problem_notes: "",
} as OrderItem,
];
describe("renderPurchaseOrderPdf", () => {
it("produces a Buffer with a PDF magic-number header", async () => {
const buf = await renderPurchaseOrderPdf({
purchaseOrder: basePurchaseOrder,
items: baseItems,
order: baseOrder,
supplier: baseSupplier,
letterhead: baseLetterhead,
logoDataUri: null,
generatedAtIso: "2026-08-06T12:00:00.000Z",
totalAmount: 300,
});
expect(Buffer.isBuffer(buf)).toBe(true);
expect(buf.subarray(0, 5).toString("ascii")).toBe("%PDF-");
}, 30_000);
it("produces a non-trivial buffer (> 1 KB) for a simple PO", async () => {
const buf = await renderPurchaseOrderPdf({
purchaseOrder: basePurchaseOrder,
items: baseItems,
order: baseOrder,
supplier: baseSupplier,
letterhead: baseLetterhead,
logoDataUri: null,
generatedAtIso: "2026-08-06T12:00:00.000Z",
totalAmount: 300,
});
expect(buf.length).toBeGreaterThan(1024);
}, 30_000);
it("handles missing logo gracefully (logoDataUri=null)", async () => {
const buf = await renderPurchaseOrderPdf({
purchaseOrder: basePurchaseOrder,
items: baseItems,
order: baseOrder,
supplier: baseSupplier,
letterhead: { ...baseLetterhead, logo: "" },
logoDataUri: null,
generatedAtIso: "2026-08-06T12:00:00.000Z",
totalAmount: 300,
});
expect(buf.subarray(0, 5).toString("ascii")).toBe("%PDF-");
}, 30_000);
it("renders with the ISHERWOOD letterhead code (different accent color)", async () => {
const buf = await renderPurchaseOrderPdf({
purchaseOrder: basePurchaseOrder,
items: baseItems,
order: baseOrder,
supplier: baseSupplier,
letterhead: {
...baseLetterhead,
display_name: "ISHERWOOD MINING SUPPLIES",
accent_color: "#7ed957",
},
logoDataUri: null,
generatedAtIso: "2026-08-06T12:00:00.000Z",
totalAmount: 300,
});
expect(buf.subarray(0, 5).toString("ascii")).toBe("%PDF-");
}, 30_000);
});