galbe 0.10.1 → 0.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.prettierrc +1 -1
- package/README.md +3 -0
- package/bin/commands/generate/client.ts +58 -30
- package/bin/commands/generate/code/openapi.parser.ts +72 -45
- package/bin/res/cli.template.js +20 -18
- package/bin/res/client.template.ts +52 -26
- package/bin/util.ts +27 -7
- package/docs/cli.md +25 -22
- package/docs/configuration.md +80 -0
- package/docs/context.md +38 -52
- package/docs/error-handler.md +20 -31
- package/docs/getting-started.md +40 -157
- package/docs/handler.md +35 -21
- package/docs/hooks.md +16 -16
- package/docs/plugins.md +50 -57
- package/docs/router.md +2 -2
- package/docs/routes.md +56 -39
- package/docs/schemas.md +115 -69
- package/package.json +1 -1
- package/src/extras/spec/openapi.serializer.ts +83 -56
- package/src/index.ts +16 -11
- package/src/parser.ts +199 -147
- package/src/router.ts +2 -2
- package/src/schema.ts +156 -66
- package/src/server.ts +25 -17
- package/src/types.ts +54 -42
- package/src/util.ts +37 -9
- package/src/validator.ts +23 -19
- package/test/parser.test.ts +375 -272
- package/test/requests.test.ts +242 -176
- package/test/resources/static/chameleon.png +0 -0
- package/test/resources/static/index.html +13 -0
- package/test/resources/static/sub/index.html +13 -0
- package/test/resources/static/sub/other.html +13 -0
- package/test/responses.test.ts +49 -49
- package/test/router.test.ts +14 -0
- package/test/test.utils.ts +4 -2
- package/test/types.test.ts +909 -0
package/test/parser.test.ts
CHANGED
|
@@ -7,7 +7,8 @@ import {
|
|
|
7
7
|
handleBody,
|
|
8
8
|
schema_objectBase,
|
|
9
9
|
handleUrlFormStream,
|
|
10
|
-
isAsyncIterator
|
|
10
|
+
isAsyncIterator,
|
|
11
|
+
EMPTY_BA_STR,
|
|
11
12
|
} from './test.utils'
|
|
12
13
|
import { Galbe, $T } from '../src'
|
|
13
14
|
import { schemaToTypeStr } from '../src/schema'
|
|
@@ -29,8 +30,8 @@ describe('parser', () => {
|
|
|
29
30
|
float: $T.number(),
|
|
30
31
|
integer: $T.integer(),
|
|
31
32
|
'boolean-true': $T.boolean(),
|
|
32
|
-
'boolean-false': $T.boolean()
|
|
33
|
-
}
|
|
33
|
+
'boolean-false': $T.boolean(),
|
|
34
|
+
},
|
|
34
35
|
},
|
|
35
36
|
ctx => {
|
|
36
37
|
return ctx.headers
|
|
@@ -44,8 +45,8 @@ describe('parser', () => {
|
|
|
44
45
|
p1: $T.string(),
|
|
45
46
|
p2: $T.number(),
|
|
46
47
|
p3: $T.integer(),
|
|
47
|
-
p4: $T.boolean()
|
|
48
|
-
}
|
|
48
|
+
p4: $T.boolean(),
|
|
49
|
+
},
|
|
49
50
|
},
|
|
50
51
|
ctx => {
|
|
51
52
|
return ctx.params
|
|
@@ -60,8 +61,8 @@ describe('parser', () => {
|
|
|
60
61
|
p2: $T.number(),
|
|
61
62
|
p3: $T.boolean(),
|
|
62
63
|
p4: $T.union([$T.number(), $T.boolean()]),
|
|
63
|
-
p5: $T.optional($T.string())
|
|
64
|
-
}
|
|
64
|
+
p5: $T.optional($T.string()),
|
|
65
|
+
},
|
|
65
66
|
},
|
|
66
67
|
ctx => {
|
|
67
68
|
return ctx.query
|
|
@@ -74,66 +75,86 @@ describe('parser', () => {
|
|
|
74
75
|
default: $T.optional($T.string({ default: 'DEFAULT_VALUE' })),
|
|
75
76
|
int: $T.integer({ exclusiveMin: 10, max: 42 }),
|
|
76
77
|
num: $T.number({ min: 10, exclusiveMax: 42 }),
|
|
77
|
-
str: $T.string({ minLength: 4, maxLength: 8, pattern: /^a.*z/ })
|
|
78
|
-
}
|
|
78
|
+
str: $T.string({ minLength: 4, maxLength: 8, pattern: /^a.*z/ }),
|
|
79
|
+
},
|
|
79
80
|
},
|
|
80
81
|
ctx => {
|
|
81
82
|
return ctx.query
|
|
82
83
|
}
|
|
83
84
|
)
|
|
84
85
|
|
|
85
|
-
galbe.post('/obj/schema/base', { body: $T.object(schema_object) }, handleBody)
|
|
86
|
+
galbe.post('/obj/schema/base', { body: { json: $T.object(schema_object) } }, handleBody)
|
|
86
87
|
|
|
87
88
|
galbe.post(
|
|
88
89
|
'/form/schema/base',
|
|
89
90
|
{
|
|
90
|
-
body:
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
91
|
+
body: {
|
|
92
|
+
urlForm: $T.object({
|
|
93
|
+
...schema_objectBase,
|
|
94
|
+
object: $T.optional($T.object({ nested: $T.object({ foo: $T.literal('bar') }), baz: $T.number() })),
|
|
95
|
+
union: $T.optional($T.union([$T.number(), $T.boolean()])),
|
|
96
|
+
literal: $T.optional($T.literal('x')),
|
|
97
|
+
array: $T.array(),
|
|
98
|
+
}),
|
|
99
|
+
},
|
|
96
100
|
},
|
|
97
101
|
handleBody
|
|
98
102
|
)
|
|
99
103
|
galbe.post(
|
|
100
104
|
'/form/stream/schema/base',
|
|
101
105
|
{
|
|
102
|
-
body:
|
|
103
|
-
$T.
|
|
106
|
+
body: {
|
|
107
|
+
urlForm: $T.stream(
|
|
108
|
+
$T.object({
|
|
109
|
+
...schema_objectBase,
|
|
110
|
+
union: $T.optional($T.union([$T.number(), $T.boolean()])),
|
|
111
|
+
literal: $T.optional($T.literal('x')),
|
|
112
|
+
array: $T.array($T.any()),
|
|
113
|
+
numArray: $T.optional($T.array($T.number())),
|
|
114
|
+
})
|
|
115
|
+
),
|
|
116
|
+
},
|
|
117
|
+
},
|
|
118
|
+
handleUrlFormStream
|
|
119
|
+
)
|
|
120
|
+
galbe.post(
|
|
121
|
+
'/mp/schema/base',
|
|
122
|
+
{
|
|
123
|
+
body: {
|
|
124
|
+
multipart: $T.multipartForm({
|
|
104
125
|
...schema_objectBase,
|
|
105
126
|
union: $T.optional($T.union([$T.number(), $T.boolean()])),
|
|
106
127
|
literal: $T.optional($T.literal('x')),
|
|
107
128
|
array: $T.array($T.any()),
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
)
|
|
129
|
+
}),
|
|
130
|
+
},
|
|
111
131
|
},
|
|
112
|
-
|
|
132
|
+
handleBody
|
|
113
133
|
)
|
|
114
134
|
galbe.post(
|
|
115
|
-
'/mp/schema/
|
|
135
|
+
'/mp/schema/file',
|
|
116
136
|
{
|
|
117
|
-
body:
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
})
|
|
137
|
+
body: {
|
|
138
|
+
multipart: $T.multipartForm({
|
|
139
|
+
foo: $T.byteArray(),
|
|
140
|
+
}),
|
|
141
|
+
},
|
|
123
142
|
},
|
|
124
143
|
handleBody
|
|
125
144
|
)
|
|
126
145
|
galbe.post(
|
|
127
146
|
'/mp/stream/schema/base',
|
|
128
147
|
{
|
|
129
|
-
body:
|
|
130
|
-
$T.
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
148
|
+
body: {
|
|
149
|
+
multipart: $T.stream(
|
|
150
|
+
$T.multipartForm({
|
|
151
|
+
...schema_objectBase,
|
|
152
|
+
union: $T.optional($T.union([$T.number(), $T.boolean()])),
|
|
153
|
+
literal: $T.optional($T.literal('x')),
|
|
154
|
+
array: $T.array($T.any()),
|
|
155
|
+
})
|
|
156
|
+
),
|
|
157
|
+
},
|
|
137
158
|
},
|
|
138
159
|
handleBody
|
|
139
160
|
)
|
|
@@ -144,17 +165,21 @@ describe('parser', () => {
|
|
|
144
165
|
bool: $T.boolean(),
|
|
145
166
|
arrayStr: $T.array($T.string()),
|
|
146
167
|
arrayNumber: $T.array($T.number()),
|
|
147
|
-
arrayBool: $T.array($T.boolean())
|
|
168
|
+
arrayBool: $T.array($T.boolean()),
|
|
148
169
|
}
|
|
149
170
|
|
|
150
171
|
galbe.post(
|
|
151
172
|
'/mp/file',
|
|
152
|
-
{ body: $T.multipartForm({ imgFile: $T.byteArray(), jsonFile: $T.object(schema_jsonFile) }) },
|
|
173
|
+
{ body: { multipart: $T.multipartForm({ imgFile: $T.byteArray(), jsonFile: $T.object(schema_jsonFile) }) } },
|
|
153
174
|
handleBody
|
|
154
175
|
)
|
|
155
176
|
galbe.post(
|
|
156
177
|
'/mp/stream/file',
|
|
157
|
-
{
|
|
178
|
+
{
|
|
179
|
+
body: {
|
|
180
|
+
multipart: $T.stream($T.multipartForm({ imgFile: $T.byteArray(), jsonFile: $T.object(schema_jsonFile) })),
|
|
181
|
+
},
|
|
182
|
+
},
|
|
158
183
|
async ctx => {
|
|
159
184
|
if (isAsyncIterator(ctx.body)) {
|
|
160
185
|
const chunks: any[] = []
|
|
@@ -169,14 +194,14 @@ describe('parser', () => {
|
|
|
169
194
|
}
|
|
170
195
|
}
|
|
171
196
|
)
|
|
172
|
-
galbe.post('/ba/file', { body: $T.byteArray() }, async ctx => {
|
|
197
|
+
galbe.post('/ba/file', { body: { byteArray: $T.byteArray() } }, async ctx => {
|
|
173
198
|
if (ctx?.body instanceof Uint8Array) {
|
|
174
199
|
return { type: 'byteArray', content: await fileHash(ctx.body) }
|
|
175
200
|
} else {
|
|
176
201
|
return { type: null, content: 'error' }
|
|
177
202
|
}
|
|
178
203
|
})
|
|
179
|
-
galbe.post('/ba/stream/file', { body: $T.stream($T.byteArray()) }, async ctx => {
|
|
204
|
+
galbe.post('/ba/stream/file', { body: { byteArray: $T.stream($T.byteArray()) } }, async ctx => {
|
|
180
205
|
if (isAsyncIterator(ctx.body)) {
|
|
181
206
|
let bytes = new Uint8Array()
|
|
182
207
|
for await (const b of ctx.body) {
|
|
@@ -202,7 +227,7 @@ describe('parser', () => {
|
|
|
202
227
|
float: '3.14',
|
|
203
228
|
integer: '42',
|
|
204
229
|
'boolean-true': 'true',
|
|
205
|
-
'boolean-false': 'false'
|
|
230
|
+
'boolean-false': 'false',
|
|
206
231
|
},
|
|
207
232
|
expected: {
|
|
208
233
|
body: {
|
|
@@ -213,9 +238,9 @@ describe('parser', () => {
|
|
|
213
238
|
float: 3.14,
|
|
214
239
|
integer: 42,
|
|
215
240
|
'boolean-true': true,
|
|
216
|
-
'boolean-false': false
|
|
217
|
-
}
|
|
218
|
-
}
|
|
241
|
+
'boolean-false': false,
|
|
242
|
+
},
|
|
243
|
+
},
|
|
219
244
|
},
|
|
220
245
|
{
|
|
221
246
|
h: {
|
|
@@ -225,18 +250,18 @@ describe('parser', () => {
|
|
|
225
250
|
float: '3.14',
|
|
226
251
|
integer: '42',
|
|
227
252
|
'boolean-true': 'a',
|
|
228
|
-
'boolean-false': 'false'
|
|
253
|
+
'boolean-false': 'false',
|
|
229
254
|
},
|
|
230
255
|
expected: {
|
|
231
256
|
status: 400,
|
|
232
257
|
body: {
|
|
233
258
|
headers: {
|
|
234
259
|
'neg-number': 'Required',
|
|
235
|
-
'boolean-true': "Not a valid boolean. Should be 'true' or 'false'"
|
|
236
|
-
}
|
|
237
|
-
}
|
|
238
|
-
}
|
|
239
|
-
}
|
|
260
|
+
'boolean-true': "Not a valid boolean. Should be 'true' or 'false'",
|
|
261
|
+
},
|
|
262
|
+
},
|
|
263
|
+
},
|
|
264
|
+
},
|
|
240
265
|
]
|
|
241
266
|
|
|
242
267
|
for (let { h, expected } of cases) {
|
|
@@ -251,7 +276,7 @@ describe('parser', () => {
|
|
|
251
276
|
const cases: any = [
|
|
252
277
|
{
|
|
253
278
|
p: { p1: 'one', p2: '3.14', p3: '42', p4: 'true' },
|
|
254
|
-
expected: { body: { p1: 'one', p2: 3.14, p3: 42, p4: true } }
|
|
279
|
+
expected: { body: { p1: 'one', p2: 3.14, p3: 42, p4: true } },
|
|
255
280
|
},
|
|
256
281
|
{
|
|
257
282
|
p: { p1: '_', p2: 'test', p3: '42.5', p4: 'a' },
|
|
@@ -261,11 +286,11 @@ describe('parser', () => {
|
|
|
261
286
|
params: {
|
|
262
287
|
p2: 'Not a valid number',
|
|
263
288
|
p3: 'Not a valid integer',
|
|
264
|
-
p4: "Not a valid boolean. Should be 'true' or 'false'"
|
|
265
|
-
}
|
|
266
|
-
}
|
|
267
|
-
}
|
|
268
|
-
}
|
|
289
|
+
p4: "Not a valid boolean. Should be 'true' or 'false'",
|
|
290
|
+
},
|
|
291
|
+
},
|
|
292
|
+
},
|
|
293
|
+
},
|
|
269
294
|
]
|
|
270
295
|
for (let { p, expected } of cases) {
|
|
271
296
|
let resp = await fetch(`http://localhost:${port}/params/schema/${p.p1}/${p.p2}/${p.p3}/${p.p4}`)
|
|
@@ -279,11 +304,11 @@ describe('parser', () => {
|
|
|
279
304
|
const cases: any = [
|
|
280
305
|
{
|
|
281
306
|
p: { p1: 'one', p2: '3.14', p3: 'false', p4: '42' },
|
|
282
|
-
expected: { body: { p1: 'one', p2: 3.14, p3: false, p4: 42 } }
|
|
307
|
+
expected: { body: { p1: 'one', p2: 3.14, p3: false, p4: 42 } },
|
|
283
308
|
},
|
|
284
309
|
{
|
|
285
310
|
p: { p1: 'one', p2: '3.14', p3: 'true', p4: 'true', p5: 'hello' },
|
|
286
|
-
expected: { body: { p1: 'one', p2: 3.14, p3: true, p4: true, p5: 'hello' } }
|
|
311
|
+
expected: { body: { p1: 'one', p2: 3.14, p3: true, p4: true, p5: 'hello' } },
|
|
287
312
|
},
|
|
288
313
|
{
|
|
289
314
|
p: { p1: '36', p2: 'a', p3: '0' },
|
|
@@ -293,11 +318,11 @@ describe('parser', () => {
|
|
|
293
318
|
query: {
|
|
294
319
|
p2: 'Not a valid number',
|
|
295
320
|
p3: "Not a valid boolean. Should be 'true' or 'false'",
|
|
296
|
-
p4: 'Required'
|
|
297
|
-
}
|
|
298
|
-
}
|
|
299
|
-
}
|
|
300
|
-
}
|
|
321
|
+
p4: 'Required',
|
|
322
|
+
},
|
|
323
|
+
},
|
|
324
|
+
},
|
|
325
|
+
},
|
|
301
326
|
]
|
|
302
327
|
|
|
303
328
|
for (let { p, expected } of cases) {
|
|
@@ -312,6 +337,21 @@ describe('parser', () => {
|
|
|
312
337
|
}
|
|
313
338
|
})
|
|
314
339
|
|
|
340
|
+
test('query params, duplicates', async () => {
|
|
341
|
+
const search = new URLSearchParams()
|
|
342
|
+
search.append('p1', 'one')
|
|
343
|
+
search.append('p1', 'two')
|
|
344
|
+
search.append('p2', '3.14')
|
|
345
|
+
search.append('p3', 'true')
|
|
346
|
+
search.append('p4', '42')
|
|
347
|
+
|
|
348
|
+
let resp = await fetch(`http://localhost:${port}/query/params/schema?${search.toString()}`)
|
|
349
|
+
let body = await resp.json()
|
|
350
|
+
|
|
351
|
+
expect(resp.status).toBe(400)
|
|
352
|
+
expect(body).toEqual({ query: { p1: 'Multiple values found' } })
|
|
353
|
+
})
|
|
354
|
+
|
|
315
355
|
test('body, json, schema object', async () => {
|
|
316
356
|
const type = 'application/json'
|
|
317
357
|
const schema = 'obj/schema/base'
|
|
@@ -327,7 +367,7 @@ describe('parser', () => {
|
|
|
327
367
|
any: false,
|
|
328
368
|
null: null,
|
|
329
369
|
nullable: null,
|
|
330
|
-
nullish: 42
|
|
370
|
+
nullish: 42,
|
|
331
371
|
}),
|
|
332
372
|
type,
|
|
333
373
|
schema,
|
|
@@ -344,9 +384,9 @@ describe('parser', () => {
|
|
|
344
384
|
any: false,
|
|
345
385
|
null: null,
|
|
346
386
|
nullable: null,
|
|
347
|
-
nullish: 42
|
|
348
|
-
}
|
|
349
|
-
}
|
|
387
|
+
nullish: 42,
|
|
388
|
+
},
|
|
389
|
+
},
|
|
350
390
|
},
|
|
351
391
|
{
|
|
352
392
|
body: JSON.stringify({
|
|
@@ -360,7 +400,7 @@ describe('parser', () => {
|
|
|
360
400
|
optional: 'optional',
|
|
361
401
|
null: null,
|
|
362
402
|
nullable: 'test',
|
|
363
|
-
nullish: null
|
|
403
|
+
nullish: null,
|
|
364
404
|
}),
|
|
365
405
|
type,
|
|
366
406
|
schema,
|
|
@@ -378,9 +418,9 @@ describe('parser', () => {
|
|
|
378
418
|
optional: 'optional',
|
|
379
419
|
null: null,
|
|
380
420
|
nullable: 'test',
|
|
381
|
-
nullish: null
|
|
382
|
-
}
|
|
383
|
-
}
|
|
421
|
+
nullish: null,
|
|
422
|
+
},
|
|
423
|
+
},
|
|
384
424
|
},
|
|
385
425
|
{
|
|
386
426
|
body: JSON.stringify({
|
|
@@ -391,7 +431,7 @@ describe('parser', () => {
|
|
|
391
431
|
object: [],
|
|
392
432
|
array: {},
|
|
393
433
|
any: {},
|
|
394
|
-
null: ''
|
|
434
|
+
null: '',
|
|
395
435
|
}),
|
|
396
436
|
type,
|
|
397
437
|
schema,
|
|
@@ -406,17 +446,17 @@ describe('parser', () => {
|
|
|
406
446
|
object: 'Expected an object, not an array',
|
|
407
447
|
array: 'Not a valid array',
|
|
408
448
|
null: 'Expected null value got ',
|
|
409
|
-
nullable: 'Required'
|
|
410
|
-
}
|
|
411
|
-
}
|
|
412
|
-
}
|
|
413
|
-
}
|
|
449
|
+
nullable: 'Required',
|
|
450
|
+
},
|
|
451
|
+
},
|
|
452
|
+
},
|
|
453
|
+
},
|
|
414
454
|
]
|
|
415
455
|
for (let { body, type, schema, expected } of cases) {
|
|
416
456
|
let resp = await fetch(`http://localhost:${port}/${schema}`, {
|
|
417
457
|
method: 'POST',
|
|
418
458
|
body,
|
|
419
|
-
headers: { ...(type ? { 'content-type': type } : {}) }
|
|
459
|
+
headers: { ...(type ? { 'content-type': type } : {}) },
|
|
420
460
|
})
|
|
421
461
|
let respBody = (await resp.json()) as { type: string; content: any }
|
|
422
462
|
|
|
@@ -445,15 +485,15 @@ describe('parser', () => {
|
|
|
445
485
|
status: 200,
|
|
446
486
|
type: 'object',
|
|
447
487
|
resp: {
|
|
448
|
-
ba:
|
|
488
|
+
ba: EMPTY_BA_STR,
|
|
449
489
|
string: '',
|
|
450
490
|
number: 0,
|
|
451
491
|
bool: false,
|
|
452
492
|
any: 'false',
|
|
453
493
|
union: true,
|
|
454
|
-
array: []
|
|
455
|
-
}
|
|
456
|
-
}
|
|
494
|
+
array: [],
|
|
495
|
+
},
|
|
496
|
+
},
|
|
457
497
|
},
|
|
458
498
|
{
|
|
459
499
|
body: 'ba=Hello&string=Mom!&number=42&bool=true&any=36&optional=optional&array=1&array=2&literal=x&union=42',
|
|
@@ -471,9 +511,9 @@ describe('parser', () => {
|
|
|
471
511
|
optional: 'optional',
|
|
472
512
|
literal: 'x',
|
|
473
513
|
union: 42,
|
|
474
|
-
array: ['1', '2']
|
|
475
|
-
}
|
|
476
|
-
}
|
|
514
|
+
array: ['1', '2'],
|
|
515
|
+
},
|
|
516
|
+
},
|
|
477
517
|
},
|
|
478
518
|
{
|
|
479
519
|
body: 'optional=optional',
|
|
@@ -483,9 +523,9 @@ describe('parser', () => {
|
|
|
483
523
|
status: 400,
|
|
484
524
|
type: 'object',
|
|
485
525
|
resp: {
|
|
486
|
-
body: 'Missing fields: ba, string, number, bool, any'
|
|
487
|
-
}
|
|
488
|
-
}
|
|
526
|
+
body: 'Missing fields: ba, string, number, bool, any',
|
|
527
|
+
},
|
|
528
|
+
},
|
|
489
529
|
},
|
|
490
530
|
{
|
|
491
531
|
body: 'ba=&string=Hello&string=Mom!&number=aaa&bool=1&any=36&literal=y&union=X',
|
|
@@ -499,20 +539,60 @@ describe('parser', () => {
|
|
|
499
539
|
number: 'Not a valid number',
|
|
500
540
|
bool: "Not a valid boolean. Should be 'true' or 'false'",
|
|
501
541
|
literal: 'Not a valid value',
|
|
502
|
-
union: 'Could not be parsed to any of [number, boolean]'
|
|
503
|
-
}
|
|
504
|
-
}
|
|
505
|
-
}
|
|
506
|
-
}
|
|
542
|
+
union: 'Could not be parsed to any of [number, boolean]',
|
|
543
|
+
},
|
|
544
|
+
},
|
|
545
|
+
},
|
|
546
|
+
},
|
|
547
|
+
{
|
|
548
|
+
body: 'object=%7B%22nested%22%3A%7B%22foo%22%3A%22bar%22%7D%2C%22baz%22%3A42%7D&ba=&string=&number=0&bool=false&any=any',
|
|
549
|
+
type,
|
|
550
|
+
schema,
|
|
551
|
+
expected: {
|
|
552
|
+
status: 200,
|
|
553
|
+
resp: {
|
|
554
|
+
object: { nested: { foo: 'bar' }, baz: 42 },
|
|
555
|
+
any: 'any',
|
|
556
|
+
string: '',
|
|
557
|
+
array: [],
|
|
558
|
+
ba: EMPTY_BA_STR,
|
|
559
|
+
bool: false,
|
|
560
|
+
number: 0,
|
|
561
|
+
},
|
|
562
|
+
},
|
|
563
|
+
},
|
|
564
|
+
{
|
|
565
|
+
body: 'object=&ba=&string=&number=0&bool=false&any=any',
|
|
566
|
+
type,
|
|
567
|
+
schema,
|
|
568
|
+
expected: {
|
|
569
|
+
status: 400,
|
|
570
|
+
resp: {
|
|
571
|
+
body: { object: 'Not a valid object' },
|
|
572
|
+
},
|
|
573
|
+
},
|
|
574
|
+
},
|
|
575
|
+
{
|
|
576
|
+
body: 'object=%7B%22nested%22%3A%7B%22foo%22%3A%22toto%22%7D%2C%22baz%22%3A42%7D&ba=&string=&number=0&bool=false&any=any',
|
|
577
|
+
type,
|
|
578
|
+
schema,
|
|
579
|
+
expected: {
|
|
580
|
+
status: 400,
|
|
581
|
+
resp: {
|
|
582
|
+
body: { object: { nested: { foo: 'Not a valid value. Found "toto" but expected "bar"' } } },
|
|
583
|
+
},
|
|
584
|
+
},
|
|
585
|
+
},
|
|
507
586
|
]
|
|
508
587
|
for (let { body, type, schema, expected } of cases) {
|
|
509
588
|
let resp = await fetch(`http://localhost:${port}/${schema}`, {
|
|
510
589
|
method: 'POST',
|
|
511
590
|
body,
|
|
512
|
-
headers: { ...(type ? { 'content-type': type } : {}) }
|
|
591
|
+
headers: { ...(type ? { 'content-type': type } : {}) },
|
|
513
592
|
})
|
|
514
593
|
let respBody = (await resp.json()) as { type: string; content: any }
|
|
515
594
|
|
|
595
|
+
console.log(respBody)
|
|
516
596
|
expect(resp.status).toBe(expected.status)
|
|
517
597
|
if (resp.status === 200) {
|
|
518
598
|
if (expected.type) expect(respBody.type).toEqual(expected.type)
|
|
@@ -544,9 +624,9 @@ describe('parser', () => {
|
|
|
544
624
|
bool: false,
|
|
545
625
|
any: 'false',
|
|
546
626
|
union: true,
|
|
547
|
-
array: []
|
|
548
|
-
}
|
|
549
|
-
}
|
|
627
|
+
array: [],
|
|
628
|
+
},
|
|
629
|
+
},
|
|
550
630
|
},
|
|
551
631
|
{
|
|
552
632
|
body: 'ba=Hello&string=Mom!&number=42&bool=true&any=36&optional=optional&array=1&array=2&literal=x&union=42',
|
|
@@ -564,9 +644,9 @@ describe('parser', () => {
|
|
|
564
644
|
optional: 'optional',
|
|
565
645
|
literal: 'x',
|
|
566
646
|
union: 42,
|
|
567
|
-
array: ['1', '2']
|
|
568
|
-
}
|
|
569
|
-
}
|
|
647
|
+
array: ['1', '2'],
|
|
648
|
+
},
|
|
649
|
+
},
|
|
570
650
|
},
|
|
571
651
|
{
|
|
572
652
|
body: 'ba=Hello&string=Mom!&number=42&bool=true&any=36&optional=optional&array=1&array=2&literal=x&union=42&numArray=x',
|
|
@@ -576,9 +656,9 @@ describe('parser', () => {
|
|
|
576
656
|
status: 400,
|
|
577
657
|
type: 'object',
|
|
578
658
|
resp: {
|
|
579
|
-
body: { numArray: 'Not a valid number' }
|
|
580
|
-
}
|
|
581
|
-
}
|
|
659
|
+
body: { numArray: 'Not a valid number' },
|
|
660
|
+
},
|
|
661
|
+
},
|
|
582
662
|
},
|
|
583
663
|
{
|
|
584
664
|
body: 'ba=&string=Hello&string=Mom!&number=1&bool=true&any=36&literal=y&union=X',
|
|
@@ -588,10 +668,10 @@ describe('parser', () => {
|
|
|
588
668
|
status: 400,
|
|
589
669
|
resp: {
|
|
590
670
|
body: {
|
|
591
|
-
literal: 'Not a valid value'
|
|
592
|
-
}
|
|
593
|
-
}
|
|
594
|
-
}
|
|
671
|
+
literal: 'Not a valid value',
|
|
672
|
+
},
|
|
673
|
+
},
|
|
674
|
+
},
|
|
595
675
|
},
|
|
596
676
|
{
|
|
597
677
|
body: 'optional=otpional',
|
|
@@ -600,16 +680,16 @@ describe('parser', () => {
|
|
|
600
680
|
expected: {
|
|
601
681
|
status: 400,
|
|
602
682
|
resp: {
|
|
603
|
-
body: 'Missing fields: ba, string, number, bool, any'
|
|
604
|
-
}
|
|
605
|
-
}
|
|
606
|
-
}
|
|
683
|
+
body: 'Missing fields: ba, string, number, bool, any',
|
|
684
|
+
},
|
|
685
|
+
},
|
|
686
|
+
},
|
|
607
687
|
]
|
|
608
688
|
for (let { body, type, schema, expected } of cases) {
|
|
609
689
|
let resp = await fetch(`http://localhost:${port}/${schema}`, {
|
|
610
690
|
method: 'POST',
|
|
611
691
|
body,
|
|
612
|
-
headers: { ...(type ? { 'content-type': type } : {}) }
|
|
692
|
+
headers: { ...(type ? { 'content-type': type } : {}) },
|
|
613
693
|
})
|
|
614
694
|
let respBody = (await resp.json()) as any
|
|
615
695
|
|
|
@@ -628,6 +708,9 @@ describe('parser', () => {
|
|
|
628
708
|
test('body, MultipartForm, schema object', async () => {
|
|
629
709
|
const schema = 'mp/schema/base'
|
|
630
710
|
|
|
711
|
+
const formWithHeader = formdata({})
|
|
712
|
+
formWithHeader.append('foo', new Blob([new Uint8Array()], { type: 'image/png' }), 'foo.png')
|
|
713
|
+
|
|
631
714
|
const cases: Case[] = [
|
|
632
715
|
{
|
|
633
716
|
body: formdata({ ba: '', string: '', number: '0', bool: 'false', any: 'false', union: 'true' }),
|
|
@@ -637,49 +720,67 @@ describe('parser', () => {
|
|
|
637
720
|
type: 'object',
|
|
638
721
|
resp: {
|
|
639
722
|
ba: {
|
|
640
|
-
content:
|
|
723
|
+
content: EMPTY_BA_STR,
|
|
641
724
|
headers: {
|
|
642
|
-
name: 'ba'
|
|
643
|
-
}
|
|
725
|
+
name: 'ba',
|
|
726
|
+
},
|
|
644
727
|
},
|
|
645
728
|
string: {
|
|
646
729
|
content: '',
|
|
647
730
|
headers: {
|
|
648
|
-
name: 'string'
|
|
649
|
-
}
|
|
731
|
+
name: 'string',
|
|
732
|
+
},
|
|
650
733
|
},
|
|
651
734
|
number: {
|
|
652
735
|
content: 0,
|
|
653
736
|
headers: {
|
|
654
|
-
name: 'number'
|
|
655
|
-
}
|
|
737
|
+
name: 'number',
|
|
738
|
+
},
|
|
656
739
|
},
|
|
657
740
|
bool: {
|
|
658
741
|
content: false,
|
|
659
742
|
headers: {
|
|
660
|
-
name: 'bool'
|
|
661
|
-
}
|
|
743
|
+
name: 'bool',
|
|
744
|
+
},
|
|
662
745
|
},
|
|
663
746
|
any: {
|
|
664
747
|
content: 'false',
|
|
665
748
|
headers: {
|
|
666
|
-
name: 'any'
|
|
667
|
-
}
|
|
749
|
+
name: 'any',
|
|
750
|
+
},
|
|
668
751
|
},
|
|
669
752
|
union: {
|
|
670
753
|
content: true,
|
|
671
754
|
headers: {
|
|
672
|
-
name: 'union'
|
|
673
|
-
}
|
|
755
|
+
name: 'union',
|
|
756
|
+
},
|
|
674
757
|
},
|
|
675
758
|
array: {
|
|
676
759
|
content: [],
|
|
677
760
|
headers: {
|
|
678
|
-
name: 'array'
|
|
679
|
-
}
|
|
680
|
-
}
|
|
681
|
-
}
|
|
682
|
-
}
|
|
761
|
+
name: 'array',
|
|
762
|
+
},
|
|
763
|
+
},
|
|
764
|
+
},
|
|
765
|
+
},
|
|
766
|
+
},
|
|
767
|
+
{
|
|
768
|
+
body: formWithHeader,
|
|
769
|
+
schema: 'mp/schema/file',
|
|
770
|
+
expected: {
|
|
771
|
+
status: 200,
|
|
772
|
+
type: 'object',
|
|
773
|
+
resp: {
|
|
774
|
+
foo: {
|
|
775
|
+
content: EMPTY_BA_STR,
|
|
776
|
+
headers: {
|
|
777
|
+
name: 'foo',
|
|
778
|
+
filename: 'foo.png',
|
|
779
|
+
type: 'image/png',
|
|
780
|
+
},
|
|
781
|
+
},
|
|
782
|
+
},
|
|
783
|
+
},
|
|
683
784
|
},
|
|
684
785
|
{
|
|
685
786
|
body: formdata({
|
|
@@ -691,7 +792,7 @@ describe('parser', () => {
|
|
|
691
792
|
optional: 'optional',
|
|
692
793
|
array: ['1', '2'],
|
|
693
794
|
literal: 'x',
|
|
694
|
-
union: '42'
|
|
795
|
+
union: '42',
|
|
695
796
|
}),
|
|
696
797
|
schema,
|
|
697
798
|
expected: {
|
|
@@ -701,59 +802,59 @@ describe('parser', () => {
|
|
|
701
802
|
ba: {
|
|
702
803
|
content: '185f8db32271fe25f561a6fc938b2e264306ec304eda518007d1764826381969',
|
|
703
804
|
headers: {
|
|
704
|
-
name: 'ba'
|
|
705
|
-
}
|
|
805
|
+
name: 'ba',
|
|
806
|
+
},
|
|
706
807
|
},
|
|
707
808
|
string: {
|
|
708
809
|
content: 'Mom!',
|
|
709
810
|
headers: {
|
|
710
|
-
name: 'string'
|
|
711
|
-
}
|
|
811
|
+
name: 'string',
|
|
812
|
+
},
|
|
712
813
|
},
|
|
713
814
|
number: {
|
|
714
815
|
content: 42,
|
|
715
816
|
headers: {
|
|
716
|
-
name: 'number'
|
|
717
|
-
}
|
|
817
|
+
name: 'number',
|
|
818
|
+
},
|
|
718
819
|
},
|
|
719
820
|
bool: {
|
|
720
821
|
content: true,
|
|
721
822
|
headers: {
|
|
722
|
-
name: 'bool'
|
|
723
|
-
}
|
|
823
|
+
name: 'bool',
|
|
824
|
+
},
|
|
724
825
|
},
|
|
725
826
|
any: {
|
|
726
827
|
content: '36',
|
|
727
828
|
headers: {
|
|
728
|
-
name: 'any'
|
|
729
|
-
}
|
|
829
|
+
name: 'any',
|
|
830
|
+
},
|
|
730
831
|
},
|
|
731
832
|
optional: {
|
|
732
833
|
content: 'optional',
|
|
733
834
|
headers: {
|
|
734
|
-
name: 'optional'
|
|
735
|
-
}
|
|
835
|
+
name: 'optional',
|
|
836
|
+
},
|
|
736
837
|
},
|
|
737
838
|
array: {
|
|
738
839
|
content: ['1', '2'],
|
|
739
840
|
headers: {
|
|
740
|
-
name: 'array'
|
|
741
|
-
}
|
|
841
|
+
name: 'array',
|
|
842
|
+
},
|
|
742
843
|
},
|
|
743
844
|
literal: {
|
|
744
845
|
content: 'x',
|
|
745
846
|
headers: {
|
|
746
|
-
name: 'literal'
|
|
747
|
-
}
|
|
847
|
+
name: 'literal',
|
|
848
|
+
},
|
|
748
849
|
},
|
|
749
850
|
union: {
|
|
750
851
|
content: 42,
|
|
751
852
|
headers: {
|
|
752
|
-
name: 'union'
|
|
753
|
-
}
|
|
754
|
-
}
|
|
755
|
-
}
|
|
756
|
-
}
|
|
853
|
+
name: 'union',
|
|
854
|
+
},
|
|
855
|
+
},
|
|
856
|
+
},
|
|
857
|
+
},
|
|
757
858
|
},
|
|
758
859
|
{
|
|
759
860
|
body: formdata({ optional: 'optional' }),
|
|
@@ -762,9 +863,9 @@ describe('parser', () => {
|
|
|
762
863
|
status: 400,
|
|
763
864
|
type: 'object',
|
|
764
865
|
resp: {
|
|
765
|
-
body: 'Missing fields: ba, string, number, bool, any'
|
|
766
|
-
}
|
|
767
|
-
}
|
|
866
|
+
body: 'Missing fields: ba, string, number, bool, any',
|
|
867
|
+
},
|
|
868
|
+
},
|
|
768
869
|
},
|
|
769
870
|
{
|
|
770
871
|
body: formdata({
|
|
@@ -774,7 +875,7 @@ describe('parser', () => {
|
|
|
774
875
|
bool: '1',
|
|
775
876
|
any: '36',
|
|
776
877
|
literal: 'y',
|
|
777
|
-
union: 'X'
|
|
878
|
+
union: 'X',
|
|
778
879
|
}),
|
|
779
880
|
schema,
|
|
780
881
|
expected: {
|
|
@@ -784,18 +885,18 @@ describe('parser', () => {
|
|
|
784
885
|
string: 'Multiple values found',
|
|
785
886
|
number: 'Not a valid number',
|
|
786
887
|
bool: "Not a valid boolean. Should be 'true' or 'false'",
|
|
787
|
-
literal: 'Not a valid value',
|
|
788
|
-
union: 'Could not be parsed to any of [number, boolean]'
|
|
789
|
-
}
|
|
790
|
-
}
|
|
791
|
-
}
|
|
792
|
-
}
|
|
888
|
+
literal: 'Not a valid value. Found "y" but expected "x"',
|
|
889
|
+
union: 'Could not be parsed to any of [number, boolean]',
|
|
890
|
+
},
|
|
891
|
+
},
|
|
892
|
+
},
|
|
893
|
+
},
|
|
793
894
|
]
|
|
794
895
|
for (let { body, type, schema, expected } of cases) {
|
|
795
896
|
let resp = await fetch(`http://localhost:${port}/${schema}`, {
|
|
796
897
|
method: 'POST',
|
|
797
898
|
body,
|
|
798
|
-
headers: { ...(type ? { 'content-type': type } : {}) }
|
|
899
|
+
headers: { ...(type ? { 'content-type': type } : {}) },
|
|
799
900
|
})
|
|
800
901
|
let respBody = (await resp.json()) as { type: string; content: any }
|
|
801
902
|
|
|
@@ -825,47 +926,47 @@ describe('parser', () => {
|
|
|
825
926
|
{
|
|
826
927
|
content: {},
|
|
827
928
|
headers: {
|
|
828
|
-
name: 'ba'
|
|
829
|
-
}
|
|
929
|
+
name: 'ba',
|
|
930
|
+
},
|
|
830
931
|
},
|
|
831
932
|
{
|
|
832
933
|
content: '',
|
|
833
934
|
headers: {
|
|
834
|
-
name: 'string'
|
|
835
|
-
}
|
|
935
|
+
name: 'string',
|
|
936
|
+
},
|
|
836
937
|
},
|
|
837
938
|
{
|
|
838
939
|
content: 0,
|
|
839
940
|
headers: {
|
|
840
|
-
name: 'number'
|
|
841
|
-
}
|
|
941
|
+
name: 'number',
|
|
942
|
+
},
|
|
842
943
|
},
|
|
843
944
|
{
|
|
844
945
|
content: false,
|
|
845
946
|
headers: {
|
|
846
|
-
name: 'bool'
|
|
847
|
-
}
|
|
947
|
+
name: 'bool',
|
|
948
|
+
},
|
|
848
949
|
},
|
|
849
950
|
{
|
|
850
951
|
content: 'false',
|
|
851
952
|
headers: {
|
|
852
|
-
name: 'any'
|
|
853
|
-
}
|
|
953
|
+
name: 'any',
|
|
954
|
+
},
|
|
854
955
|
},
|
|
855
956
|
{
|
|
856
957
|
content: true,
|
|
857
958
|
headers: {
|
|
858
|
-
name: 'union'
|
|
859
|
-
}
|
|
959
|
+
name: 'union',
|
|
960
|
+
},
|
|
860
961
|
},
|
|
861
962
|
{
|
|
862
963
|
content: [],
|
|
863
964
|
headers: {
|
|
864
|
-
name: 'array'
|
|
865
|
-
}
|
|
866
|
-
}
|
|
867
|
-
]
|
|
868
|
-
}
|
|
965
|
+
name: 'array',
|
|
966
|
+
},
|
|
967
|
+
},
|
|
968
|
+
],
|
|
969
|
+
},
|
|
869
970
|
},
|
|
870
971
|
{
|
|
871
972
|
body: formdata({
|
|
@@ -877,7 +978,7 @@ describe('parser', () => {
|
|
|
877
978
|
optional: 'optional',
|
|
878
979
|
array: ['1', '2'],
|
|
879
980
|
literal: 'x',
|
|
880
|
-
union: '42'
|
|
981
|
+
union: '42',
|
|
881
982
|
}),
|
|
882
983
|
schema,
|
|
883
984
|
expected: {
|
|
@@ -887,65 +988,65 @@ describe('parser', () => {
|
|
|
887
988
|
{
|
|
888
989
|
content: Object.fromEntries(Uint8Array.from('Hello', c => c.charCodeAt(0)).entries()),
|
|
889
990
|
headers: {
|
|
890
|
-
name: 'ba'
|
|
891
|
-
}
|
|
991
|
+
name: 'ba',
|
|
992
|
+
},
|
|
892
993
|
},
|
|
893
994
|
{
|
|
894
995
|
content: 'Mom!',
|
|
895
996
|
headers: {
|
|
896
|
-
name: 'string'
|
|
897
|
-
}
|
|
997
|
+
name: 'string',
|
|
998
|
+
},
|
|
898
999
|
},
|
|
899
1000
|
{
|
|
900
1001
|
content: 42,
|
|
901
1002
|
headers: {
|
|
902
|
-
name: 'number'
|
|
903
|
-
}
|
|
1003
|
+
name: 'number',
|
|
1004
|
+
},
|
|
904
1005
|
},
|
|
905
1006
|
{
|
|
906
1007
|
content: true,
|
|
907
1008
|
headers: {
|
|
908
|
-
name: 'bool'
|
|
909
|
-
}
|
|
1009
|
+
name: 'bool',
|
|
1010
|
+
},
|
|
910
1011
|
},
|
|
911
1012
|
{
|
|
912
1013
|
content: '36',
|
|
913
1014
|
headers: {
|
|
914
|
-
name: 'any'
|
|
915
|
-
}
|
|
1015
|
+
name: 'any',
|
|
1016
|
+
},
|
|
916
1017
|
},
|
|
917
1018
|
{
|
|
918
1019
|
content: 'optional',
|
|
919
1020
|
headers: {
|
|
920
|
-
name: 'optional'
|
|
921
|
-
}
|
|
1021
|
+
name: 'optional',
|
|
1022
|
+
},
|
|
922
1023
|
},
|
|
923
1024
|
{
|
|
924
1025
|
content: '1',
|
|
925
1026
|
headers: {
|
|
926
|
-
name: 'array'
|
|
927
|
-
}
|
|
1027
|
+
name: 'array',
|
|
1028
|
+
},
|
|
928
1029
|
},
|
|
929
1030
|
{
|
|
930
1031
|
content: '2',
|
|
931
1032
|
headers: {
|
|
932
|
-
name: 'array'
|
|
933
|
-
}
|
|
1033
|
+
name: 'array',
|
|
1034
|
+
},
|
|
934
1035
|
},
|
|
935
1036
|
{
|
|
936
1037
|
content: 'x',
|
|
937
1038
|
headers: {
|
|
938
|
-
name: 'literal'
|
|
939
|
-
}
|
|
1039
|
+
name: 'literal',
|
|
1040
|
+
},
|
|
940
1041
|
},
|
|
941
1042
|
{
|
|
942
1043
|
content: 42,
|
|
943
1044
|
headers: {
|
|
944
|
-
name: 'union'
|
|
945
|
-
}
|
|
946
|
-
}
|
|
947
|
-
]
|
|
948
|
-
}
|
|
1045
|
+
name: 'union',
|
|
1046
|
+
},
|
|
1047
|
+
},
|
|
1048
|
+
],
|
|
1049
|
+
},
|
|
949
1050
|
},
|
|
950
1051
|
{
|
|
951
1052
|
body: formdata({ optional: 'optional' }),
|
|
@@ -954,9 +1055,9 @@ describe('parser', () => {
|
|
|
954
1055
|
status: 400,
|
|
955
1056
|
type: 'object',
|
|
956
1057
|
resp: {
|
|
957
|
-
body: 'Missing fields: ba, string, number, bool, any'
|
|
958
|
-
}
|
|
959
|
-
}
|
|
1058
|
+
body: 'Missing fields: ba, string, number, bool, any',
|
|
1059
|
+
},
|
|
1060
|
+
},
|
|
960
1061
|
},
|
|
961
1062
|
{
|
|
962
1063
|
body: formdata({
|
|
@@ -966,24 +1067,24 @@ describe('parser', () => {
|
|
|
966
1067
|
bool: '1',
|
|
967
1068
|
any: '36',
|
|
968
1069
|
literal: 'y',
|
|
969
|
-
union: 'X'
|
|
1070
|
+
union: 'X',
|
|
970
1071
|
}),
|
|
971
1072
|
schema,
|
|
972
1073
|
expected: {
|
|
973
1074
|
status: 400,
|
|
974
1075
|
resp: {
|
|
975
1076
|
body: {
|
|
976
|
-
number: 'Not a valid number'
|
|
977
|
-
}
|
|
978
|
-
}
|
|
979
|
-
}
|
|
980
|
-
}
|
|
1077
|
+
number: 'Not a valid number',
|
|
1078
|
+
},
|
|
1079
|
+
},
|
|
1080
|
+
},
|
|
1081
|
+
},
|
|
981
1082
|
]
|
|
982
1083
|
for (let { body, type, schema, expected } of cases) {
|
|
983
1084
|
let resp = await fetch(`http://localhost:${port}/${schema}`, {
|
|
984
1085
|
method: 'POST',
|
|
985
1086
|
body,
|
|
986
|
-
headers: { ...(type ? { 'content-type': type } : {}) }
|
|
1087
|
+
headers: { ...(type ? { 'content-type': type } : {}) },
|
|
987
1088
|
})
|
|
988
1089
|
let respBody = (await resp.json()) as { type: string; content: any }
|
|
989
1090
|
|
|
@@ -1020,8 +1121,8 @@ describe('parser', () => {
|
|
|
1020
1121
|
headers: {
|
|
1021
1122
|
name: 'imgFile',
|
|
1022
1123
|
filename: 'test/resources/image.png',
|
|
1023
|
-
type: 'image/png'
|
|
1024
|
-
}
|
|
1124
|
+
type: 'image/png',
|
|
1125
|
+
},
|
|
1025
1126
|
},
|
|
1026
1127
|
jsonFile: {
|
|
1027
1128
|
content: {
|
|
@@ -1030,16 +1131,16 @@ describe('parser', () => {
|
|
|
1030
1131
|
bool: true,
|
|
1031
1132
|
arrayStr: ['un', 'deux', 'trois'],
|
|
1032
1133
|
arrayNumber: [0],
|
|
1033
|
-
arrayBool: [true, false]
|
|
1134
|
+
arrayBool: [true, false],
|
|
1034
1135
|
},
|
|
1035
1136
|
headers: {
|
|
1036
1137
|
name: 'jsonFile',
|
|
1037
1138
|
filename: 'test/resources/object.json',
|
|
1038
|
-
type: 'application/json'
|
|
1039
|
-
}
|
|
1040
|
-
}
|
|
1041
|
-
}
|
|
1042
|
-
}
|
|
1139
|
+
type: 'application/json',
|
|
1140
|
+
},
|
|
1141
|
+
},
|
|
1142
|
+
},
|
|
1143
|
+
},
|
|
1043
1144
|
},
|
|
1044
1145
|
{
|
|
1045
1146
|
body: formdata({ imgFile, jsonFile: missingJsonFile }),
|
|
@@ -1047,9 +1148,9 @@ describe('parser', () => {
|
|
|
1047
1148
|
expected: {
|
|
1048
1149
|
status: 400,
|
|
1049
1150
|
resp: {
|
|
1050
|
-
body: { jsonFile: { arrayBool: 'Required', arrayStr: 'Required' } }
|
|
1051
|
-
}
|
|
1052
|
-
}
|
|
1151
|
+
body: { jsonFile: { arrayBool: 'Required', arrayStr: 'Required' } },
|
|
1152
|
+
},
|
|
1153
|
+
},
|
|
1053
1154
|
},
|
|
1054
1155
|
{
|
|
1055
1156
|
body: formdata({ imgFile, jsonFile: badSyntaxJsonFile }),
|
|
@@ -1057,25 +1158,26 @@ describe('parser', () => {
|
|
|
1057
1158
|
expected: {
|
|
1058
1159
|
status: 400,
|
|
1059
1160
|
resp: {
|
|
1060
|
-
body: { jsonFile: "JSON Parse error: Expected '}'" }
|
|
1061
|
-
}
|
|
1062
|
-
}
|
|
1161
|
+
body: { jsonFile: "JSON Parse error: Expected '}'" },
|
|
1162
|
+
},
|
|
1163
|
+
},
|
|
1063
1164
|
},
|
|
1064
1165
|
{
|
|
1065
1166
|
body: imgFileBytes,
|
|
1066
1167
|
schema: '/ba/file',
|
|
1168
|
+
type: 'application/octet-stream',
|
|
1067
1169
|
expected: {
|
|
1068
1170
|
status: 200,
|
|
1069
1171
|
type: 'byteArray',
|
|
1070
|
-
resp: await fileHash(imgFileBytes)
|
|
1071
|
-
}
|
|
1072
|
-
}
|
|
1172
|
+
resp: await fileHash(imgFileBytes),
|
|
1173
|
+
},
|
|
1174
|
+
},
|
|
1073
1175
|
]
|
|
1074
1176
|
for (let { body, type, schema, expected } of cases) {
|
|
1075
1177
|
let resp = await fetch(`http://localhost:${port}/${schema}`, {
|
|
1076
1178
|
method: 'POST',
|
|
1077
1179
|
body,
|
|
1078
|
-
headers: { ...(type ? { 'content-type': type } : {}) }
|
|
1180
|
+
headers: { ...(type ? { 'content-type': type } : {}) },
|
|
1079
1181
|
})
|
|
1080
1182
|
let respBody = (await resp.json()) as { type: string; content: any }
|
|
1081
1183
|
|
|
@@ -1112,8 +1214,8 @@ describe('parser', () => {
|
|
|
1112
1214
|
headers: {
|
|
1113
1215
|
name: 'imgFile',
|
|
1114
1216
|
filename: 'test/resources/image.png',
|
|
1115
|
-
type: 'image/png'
|
|
1116
|
-
}
|
|
1217
|
+
type: 'image/png',
|
|
1218
|
+
},
|
|
1117
1219
|
},
|
|
1118
1220
|
{
|
|
1119
1221
|
content: {
|
|
@@ -1122,16 +1224,16 @@ describe('parser', () => {
|
|
|
1122
1224
|
bool: true,
|
|
1123
1225
|
arrayStr: ['un', 'deux', 'trois'],
|
|
1124
1226
|
arrayNumber: [0],
|
|
1125
|
-
arrayBool: [true, false]
|
|
1227
|
+
arrayBool: [true, false],
|
|
1126
1228
|
},
|
|
1127
1229
|
headers: {
|
|
1128
1230
|
name: 'jsonFile',
|
|
1129
1231
|
filename: 'test/resources/object.json',
|
|
1130
|
-
type: 'application/json'
|
|
1131
|
-
}
|
|
1132
|
-
}
|
|
1133
|
-
]
|
|
1134
|
-
}
|
|
1232
|
+
type: 'application/json',
|
|
1233
|
+
},
|
|
1234
|
+
},
|
|
1235
|
+
],
|
|
1236
|
+
},
|
|
1135
1237
|
},
|
|
1136
1238
|
{
|
|
1137
1239
|
body: formdata({ imgFile, jsonFile: missingJsonFile }),
|
|
@@ -1139,9 +1241,9 @@ describe('parser', () => {
|
|
|
1139
1241
|
expected: {
|
|
1140
1242
|
status: 400,
|
|
1141
1243
|
resp: {
|
|
1142
|
-
body: { jsonFile: { arrayBool: 'Required', arrayStr: 'Required' } }
|
|
1143
|
-
}
|
|
1144
|
-
}
|
|
1244
|
+
body: { jsonFile: { arrayBool: 'Required', arrayStr: 'Required' } },
|
|
1245
|
+
},
|
|
1246
|
+
},
|
|
1145
1247
|
},
|
|
1146
1248
|
{
|
|
1147
1249
|
body: formdata({ imgFile, jsonFile: badSyntaxJsonFile }),
|
|
@@ -1149,25 +1251,26 @@ describe('parser', () => {
|
|
|
1149
1251
|
expected: {
|
|
1150
1252
|
status: 400,
|
|
1151
1253
|
resp: {
|
|
1152
|
-
body: { jsonFile: "JSON Parse error: Expected '}'" }
|
|
1153
|
-
}
|
|
1154
|
-
}
|
|
1254
|
+
body: { jsonFile: "JSON Parse error: Expected '}'" },
|
|
1255
|
+
},
|
|
1256
|
+
},
|
|
1155
1257
|
},
|
|
1156
1258
|
{
|
|
1157
1259
|
body: imgFileBytes,
|
|
1158
1260
|
schema: '/ba/stream/file',
|
|
1261
|
+
type: 'application/octet-stream',
|
|
1159
1262
|
expected: {
|
|
1160
1263
|
status: 200,
|
|
1161
1264
|
type: 'AsyncIterator',
|
|
1162
|
-
resp: await fileHash(imgFileBytes)
|
|
1163
|
-
}
|
|
1164
|
-
}
|
|
1265
|
+
resp: await fileHash(imgFileBytes),
|
|
1266
|
+
},
|
|
1267
|
+
},
|
|
1165
1268
|
]
|
|
1166
1269
|
for (let { body, type, schema, expected } of cases) {
|
|
1167
1270
|
let resp = await fetch(`http://localhost:${port}/${schema}`, {
|
|
1168
1271
|
method: 'POST',
|
|
1169
1272
|
body,
|
|
1170
|
-
headers: { ...(type ? { 'content-type': type } : {}) }
|
|
1273
|
+
headers: { ...(type ? { 'content-type': type } : {}) },
|
|
1171
1274
|
})
|
|
1172
1275
|
let respBody = (await resp.json()) as { type: string; content: any }
|
|
1173
1276
|
|
|
@@ -1187,11 +1290,11 @@ describe('parser', () => {
|
|
|
1187
1290
|
const cases: any = [
|
|
1188
1291
|
{
|
|
1189
1292
|
p: { int: '11', num: '10', str: 'aaaz' },
|
|
1190
|
-
expected: { body: { default: 'DEFAULT_VALUE', int: 11, num: 10, str: 'aaaz' } }
|
|
1293
|
+
expected: { body: { default: 'DEFAULT_VALUE', int: 11, num: 10, str: 'aaaz' } },
|
|
1191
1294
|
},
|
|
1192
1295
|
{
|
|
1193
1296
|
p: { default: '', int: '42', num: '41.5', str: 'a______z' },
|
|
1194
|
-
expected: { body: { default: '', int: 42, num: 41.5, str: 'a______z' } }
|
|
1297
|
+
expected: { body: { default: '', int: 42, num: 41.5, str: 'a______z' } },
|
|
1195
1298
|
},
|
|
1196
1299
|
{
|
|
1197
1300
|
p: { int: '10', num: '42.01', str: 'xxxxxxxxxx' },
|
|
@@ -1201,11 +1304,11 @@ describe('parser', () => {
|
|
|
1201
1304
|
query: {
|
|
1202
1305
|
int: 'Is less or equal to 10',
|
|
1203
1306
|
num: 'Is greater or equal to 42',
|
|
1204
|
-
str: ['Length is too large (8 char max)', 'Does not match pattern /^a.*z/']
|
|
1205
|
-
}
|
|
1206
|
-
}
|
|
1207
|
-
}
|
|
1208
|
-
}
|
|
1307
|
+
str: ['Length is too large (8 char max)', 'Does not match pattern /^a.*z/'],
|
|
1308
|
+
},
|
|
1309
|
+
},
|
|
1310
|
+
},
|
|
1311
|
+
},
|
|
1209
1312
|
]
|
|
1210
1313
|
|
|
1211
1314
|
for (let { p, expected } of cases) {
|
|
@@ -1232,24 +1335,24 @@ describe('parser', () => {
|
|
|
1232
1335
|
literal: $T.literal('literal'),
|
|
1233
1336
|
array: $T.array($T.string()),
|
|
1234
1337
|
object: $T.object({
|
|
1235
|
-
foo: $T.string()
|
|
1338
|
+
foo: $T.string(),
|
|
1236
1339
|
}),
|
|
1237
|
-
union: $T.union([$T.number(), $T.string()])
|
|
1340
|
+
union: $T.union([$T.number(), $T.string()]),
|
|
1238
1341
|
})
|
|
1239
1342
|
)
|
|
1240
1343
|
expect(type).toBe(
|
|
1241
1344
|
`{` +
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1345
|
+
`'boolean':boolean;` +
|
|
1346
|
+
`'byteArray':Uint8Array;` +
|
|
1347
|
+
`'number':number;` +
|
|
1348
|
+
`'integer':number;` +
|
|
1349
|
+
`'string':string;` +
|
|
1350
|
+
`'any':any;` +
|
|
1351
|
+
`'literal':'literal';` +
|
|
1352
|
+
`'array':Array<string>;` +
|
|
1353
|
+
`'object':{'foo':string};` +
|
|
1354
|
+
`'union':number|string` +
|
|
1355
|
+
`}`
|
|
1253
1356
|
)
|
|
1254
1357
|
})
|
|
1255
1358
|
})
|