pelagia-portal/App/tests/unit/attachments.test.ts
Claude (auto-fix) 4e6175153d fix(po): show all attachments grouped by type on PO details
All PO attachments are stored as PODocument rows whose lifecycle stage
(submission vs delivery) is encoded in the storageKey prefix. The PO
details screen previously listed them in a single flat "Attachments"
block, giving no indication of which were submission documents (invoice,
quotation) versus delivery receipts.

Add lib/attachments.ts to derive a user-facing group from the storageKey
prefix (submission / payment / delivery / other) and render each
non-empty group as a labelled subsection on the PO details screen, in
lifecycle order. Unknown prefixes fall back to an "Other" group so
nothing is ever hidden.

Fixes #10
2026-06-19 04:43:44 +05:30

67 lines
2.3 KiB
TypeScript

import { describe, expect, it } from "vitest";
import {
categorizeAttachment,
groupAttachments,
} from "@/lib/attachments";
describe("categorizeAttachment", () => {
it("maps po-document keys to the submission group", () => {
expect(categorizeAttachment("po-document/po123/1700-invoice.pdf")).toBe("submission");
});
it("maps receipt keys to the delivery group", () => {
expect(categorizeAttachment("receipt/po123/1700-delivery.pdf")).toBe("delivery");
});
it("maps payment keys to the payment group", () => {
expect(categorizeAttachment("payment-document/po123/proof.pdf")).toBe("payment");
expect(categorizeAttachment("payment/po123/proof.pdf")).toBe("payment");
});
it("falls back to other for unknown prefixes", () => {
expect(categorizeAttachment("something-else/x.pdf")).toBe("other");
expect(categorizeAttachment("no-slash")).toBe("other");
});
});
describe("groupAttachments", () => {
const doc = (id: string, storageKey: string) => ({ id, storageKey });
it("groups documents by lifecycle stage in canonical order", () => {
const groups = groupAttachments([
doc("a", "receipt/po1/delivery.pdf"),
doc("b", "po-document/po1/invoice.pdf"),
doc("c", "po-document/po1/quote.pdf"),
]);
expect(groups.map((g) => g.meta.key)).toEqual(["submission", "delivery"]);
expect(groups[0].items.map((d) => d.id)).toEqual(["b", "c"]);
expect(groups[1].items.map((d) => d.id)).toEqual(["a"]);
});
it("omits empty groups", () => {
const groups = groupAttachments([doc("a", "po-document/po1/invoice.pdf")]);
expect(groups).toHaveLength(1);
expect(groups[0].meta.key).toBe("submission");
});
it("returns an empty array when there are no documents", () => {
expect(groupAttachments([])).toEqual([]);
});
it("preserves input order within a group", () => {
const groups = groupAttachments([
doc("first", "receipt/po1/a.pdf"),
doc("second", "receipt/po1/b.pdf"),
]);
expect(groups[0].items.map((d) => d.id)).toEqual(["first", "second"]);
});
it("collects unknown prefixes into the other group last", () => {
const groups = groupAttachments([
doc("x", "mystery/po1/file.pdf"),
doc("y", "po-document/po1/invoice.pdf"),
]);
expect(groups.map((g) => g.meta.key)).toEqual(["submission", "other"]);
});
});