Add test coverage for the order-unavailable error responses (Task #86)
Task #80 introduced a new 409 `order_unavailable` error code returned by: - PATCH /api/orders/:id/confirm-receipt - PATCH /api/orders/:id/status …to distinguish "already_claimed" (lost a race) from "no longer claimable" (target order is cancelled or completed). The integration test suite did not cover these paths. Changes ------- artifacts/api-server/tests/service-orders.test.mjs + Added test "confirm-receipt returns 409 order_unavailable when the order is cancelled or completed": - Owner cancels a pending order → another receiver's confirm-receipt returns 409 with body.error === "order_unavailable" (not "already_claimed"). - Receiver claims, prepares, completes an order → another receiver's confirm-receipt returns 409 "order_unavailable". + Added test "PATCH /orders/:id/status returns 409 order_unavailable when targeting a terminal order": - Completed order: assignee → preparing → 409 "order_unavailable" - Completed order: assignee → completed → 409 "order_unavailable" - Completed order: owner → cancelled → 409 "order_unavailable" - Cancelled order: owner → cancelled → 409 "order_unavailable" Verification ------------ All 11 service-orders integration tests pass (including both new tests): pnpm --filter @workspace/api-server test → 11 passed, 0 failed. No production code changes; tests only.
This commit is contained in:
@@ -423,6 +423,128 @@ test("owner can restore (undo) a freshly cancelled order to its prior status; ex
|
||||
assert.match(body.error, /undo_window_expired/);
|
||||
});
|
||||
|
||||
test("confirm-receipt returns 409 order_unavailable when the order is cancelled or completed", async () => {
|
||||
const owner = await createUser("ownU", "user");
|
||||
const recv1 = await createUser("recvU1", "order_receiver");
|
||||
const recv2 = await createUser("recvU2", "order_receiver");
|
||||
const co = await login(owner.username);
|
||||
const cr1 = await login(recv1.username);
|
||||
const cr2 = await login(recv2.username);
|
||||
|
||||
// Case A: order cancelled before any claim → second receiver sees order_unavailable
|
||||
let res = await call(co, "POST", "/orders", { serviceId });
|
||||
assert.equal(res.status, 201);
|
||||
const oCancelled = await res.json();
|
||||
createdOrderIds.push(oCancelled.id);
|
||||
|
||||
res = await call(co, "PATCH", `/orders/${oCancelled.id}/status`, {
|
||||
status: "cancelled",
|
||||
});
|
||||
assert.equal(res.status, 200);
|
||||
|
||||
res = await call(cr1, "PATCH", `/orders/${oCancelled.id}/confirm-receipt`);
|
||||
assert.equal(res.status, 409);
|
||||
let body = await res.json();
|
||||
assert.equal(
|
||||
body.error,
|
||||
"order_unavailable",
|
||||
"cancelled order should report order_unavailable, not already_claimed",
|
||||
);
|
||||
|
||||
// Case B: order taken all the way to completed → another receiver sees order_unavailable
|
||||
res = await call(co, "POST", "/orders", { serviceId });
|
||||
assert.equal(res.status, 201);
|
||||
const oCompleted = await res.json();
|
||||
createdOrderIds.push(oCompleted.id);
|
||||
|
||||
res = await call(cr1, "PATCH", `/orders/${oCompleted.id}/confirm-receipt`);
|
||||
assert.equal(res.status, 200);
|
||||
res = await call(cr1, "PATCH", `/orders/${oCompleted.id}/status`, {
|
||||
status: "preparing",
|
||||
});
|
||||
assert.equal(res.status, 200);
|
||||
res = await call(cr1, "PATCH", `/orders/${oCompleted.id}/status`, {
|
||||
status: "completed",
|
||||
});
|
||||
assert.equal(res.status, 200);
|
||||
|
||||
res = await call(cr2, "PATCH", `/orders/${oCompleted.id}/confirm-receipt`);
|
||||
assert.equal(res.status, 409);
|
||||
body = await res.json();
|
||||
assert.equal(
|
||||
body.error,
|
||||
"order_unavailable",
|
||||
"completed order should report order_unavailable, not already_claimed",
|
||||
);
|
||||
});
|
||||
|
||||
test("PATCH /orders/:id/status returns 409 order_unavailable when targeting a terminal order", async () => {
|
||||
const owner = await createUser("ownT", "user");
|
||||
const recv = await createUser("recvT", "order_receiver");
|
||||
const co = await login(owner.username);
|
||||
const cr = await login(recv.username);
|
||||
|
||||
// Build a completed order (assignee = recv)
|
||||
let res = await call(co, "POST", "/orders", { serviceId });
|
||||
assert.equal(res.status, 201);
|
||||
const oDone = await res.json();
|
||||
createdOrderIds.push(oDone.id);
|
||||
|
||||
res = await call(cr, "PATCH", `/orders/${oDone.id}/confirm-receipt`);
|
||||
assert.equal(res.status, 200);
|
||||
res = await call(cr, "PATCH", `/orders/${oDone.id}/status`, {
|
||||
status: "preparing",
|
||||
});
|
||||
assert.equal(res.status, 200);
|
||||
res = await call(cr, "PATCH", `/orders/${oDone.id}/status`, {
|
||||
status: "completed",
|
||||
});
|
||||
assert.equal(res.status, 200);
|
||||
|
||||
// Assignee tries preparing on a completed order → 409 order_unavailable
|
||||
res = await call(cr, "PATCH", `/orders/${oDone.id}/status`, {
|
||||
status: "preparing",
|
||||
});
|
||||
assert.equal(res.status, 409);
|
||||
let body = await res.json();
|
||||
assert.equal(body.error, "order_unavailable");
|
||||
|
||||
// Assignee tries completed (again) on a completed order → 409 order_unavailable
|
||||
res = await call(cr, "PATCH", `/orders/${oDone.id}/status`, {
|
||||
status: "completed",
|
||||
});
|
||||
assert.equal(res.status, 409);
|
||||
body = await res.json();
|
||||
assert.equal(body.error, "order_unavailable");
|
||||
|
||||
// Owner tries to cancel a completed order → 409 order_unavailable (non-admin)
|
||||
res = await call(co, "PATCH", `/orders/${oDone.id}/status`, {
|
||||
status: "cancelled",
|
||||
});
|
||||
assert.equal(res.status, 409);
|
||||
body = await res.json();
|
||||
assert.equal(body.error, "order_unavailable");
|
||||
|
||||
// Build a cancelled order (no assignee)
|
||||
res = await call(co, "POST", "/orders", { serviceId });
|
||||
assert.equal(res.status, 201);
|
||||
const oCxl = await res.json();
|
||||
createdOrderIds.push(oCxl.id);
|
||||
|
||||
res = await call(co, "PATCH", `/orders/${oCxl.id}/status`, {
|
||||
status: "cancelled",
|
||||
});
|
||||
assert.equal(res.status, 200);
|
||||
|
||||
// Owner tries to cancel an already-cancelled order → 409 order_unavailable (non-admin)
|
||||
res = await call(co, "PATCH", `/orders/${oCxl.id}/status`, {
|
||||
status: "cancelled",
|
||||
});
|
||||
assert.equal(res.status, 409);
|
||||
body = await res.json();
|
||||
assert.equal(body.error, "order_unavailable");
|
||||
});
|
||||
|
||||
test("unauthenticated cannot place order", async () => {
|
||||
const res = await fetch(`${API_BASE}/api/orders`, {
|
||||
method: "POST",
|
||||
|
||||
Reference in New Issue
Block a user