187 lines
5.5 KiB
TypeScript
187 lines
5.5 KiB
TypeScript
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);
|
|
});
|