test(orders): cover auth + matcher-isolation for backfill endpoint, document response shape

This commit is contained in:
Dave 2026-08-30 22:30:52 +02:00
parent f0c5daa99e
commit 14347c4b4b
2 changed files with 56 additions and 0 deletions

View file

@ -1,6 +1,9 @@
import { describe, it, expect, vi, beforeEach } from "vitest";
import { NextRequest } from "next/server";
import { POST } from "./route";
import { suggestOrderNumberDuplicate } from "@/lib/server/order-number-duplicate-link-service";
import { suggestOrderDuplicate } from "@/lib/server/order-order-duplicate-link-service";
import { suggestDeliveryNoteForOrder } from "@/lib/server/order-delivery-note-link-service";
vi.mock("@/lib/server/order-number-duplicate-link-service", () => ({
suggestOrderNumberDuplicate: vi.fn().mockResolvedValue({ duplicateOrderId: null }),
@ -45,5 +48,47 @@ describe("POST /api/v1/orders/backfill-duplicate-checks", () => {
expect(res.status).toBe(200);
const body = await res.json();
expect(body.ordersProcessed).toBe(2);
expect(suggestOrderNumberDuplicate).toHaveBeenCalledTimes(2);
expect(suggestOrderDuplicate).toHaveBeenCalledTimes(2);
expect(suggestDeliveryNoteForOrder).toHaveBeenCalledTimes(2);
expect(suggestOrderNumberDuplicate).toHaveBeenCalledWith("order-1");
expect(suggestOrderNumberDuplicate).toHaveBeenCalledWith("order-2");
});
it("returns 401 when AGENT_API_KEY is missing", async () => {
delete process.env.AGENT_API_KEY;
const res = await POST(backfillRequest());
expect(res.status).toBe(401);
const body = await res.json();
expect(body.error).toBeTruthy();
});
it("returns 401 when AGENT_API_KEY is wrong", async () => {
process.env.AGENT_API_KEY = AGENT_API_KEY;
const req = new NextRequest(
"http://localhost/api/v1/orders/backfill-duplicate-checks",
{
method: "POST",
headers: { authorization: "Bearer wrong-key" },
},
);
const res = await POST(req);
expect(res.status).toBe(401);
});
it("continues processing when one matcher throws for one order", async () => {
vi.mocked(suggestOrderNumberDuplicate)
.mockRejectedValueOnce(new Error("boom"))
.mockResolvedValueOnce({ duplicateOrderId: null });
const res = await POST(backfillRequest());
expect(res.status).toBe(200);
const body = await res.json();
expect(body.ordersProcessed).toBe(2);
expect(body.failures.length).toBe(1);
expect(body.failures[0].orderId).toBe("order-1");
expect(body.failures[0].error).toContain("order_number:");
expect(body.failures[0].error).toContain("boom");
});
});

View file

@ -11,6 +11,17 @@
* over the full orders table, and PocketBase's admin client doesn't
* love thousands of concurrent requests. This is a background/admin
* operation, not a user-facing latency path.
*
* Returns: `{ ordersProcessed, failures }` where `failures` is
* `Array<{ orderId, error }>`. The `error` string is prefixed with
* the matcher name (`order_number:`, `item_duplicate:`, or
* `delivery_note:`) followed by the underlying error message, so
* callers can tell which matcher tripped without re-running.
*
* Errors:
* 401 — missing/wrong `AGENT_API_KEY`.
* (per-order matcher failures are reported in `failures`, not
* surfaced as HTTP errors)
*/
export const runtime = "nodejs";
export const dynamic = "force-dynamic";