Skip to content

Commit 0bc74a2

Browse files
committed
Add tests to cover nested routers and body parameters
1 parent 351e95a commit 0bc74a2

File tree

3 files changed

+202
-0
lines changed

3 files changed

+202
-0
lines changed
+82
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
import 'isomorphic-fetch'
2+
3+
import { OpenAPIRoute } from '../../src/route'
4+
import { Path } from '../../src/parameters'
5+
import { OpenAPIRouter } from '../../src/openapi'
6+
import { buildRequest } from '../utils'
7+
8+
const innerRouter = OpenAPIRouter({ base: '/api/v1' })
9+
class ToDoGet extends OpenAPIRoute {
10+
static schema = {
11+
tags: ['ToDo'],
12+
summary: 'Get a single ToDo',
13+
parameters: {
14+
id: Path(Number),
15+
},
16+
responses: {
17+
'200': {
18+
schema: {
19+
todo: {
20+
lorem: String,
21+
ipsum: String,
22+
},
23+
},
24+
},
25+
},
26+
}
27+
28+
async handle(request: Request, env: any, context: any, data: Record<string, any>) {
29+
return {
30+
todo: {
31+
lorem: 'lorem',
32+
ipsum: 'ipsum',
33+
},
34+
}
35+
}
36+
}
37+
38+
innerRouter.get('/todo/:id', ToDoGet)
39+
innerRouter.all('*', () => Response.json({ message: 'Not Found' }, { status: 404 }))
40+
41+
const router = OpenAPIRouter({
42+
schema: {
43+
info: {
44+
title: 'Radar Worker API',
45+
version: '1.0',
46+
},
47+
},
48+
})
49+
50+
router.all('/api/v1/*', innerRouter)
51+
router.all('*', () => new Response('Not Found.', { status: 404 }))
52+
53+
describe('innerRouter', () => {
54+
it('simpleSuccessfulCall', async () => {
55+
const request = await router.handle(buildRequest({ method: 'GET', path: `/api/v1/todo/1` }))
56+
const resp = await request.json()
57+
58+
expect(request.status).toEqual(200)
59+
expect(resp).toEqual({
60+
todo: {
61+
lorem: 'lorem',
62+
ipsum: 'ipsum',
63+
},
64+
})
65+
})
66+
67+
it('innerCatchAll', async () => {
68+
const request = await router.handle(buildRequest({ method: 'GET', path: `/api/v1/asd` }))
69+
const resp = await request.json()
70+
71+
expect(request.status).toEqual(404)
72+
expect(resp).toEqual({ message: 'Not Found' })
73+
})
74+
75+
it('outerCatchAll', async () => {
76+
const request = await router.handle(buildRequest({ method: 'GET', path: `/asd` }))
77+
const resp = await request.text()
78+
79+
expect(request.status).toEqual(404)
80+
expect(resp).toEqual('Not Found.')
81+
})
82+
})

tests/integration/parameters.test.ts

+85
Original file line numberDiff line numberDiff line change
@@ -367,3 +367,88 @@ describe('queryParametersValidation', () => {
367367
expect(resp.errors.p_optional).toBeUndefined()
368368
})
369369
})
370+
371+
describe('bodyParametersValidation', () => {
372+
test('requiredFieldTitle', async () => {
373+
const request = await todoRouter.handle(
374+
buildRequest({
375+
method: 'POST',
376+
path: '/todos',
377+
json: () => {
378+
return {}
379+
},
380+
})
381+
)
382+
const resp = await request.json()
383+
384+
expect(request.status).toEqual(400)
385+
386+
// the current body implementation only validates 1 field at time
387+
expect(resp.errors['body.title']).toEqual('is required')
388+
})
389+
390+
test('requiredFieldTipe', async () => {
391+
const request = await todoRouter.handle(
392+
buildRequest({
393+
method: 'POST',
394+
path: '/todos',
395+
json: () => {
396+
return {
397+
title: 'my todo',
398+
}
399+
},
400+
})
401+
)
402+
const resp = await request.json()
403+
404+
expect(request.status).toEqual(400)
405+
406+
// the current body implementation only validates 1 field at time
407+
expect(resp.errors['body.type']).toEqual('is required')
408+
})
409+
410+
test('validRequest', async () => {
411+
const request = await todoRouter.handle(
412+
buildRequest({
413+
method: 'POST',
414+
path: '/todos',
415+
json: () => {
416+
return {
417+
title: 'my todo',
418+
type: 'nextWeek',
419+
}
420+
},
421+
}),
422+
{},
423+
{}
424+
)
425+
const resp = await request.json()
426+
427+
expect(request.status).toEqual(200)
428+
429+
expect(resp).toEqual({ todo: { title: 'my todo', type: 'nextWeek' } })
430+
})
431+
432+
test('validRequestWithOptionalParameters', async () => {
433+
const request = await todoRouter.handle(
434+
buildRequest({
435+
method: 'POST',
436+
path: '/todos',
437+
json: () => {
438+
return {
439+
title: 'my todo',
440+
description: 'this will be done',
441+
type: 'nextWeek',
442+
}
443+
},
444+
}),
445+
{},
446+
{}
447+
)
448+
const resp = await request.json()
449+
450+
expect(request.status).toEqual(200)
451+
452+
expect(resp).toEqual({ todo: { title: 'my todo', description: 'this will be done', type: 'nextWeek' } })
453+
})
454+
})

tests/router.ts

+35
Original file line numberDiff line numberDiff line change
@@ -102,9 +102,44 @@ export class ToDoGet extends OpenAPIRoute {
102102
}
103103
}
104104

105+
export class ToDoCreate extends OpenAPIRoute {
106+
static schema = {
107+
tags: ['ToDo'],
108+
summary: 'Create a new ToDo',
109+
requestBody: {
110+
title: String,
111+
description: new Str({ required: false }),
112+
type: new Enumeration({
113+
values: {
114+
nextWeek: 'nextWeek',
115+
nextMonth: 'nextMonth',
116+
},
117+
}),
118+
},
119+
responses: {
120+
'200': {
121+
schema: {
122+
todo: {
123+
title: 'My new todo',
124+
description: 'This really needs to be done next week',
125+
type: 'nextWeek',
126+
},
127+
},
128+
},
129+
},
130+
}
131+
132+
async handle(request: Request, env: any, context: any, data: Record<string, any>) {
133+
return {
134+
todo: data.body,
135+
}
136+
}
137+
}
138+
105139
export const todoRouter = OpenAPIRouter()
106140
todoRouter.get('/todos', ToDoList)
107141
todoRouter.get('/todos/:id', ToDoGet)
142+
todoRouter.post('/todos', ToDoCreate)
108143

109144
// 404 for everything else
110145
todoRouter.all('*', () => new Response('Not Found.', { status: 404 }))

0 commit comments

Comments
 (0)