Skip to content

Commit 11f3c6d

Browse files
committed
🐛 manually include issues in defaultHook
1 parent 8dcb3f4 commit 11f3c6d

File tree

2 files changed

+114
-1
lines changed

2 files changed

+114
-1
lines changed

src/openapi/default-hook.test.ts

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
import { createRoute, OpenAPIHono, z } from "@hono/zod-openapi";
2+
import { describe, expect, it } from "vitest";
3+
4+
import * as HttpStatusCodes from "../http-status-codes.js";
5+
import defaultHook from "./default-hook.js";
6+
7+
const UserSchema = z.object({
8+
name: z.string(),
9+
age: z.number(),
10+
});
11+
12+
describe("default-hook", () => {
13+
it("returns 422 and error body for failed validation", async () => {
14+
const app = new OpenAPIHono({ defaultHook });
15+
app.openapi(
16+
createRoute({
17+
method: "post",
18+
path: "/users",
19+
request: {
20+
body: {
21+
content: {
22+
"application/json": {
23+
schema: UserSchema,
24+
},
25+
},
26+
description: "Create user",
27+
},
28+
},
29+
responses: {
30+
[HttpStatusCodes.UNPROCESSABLE_ENTITY]: {
31+
content: {
32+
"application/json": {
33+
schema: z.object({
34+
success: z.boolean(),
35+
error: z.object({
36+
name: z.string(),
37+
issues: z.array(z.any()),
38+
}),
39+
}),
40+
},
41+
},
42+
description: "Validation error",
43+
},
44+
},
45+
}),
46+
// @ts-expect-error will not reach here
47+
(c) => {
48+
// Should not reach here if validation fails
49+
return c.json({ ok: true });
50+
},
51+
);
52+
53+
const res = await app.request("/users", {
54+
method: "POST",
55+
body: JSON.stringify({ name: 123, age: "not-a-number" }),
56+
headers: { "content-type": "application/json" },
57+
});
58+
expect(res.status).toBe(HttpStatusCodes.UNPROCESSABLE_ENTITY);
59+
const json = await res.json() as any;
60+
expect(json.success).toBe(false);
61+
expect(json.error).toBeDefined();
62+
expect(json.error.name).toBe("ZodError");
63+
expect(Array.isArray(json.error.issues)).toBe(true);
64+
expect(json.error.issues.length).toBeGreaterThan(0);
65+
});
66+
67+
it("does not trigger hook for valid input", async () => {
68+
const app = new OpenAPIHono({ defaultHook });
69+
app.openapi(
70+
createRoute({
71+
method: "post",
72+
path: "/users",
73+
request: {
74+
body: {
75+
content: {
76+
"application/json": {
77+
schema: UserSchema,
78+
},
79+
},
80+
description: "Create user",
81+
},
82+
},
83+
responses: {
84+
[HttpStatusCodes.OK]: {
85+
content: {
86+
"application/json": {
87+
schema: UserSchema,
88+
},
89+
},
90+
description: "User created",
91+
},
92+
},
93+
}),
94+
(c) => {
95+
const user = c.req.valid("json");
96+
return c.json(user, HttpStatusCodes.OK);
97+
},
98+
);
99+
100+
const res = await app.request("/users", {
101+
method: "POST",
102+
body: JSON.stringify({ name: "Alice", age: 30 }),
103+
headers: { "content-type": "application/json" },
104+
});
105+
expect(res.status).toBe(HttpStatusCodes.OK);
106+
const json = await res.json() as any;
107+
expect(json.name).toBe("Alice");
108+
expect(json.age).toBe(30);
109+
});
110+
});

src/openapi/default-hook.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,10 @@ const defaultHook: Hook<any, any, any, any> = (result, c) => {
77
return c.json(
88
{
99
success: result.success,
10-
error: result.error,
10+
error: {
11+
name: result.error.name,
12+
issues: result.error.issues,
13+
},
1114
},
1215
UNPROCESSABLE_ENTITY,
1316
);

0 commit comments

Comments
 (0)