test(quotes): cover spec test cases #3 and #5 for no-quote

Closes the two IMPORTANT test-coverage gaps from the final
implementation review. Pure additions; no production code changes.

  - Spec test #3: submitQuote({partial:true}) accepts zero-priced
    items when is_no_quote=true (status flips to
    partial_approval_pending)
  - Spec test #5: strengthen the no-supplier + no-quote assertion
    to check the missing array directly, not just the failure.code

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Dave 2026-08-27 00:02:25 +02:00
parent 87eacdc307
commit e0d214c94f

View file

@ -1255,6 +1255,18 @@ describe("diagnosePdfReadiness with is_no_quote", () => {
expect(result.failure?.details?.issues?.[0]?.missing).toContain(
"no supplier"
);
// Stronger assertion (spec test case #5): confirm the `details.issues`
// array directly contains an object whose `missing` list includes
// "no supplier". Guards against future refactors that drop the
// missing-array shape (e.g. moving the supplier check out of the
// per-issue structure).
expect(result.failure?.details?.issues).toEqual(
expect.arrayContaining([
expect.objectContaining({
missing: expect.arrayContaining(["no supplier"]),
}),
]),
);
// And the pricing/processed checks must NOT appear in the missing list
// (since the operator marked this as a decline).
const missing = result.failure?.details?.issues?.[0]?.missing ?? [];
@ -1909,6 +1921,41 @@ describe("submitQuote with is_no_quote", () => {
expect(stored.status).toBe("approval_pending");
});
it("flips a new no-quote quote to partial_approval_pending when partial:true even with zero-priced items", async () => {
// Spec test case #3: `submitQuote` accepts zero-priced items when
// `is_no_quote` true AND `partial: true`. Mirrors the previous test
// (spec #1) but flips on the partial flag and asserts the
// `partial_approval_pending` target status — not the full-approval
// path.
await pbMock.collection("quotes").create({
id: "q-test",
quote_number: "Q-2026-08-004",
status: "new",
is_no_quote: true,
});
await pbMock.collection("quote_items").create({
id: "qi-zero",
quote: "q-test",
description: "M16 bolt",
selling_price: 0,
});
await pbMock.collection("quote_items").create({
id: "qi-priced",
quote: "q-test",
description: "Hex nut",
selling_price: 100,
});
const result = await submitQuote("q-test", undefined, { partial: true });
expect(result.statusChanged).toBe(true);
expect(result.quote.status).toBe("partial_approval_pending");
expect(result.targetStatus).toBe("partial_approval_pending");
// PB row updated in place.
const stored = await pbMock.collection("quotes").getOne("q-test");
expect(stored.status).toBe("partial_approval_pending");
});
it("still throws unpriced_items for a regular (non-no-quote) quote with zero-priced items", async () => {
await pbMock.collection("quotes").create({
id: "q-test",