test: cover correction transaction fencing

This commit is contained in:
DEls 2026-09-19 18:38:02 +02:00
parent 0846ce5790
commit 81a4427fea
2 changed files with 21 additions and 0 deletions

View file

@ -82,4 +82,19 @@ describe("resolve-item route", () => {
const { POST } = await import("./route");
await expect(POST(request({ lineIndex: 0, purchaseOrderItemId: ITEM, reason: "verified", rememberAlias: false }), { params: Promise.resolve({ id: BATCH, noteId: NOTE }) })).rejects.toThrow("batch transaction failed");
});
it("submits note, audit, and alias mutations as one failing transaction with no committed rows", async () => {
const queued: Array<{ collection: string; method: string }> = [];
lease.batch.mockImplementationOnce(async (mutations: Array<{ collection: string; method: string }>) => {
queued.push(...mutations);
// Simulate PocketBase's all-or-nothing batch response: the server
// rejects after validating the queued mutations, so none commit.
throw new Error("batch transaction failed after validation");
});
const { POST } = await import("./route");
await expect(POST(request({ lineIndex: 0, purchaseOrderItemId: ITEM, reason: "verified", rememberAlias: true }), { params: Promise.resolve({ id: BATCH, noteId: NOTE }) })).rejects.toThrow("batch transaction failed after validation");
expect(queued.map((mutation) => mutation.collection)).toEqual(["dn_batch_notes", "dn_review_events", "dn_item_aliases"]);
expect(rows.dn_review_events).toHaveLength(0);
expect(rows.dn_item_aliases).toHaveLength(0);
});
});

View file

@ -59,4 +59,10 @@ describe("evaluateCandidateReadiness", () => {
expect(result.ready).toBe(false);
expect(result.reasons).toContain("assembly_revision_missing");
});
it("fails closed on an unknown persisted blocking check", () => {
const result = evaluateCandidateReadiness({ ...base, checks: [...base.checks, { id: "future_financial_gate", passed: false }] });
expect(result.ready).toBe(false);
expect(result.reasons).toContain("unknown_check_not_passed:future_financial_gate");
});
});