| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566 |
- /* @vitest-environment node */
- import { describe, it, expect } from "vitest";
- import { jsonError, withErrorHandling, badRequest } from "./errors.js";
- describe("lib/api/errors", () => {
- it("jsonError returns the standardized error shape without details", async () => {
- const res = jsonError(401, "AUTH_UNAUTHENTICATED", "Unauthorized");
- expect(res.status).toBe(401);
- expect(await res.json()).toEqual({
- error: { message: "Unauthorized", code: "AUTH_UNAUTHENTICATED" },
- });
- });
- it("jsonError includes details when provided", async () => {
- const res = jsonError(
- 400,
- "VALIDATION_MISSING_PARAM",
- "Missing required route parameter(s)",
- { params: ["branch"] }
- );
- expect(res.status).toBe(400);
- expect(await res.json()).toEqual({
- error: {
- message: "Missing required route parameter(s)",
- code: "VALIDATION_MISSING_PARAM",
- details: { params: ["branch"] },
- },
- });
- });
- it("withErrorHandling converts ApiError into a standardized response", async () => {
- // The wrapped handler throws an expected error (ApiError).
- // The wrapper must convert it into { error: { message, code } } with status 400.
- const handler = withErrorHandling(async () => {
- throw badRequest("VALIDATION_TEST", "Bad Request");
- });
- const res = await handler();
- expect(res.status).toBe(400);
- expect(await res.json()).toEqual({
- error: { message: "Bad Request", code: "VALIDATION_TEST" },
- });
- });
- it("withErrorHandling converts unknown errors into a safe 500 response", async () => {
- // Unknown errors must never leak internal messages/stacks.
- // We always return a generic 500 payload.
- const handler = withErrorHandling(async () => {
- throw new Error("boom");
- });
- const res = await handler();
- expect(res.status).toBe(500);
- expect(await res.json()).toEqual({
- error: {
- message: "Internal server error",
- code: "INTERNAL_SERVER_ERROR",
- },
- });
- });
- });
|