fix(api): preserve auth status + guard pagination against NaN
- Catch block now preserves error.status so assertAgentAuth's 401 surfaces as 401, not 500. Matches sibling /api/v1/stock-purchases pattern. - page/perPage parsing falls back to documented defaults on non-numeric or zero input rather than passing NaN to the service. - Add 2 tests covering the auth-status and pagination boundaries. Co-authored-by: Orca <help@stably.ai>
This commit is contained in:
parent
8cb4e9a60c
commit
469b2c0460
2 changed files with 44 additions and 3 deletions
|
|
@ -93,4 +93,38 @@ describe("/api/v1/stock-purchases/list", () => {
|
|||
const body = await res.json();
|
||||
expect(body.error).toBe("PB is down");
|
||||
});
|
||||
|
||||
it("returns 401 when the request is not authenticated", async () => {
|
||||
// No bearer header — assertAgentAuth throws with status: 401.
|
||||
const req = new NextRequest("http://localhost/api/v1/stock-purchases/list");
|
||||
const res = await GET(req);
|
||||
expect(res.status).toBe(401);
|
||||
expect(listStockPurchases).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("clamps page/perPage and falls back to defaults on malformed input", async () => {
|
||||
listStockPurchases.mockResolvedValue({
|
||||
items: [],
|
||||
totalItems: 0,
|
||||
page: 1,
|
||||
perPage: 50,
|
||||
totalPages: 0,
|
||||
});
|
||||
|
||||
const cases: Array<[string, { status: ""; page: number; perPage: number }]> = [
|
||||
["?page=0", { status: "", page: 1, perPage: 50 }],
|
||||
["?page=abc", { status: "", page: 1, perPage: 50 }],
|
||||
["?perPage=0", { status: "", page: 1, perPage: 50 }],
|
||||
["?perPage=abc", { status: "", page: 1, perPage: 50 }],
|
||||
["?perPage=999", { status: "", page: 1, perPage: 200 }],
|
||||
];
|
||||
|
||||
for (const [qs, expected] of cases) {
|
||||
listStockPurchases.mockClear();
|
||||
await GET(
|
||||
authedRequest(`http://localhost/api/v1/stock-purchases/list${qs}`),
|
||||
);
|
||||
expect(listStockPurchases).toHaveBeenCalledWith(expect.anything(), expected);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -39,10 +39,16 @@ export async function GET(req: NextRequest) {
|
|||
}
|
||||
const status = rawStatus as StockPurchaseStatus | "";
|
||||
|
||||
const page = Math.max(1, Number(req.nextUrl.searchParams.get("page") || "1"));
|
||||
const page = Math.max(
|
||||
1,
|
||||
Number(req.nextUrl.searchParams.get("page") || "1") || 1,
|
||||
);
|
||||
const perPage = Math.min(
|
||||
200,
|
||||
Math.max(1, Number(req.nextUrl.searchParams.get("perPage") || "50")),
|
||||
Math.max(
|
||||
1,
|
||||
Number(req.nextUrl.searchParams.get("perPage") || "50") || 50,
|
||||
),
|
||||
);
|
||||
|
||||
const pb = await getAdminPocketBase();
|
||||
|
|
@ -51,6 +57,7 @@ export async function GET(req: NextRequest) {
|
|||
} catch (error) {
|
||||
const message =
|
||||
error instanceof Error ? error.message : "Failed to fetch stock-purchases";
|
||||
return NextResponse.json({ error: message }, { status: 500 });
|
||||
const status = (error as Error & { status?: number }).status || 500;
|
||||
return NextResponse.json({ error: message }, { status });
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue