test(zod-openapi): update tests (#268)
* changeset * test(zod-openapi): update tests * changeset * delete md * update READMEpull/266/head
parent
2e697077bf
commit
bae3c0fd43
|
@ -286,10 +286,25 @@ const client = hc<typeof appRoutes>('http://localhost:8787/')
|
||||||
|
|
||||||
## Limitations
|
## Limitations
|
||||||
|
|
||||||
|
### Combining with `Hono`
|
||||||
|
|
||||||
Be careful when combining `OpenAPIHono` instances with plain `Hono` instances. `OpenAPIHono` will merge the definitions of direct subapps, but plain `Hono` knows nothing about the OpenAPI spec additions. Similarly `OpenAPIHono` will not "dig" for instances deep inside a branch of plain `Hono` instances.
|
Be careful when combining `OpenAPIHono` instances with plain `Hono` instances. `OpenAPIHono` will merge the definitions of direct subapps, but plain `Hono` knows nothing about the OpenAPI spec additions. Similarly `OpenAPIHono` will not "dig" for instances deep inside a branch of plain `Hono` instances.
|
||||||
|
|
||||||
If you're migrating from plain `Hono` to `OpenAPIHono`, we recommend porting your top-level app, then working your way down the router tree.
|
If you're migrating from plain `Hono` to `OpenAPIHono`, we recommend porting your top-level app, then working your way down the router tree.
|
||||||
|
|
||||||
|
### Header keys
|
||||||
|
|
||||||
|
Header keys that you define in your schema must be in lowercase.
|
||||||
|
|
||||||
|
```ts
|
||||||
|
const HeadersSchema = z.object({
|
||||||
|
// Header keys must be in lowercase, `Authorization` is not allowed.
|
||||||
|
authorization: z.string().openapi({
|
||||||
|
example: 'Bearer SECRET',
|
||||||
|
}),
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
## References
|
## References
|
||||||
|
|
||||||
- [Hono](https://hono.dev/)
|
- [Hono](https://hono.dev/)
|
||||||
|
|
|
@ -42,6 +42,7 @@
|
||||||
"zod": "3.*"
|
"zod": "3.*"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@hono/zod-validator": "^0.1.11",
|
||||||
"hono": "^3.9.1",
|
"hono": "^3.9.1",
|
||||||
"zod": "^3.22.1"
|
"zod": "^3.22.1"
|
||||||
},
|
},
|
||||||
|
|
|
@ -33,31 +33,20 @@ describe('Basic - params', () => {
|
||||||
const ParamsSchema = z.object({
|
const ParamsSchema = z.object({
|
||||||
id: z
|
id: z
|
||||||
.string()
|
.string()
|
||||||
.transform((val, ctx) => {
|
.min(4)
|
||||||
const parsed = parseInt(val)
|
|
||||||
if (isNaN(parsed)) {
|
|
||||||
ctx.addIssue({
|
|
||||||
code: z.ZodIssueCode.custom,
|
|
||||||
message: 'Not a number',
|
|
||||||
})
|
|
||||||
return z.NEVER
|
|
||||||
}
|
|
||||||
return parsed
|
|
||||||
})
|
|
||||||
.openapi({
|
.openapi({
|
||||||
param: {
|
param: {
|
||||||
name: 'id',
|
name: 'id',
|
||||||
in: 'path',
|
in: 'path',
|
||||||
},
|
},
|
||||||
example: 123,
|
example: '12345',
|
||||||
type: 'integer',
|
|
||||||
}),
|
}),
|
||||||
})
|
})
|
||||||
|
|
||||||
const UserSchema = z
|
const UserSchema = z
|
||||||
.object({
|
.object({
|
||||||
id: z.number().openapi({
|
id: z.string().openapi({
|
||||||
example: 123,
|
example: '12345',
|
||||||
}),
|
}),
|
||||||
name: z.string().openapi({
|
name: z.string().openapi({
|
||||||
example: 'John Doe',
|
example: 'John Doe',
|
||||||
|
@ -68,6 +57,13 @@ describe('Basic - params', () => {
|
||||||
})
|
})
|
||||||
.openapi('User')
|
.openapi('User')
|
||||||
|
|
||||||
|
const HeadersSchema = z.object({
|
||||||
|
// Header keys must be in lowercase
|
||||||
|
authorization: z.string().openapi({
|
||||||
|
example: 'Bearer SECRET',
|
||||||
|
}),
|
||||||
|
})
|
||||||
|
|
||||||
const ErrorSchema = z
|
const ErrorSchema = z
|
||||||
.object({
|
.object({
|
||||||
ok: z.boolean().openapi({
|
ok: z.boolean().openapi({
|
||||||
|
@ -81,6 +77,7 @@ describe('Basic - params', () => {
|
||||||
path: '/users/{id}',
|
path: '/users/{id}',
|
||||||
request: {
|
request: {
|
||||||
params: ParamsSchema,
|
params: ParamsSchema,
|
||||||
|
headers: HeadersSchema,
|
||||||
},
|
},
|
||||||
responses: {
|
responses: {
|
||||||
200: {
|
200: {
|
||||||
|
@ -136,17 +133,21 @@ describe('Basic - params', () => {
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Should return 200 response with correct contents', async () => {
|
it('Should return 200 response with correct contents', async () => {
|
||||||
const res = await app.request('/users/123')
|
const res = await app.request('/users/12345', {
|
||||||
|
headers: {
|
||||||
|
Authorization: 'Bearer TOKEN',
|
||||||
|
},
|
||||||
|
})
|
||||||
expect(res.status).toBe(200)
|
expect(res.status).toBe(200)
|
||||||
expect(await res.json()).toEqual({
|
expect(await res.json()).toEqual({
|
||||||
id: 123,
|
id: '12345',
|
||||||
age: 20,
|
age: 20,
|
||||||
name: 'Ultra-man',
|
name: 'Ultra-man',
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Should return 400 response with correct contents', async () => {
|
it('Should return 400 response with correct contents', async () => {
|
||||||
const res = await app.request('/users/abc')
|
const res = await app.request('/users/123')
|
||||||
expect(res.status).toBe(400)
|
expect(res.status).toBe(400)
|
||||||
expect(await res.json()).toEqual({ ok: false })
|
expect(await res.json()).toEqual({ ok: false })
|
||||||
})
|
})
|
||||||
|
@ -162,7 +163,7 @@ describe('Basic - params', () => {
|
||||||
User: {
|
User: {
|
||||||
type: 'object',
|
type: 'object',
|
||||||
properties: {
|
properties: {
|
||||||
id: { type: 'number', example: 123 },
|
id: { type: 'string', example: '12345' },
|
||||||
name: { type: 'string', example: 'John Doe' },
|
name: { type: 'string', example: 'John Doe' },
|
||||||
age: { type: 'number', example: 42 },
|
age: { type: 'number', example: 42 },
|
||||||
},
|
},
|
||||||
|
@ -181,11 +182,17 @@ describe('Basic - params', () => {
|
||||||
get: {
|
get: {
|
||||||
parameters: [
|
parameters: [
|
||||||
{
|
{
|
||||||
schema: { type: 'integer', example: 123 },
|
schema: { type: 'string', example: '12345', minLength: 4 },
|
||||||
required: true,
|
required: true,
|
||||||
name: 'id',
|
name: 'id',
|
||||||
in: 'path',
|
in: 'path',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
schema: { type: 'string', example: 'Bearer SECRET' },
|
||||||
|
required: true,
|
||||||
|
name: 'authorization',
|
||||||
|
in: 'header',
|
||||||
|
},
|
||||||
],
|
],
|
||||||
responses: {
|
responses: {
|
||||||
'200': {
|
'200': {
|
||||||
|
|
Loading…
Reference in New Issue