test(pdf): add render smoke tests for PO PDF (covers VAT totals)
Co-authored-by: Orca <help@stably.ai>
This commit is contained in:
parent
07900075a4
commit
180288e6e3
1 changed files with 187 additions and 0 deletions
187
src/lib/pdf/purchase-order-document.test.tsx
Normal file
187
src/lib/pdf/purchase-order-document.test.tsx
Normal 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);
|
||||
});
|
||||
Loading…
Reference in a new issue