fastify 5.3.2 → 5.4.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.
Files changed (103) hide show
  1. package/README.md +2 -0
  2. package/build/build-validation.js +2 -1
  3. package/docs/Guides/Delay-Accepting-Requests.md +3 -3
  4. package/docs/Guides/Ecosystem.md +16 -7
  5. package/docs/Guides/Serverless.md +28 -69
  6. package/docs/Reference/ContentTypeParser.md +1 -1
  7. package/docs/Reference/Errors.md +2 -4
  8. package/docs/Reference/Hooks.md +14 -14
  9. package/docs/Reference/Logging.md +3 -3
  10. package/docs/Reference/Middleware.md +1 -1
  11. package/docs/Reference/Reply.md +8 -8
  12. package/docs/Reference/Request.md +1 -1
  13. package/docs/Reference/Routes.md +3 -3
  14. package/docs/Reference/Server.md +40 -10
  15. package/docs/Reference/Validation-and-Serialization.md +1 -1
  16. package/eslint.config.js +17 -9
  17. package/fastify.d.ts +2 -1
  18. package/fastify.js +20 -4
  19. package/lib/configValidator.js +1 -1
  20. package/lib/decorate.js +2 -2
  21. package/lib/errors.js +6 -8
  22. package/lib/logger-factory.js +1 -1
  23. package/lib/logger-pino.js +2 -2
  24. package/lib/pluginOverride.js +3 -1
  25. package/lib/reply.js +9 -13
  26. package/lib/request.js +4 -11
  27. package/lib/server.js +30 -51
  28. package/lib/symbols.js +1 -0
  29. package/lib/warnings.js +8 -0
  30. package/package.json +11 -7
  31. package/test/404s.test.js +226 -325
  32. package/test/allow-unsafe-regex.test.js +19 -48
  33. package/test/als.test.js +28 -40
  34. package/test/async-await.test.js +11 -2
  35. package/test/body-limit.test.js +41 -65
  36. package/test/build-certificate.js +1 -1
  37. package/test/close-pipelining.test.js +5 -4
  38. package/test/custom-parser-async.test.js +17 -22
  39. package/test/decorator-namespace.test._js_ +3 -4
  40. package/test/decorator.test.js +422 -341
  41. package/test/diagnostics-channel/async-delay-request.test.js +7 -16
  42. package/test/diagnostics-channel/sync-delay-request.test.js +7 -16
  43. package/test/helper.js +108 -70
  44. package/test/hooks-async.test.js +248 -218
  45. package/test/hooks.on-listen.test.js +255 -239
  46. package/test/hooks.on-ready.test.js +110 -92
  47. package/test/hooks.test.js +910 -769
  48. package/test/http-methods/lock.test.js +31 -31
  49. package/test/http-methods/mkcol.test.js +5 -9
  50. package/test/http-methods/proppatch.test.js +23 -29
  51. package/test/http-methods/report.test.js +44 -69
  52. package/test/http-methods/search.test.js +67 -82
  53. package/test/http2/closing.test.js +38 -20
  54. package/test/http2/secure-with-fallback.test.js +28 -27
  55. package/test/https/https.test.js +56 -53
  56. package/test/inject.test.js +114 -97
  57. package/test/input-validation.js +63 -53
  58. package/test/internals/errors.test.js +0 -10
  59. package/test/internals/handle-request.test.js +49 -66
  60. package/test/internals/hooks.test.js +17 -0
  61. package/test/issue-4959.test.js +14 -5
  62. package/test/listen.4.test.js +31 -43
  63. package/test/logger/response.test.js +19 -20
  64. package/test/nullable-validation.test.js +33 -46
  65. package/test/options.error-handler.test.js +1 -1
  66. package/test/options.test.js +1 -1
  67. package/test/output-validation.test.js +49 -72
  68. package/test/patch.error-handler.test.js +1 -1
  69. package/test/patch.test.js +1 -1
  70. package/test/plugin.1.test.js +71 -60
  71. package/test/plugin.2.test.js +104 -86
  72. package/test/plugin.3.test.js +56 -35
  73. package/test/plugin.4.test.js +124 -119
  74. package/test/promises.test.js +36 -30
  75. package/test/proto-poisoning.test.js +78 -97
  76. package/test/put.error-handler.test.js +1 -1
  77. package/test/put.test.js +1 -1
  78. package/test/reply-error.test.js +169 -148
  79. package/test/reply-trailers.test.js +119 -108
  80. package/test/request-error.test.js +0 -46
  81. package/test/route-hooks.test.js +112 -92
  82. package/test/route-prefix.test.js +194 -133
  83. package/test/schema-feature.test.js +309 -238
  84. package/test/schema-serialization.test.js +177 -154
  85. package/test/schema-special-usage.test.js +165 -132
  86. package/test/schema-validation.test.js +278 -199
  87. package/test/set-error-handler.test.js +58 -1
  88. package/test/skip-reply-send.test.js +64 -69
  89. package/test/stream.1.test.js +30 -27
  90. package/test/stream.2.test.js +20 -10
  91. package/test/stream.3.test.js +37 -31
  92. package/test/trust-proxy.test.js +32 -58
  93. package/test/types/errors.test-d.ts +0 -1
  94. package/test/types/fastify.test-d.ts +3 -0
  95. package/test/types/plugin.test-d.ts +1 -1
  96. package/test/types/register.test-d.ts +1 -1
  97. package/test/types/request.test-d.ts +1 -0
  98. package/test/url-rewriting.test.js +45 -62
  99. package/test/use-semicolon-delimiter.test.js +1 -1
  100. package/types/errors.d.ts +0 -1
  101. package/types/request.d.ts +1 -0
  102. package/.taprc +0 -7
  103. package/test/http2/missing-http2-module.test.js +0 -17
@@ -1,11 +1,12 @@
1
1
  'use strict'
2
2
 
3
- const { test } = require('tap')
3
+ const { test } = require('node:test')
4
4
  const Fastify = require('..')
5
5
  const { request } = require('undici')
6
6
 
7
7
  const AJV = require('ajv')
8
8
  const Schema = require('fluent-json-schema')
9
+ const { waitForCb } = require('./toolkit')
9
10
 
10
11
  const customSchemaCompilers = {
11
12
  body: new AJV({
@@ -70,7 +71,7 @@ const schemaArtist = {
70
71
  required: ['name', 'work']
71
72
  }
72
73
 
73
- test('Basic validation test', t => {
74
+ test('Basic validation test', (t, testDone) => {
74
75
  t.plan(6)
75
76
 
76
77
  const fastify = Fastify()
@@ -82,6 +83,7 @@ test('Basic validation test', t => {
82
83
  reply.code(200).send(req.body.name)
83
84
  })
84
85
 
86
+ const completion = waitForCb({ steps: 2 })
85
87
  fastify.inject({
86
88
  method: 'POST',
87
89
  payload: {
@@ -90,23 +92,25 @@ test('Basic validation test', t => {
90
92
  },
91
93
  url: '/'
92
94
  }, (err, res) => {
93
- t.error(err)
94
- t.same(res.payload, 'michelangelo')
95
- t.equal(res.statusCode, 200)
95
+ t.assert.ifError(err)
96
+ t.assert.deepStrictEqual(res.payload, 'michelangelo')
97
+ t.assert.strictEqual(res.statusCode, 200)
98
+ completion.stepIn()
96
99
  })
97
-
98
100
  fastify.inject({
99
101
  method: 'POST',
100
102
  payload: { name: 'michelangelo' },
101
103
  url: '/'
102
104
  }, (err, res) => {
103
- t.error(err)
104
- t.same(res.json(), { statusCode: 400, code: 'FST_ERR_VALIDATION', error: 'Bad Request', message: "body must have required property 'work'" })
105
- t.equal(res.statusCode, 400)
105
+ t.assert.ifError(err)
106
+ t.assert.deepStrictEqual(res.json(), { statusCode: 400, code: 'FST_ERR_VALIDATION', error: 'Bad Request', message: "body must have required property 'work'" })
107
+ t.assert.strictEqual(res.statusCode, 400)
108
+ completion.stepIn()
106
109
  })
110
+ completion.patience.then(testDone)
107
111
  })
108
112
 
109
- test('Different schema per content type', t => {
113
+ test('Different schema per content type', (t, testDone) => {
110
114
  t.plan(12)
111
115
 
112
116
  const fastify = Fastify()
@@ -135,6 +139,7 @@ test('Different schema per content type', t => {
135
139
  return reply.send(req.body)
136
140
  })
137
141
 
142
+ const completion = waitForCb({ steps: 4 })
138
143
  fastify.inject({
139
144
  url: '/',
140
145
  method: 'POST',
@@ -144,46 +149,48 @@ test('Different schema per content type', t => {
144
149
  work: 'sculptor, painter, architect and poet'
145
150
  }
146
151
  }, (err, res) => {
147
- t.error(err)
148
- t.same(JSON.parse(res.payload).name, 'michelangelo')
149
- t.equal(res.statusCode, 200)
152
+ t.assert.ifError(err)
153
+ t.assert.deepStrictEqual(JSON.parse(res.payload).name, 'michelangelo')
154
+ t.assert.strictEqual(res.statusCode, 200)
155
+ completion.stepIn()
150
156
  })
151
-
152
157
  fastify.inject({
153
158
  url: '/',
154
159
  method: 'POST',
155
160
  headers: { 'Content-Type': 'application/json' },
156
161
  body: { name: 'michelangelo' }
157
162
  }, (err, res) => {
158
- t.error(err)
159
- t.same(res.json(), { statusCode: 400, code: 'FST_ERR_VALIDATION', error: 'Bad Request', message: "body must have required property 'work'" })
160
- t.equal(res.statusCode, 400)
163
+ t.assert.ifError(err)
164
+ t.assert.deepStrictEqual(res.json(), { statusCode: 400, code: 'FST_ERR_VALIDATION', error: 'Bad Request', message: "body must have required property 'work'" })
165
+ t.assert.strictEqual(res.statusCode, 400)
166
+ completion.stepIn()
161
167
  })
162
-
163
168
  fastify.inject({
164
169
  url: '/',
165
170
  method: 'POST',
166
171
  headers: { 'Content-Type': 'application/octet-stream' },
167
172
  body: Buffer.from('AAAAAAAA')
168
173
  }, (err, res) => {
169
- t.error(err)
170
- t.same(res.payload, 'AAAAAAAA')
171
- t.equal(res.statusCode, 200)
174
+ t.assert.ifError(err)
175
+ t.assert.deepStrictEqual(res.payload, 'AAAAAAAA')
176
+ t.assert.strictEqual(res.statusCode, 200)
177
+ completion.stepIn()
172
178
  })
173
-
174
179
  fastify.inject({
175
180
  url: '/',
176
181
  method: 'POST',
177
182
  headers: { 'Content-Type': 'text/plain' },
178
183
  body: 'AAAAAAAA'
179
184
  }, (err, res) => {
180
- t.error(err)
181
- t.same(res.payload, 'AAAAAAAA')
182
- t.equal(res.statusCode, 200)
185
+ t.assert.ifError(err)
186
+ t.assert.deepStrictEqual(res.payload, 'AAAAAAAA')
187
+ t.assert.strictEqual(res.statusCode, 200)
188
+ completion.stepIn()
183
189
  })
190
+ completion.patience.then(testDone)
184
191
  })
185
192
 
186
- test('Skip validation if no schema for content type', t => {
193
+ test('Skip validation if no schema for content type', (t, testDone) => {
187
194
  t.plan(3)
188
195
 
189
196
  const fastify = Fastify()
@@ -201,20 +208,20 @@ test('Skip validation if no schema for content type', t => {
201
208
  }, async function (req, reply) {
202
209
  return reply.send(req.body)
203
210
  })
204
-
205
211
  fastify.inject({
206
212
  url: '/',
207
213
  method: 'POST',
208
214
  headers: { 'Content-Type': 'text/plain' },
209
215
  body: 'AAAAAAAA'
210
216
  }, (err, res) => {
211
- t.error(err)
212
- t.same(res.payload, 'AAAAAAAA')
213
- t.equal(res.statusCode, 200)
217
+ t.assert.ifError(err)
218
+ t.assert.deepStrictEqual(res.payload, 'AAAAAAAA')
219
+ t.assert.strictEqual(res.statusCode, 200)
220
+ testDone()
214
221
  })
215
222
  })
216
223
 
217
- test('Skip validation if no content type schemas', t => {
224
+ test('Skip validation if no content type schemas', (t, testDone) => {
218
225
  t.plan(3)
219
226
 
220
227
  const fastify = Fastify()
@@ -229,20 +236,20 @@ test('Skip validation if no content type schemas', t => {
229
236
  }, async function (req, reply) {
230
237
  return reply.send(req.body)
231
238
  })
232
-
233
239
  fastify.inject({
234
240
  url: '/',
235
241
  method: 'POST',
236
242
  headers: { 'Content-Type': 'text/plain' },
237
243
  body: 'AAAAAAAA'
238
244
  }, (err, res) => {
239
- t.error(err)
240
- t.same(res.payload, 'AAAAAAAA')
241
- t.equal(res.statusCode, 200)
245
+ t.assert.ifError(err)
246
+ t.assert.deepStrictEqual(res.payload, 'AAAAAAAA')
247
+ t.assert.strictEqual(res.statusCode, 200)
248
+ testDone()
242
249
  })
243
250
  })
244
251
 
245
- test('External AJV instance', t => {
252
+ test('External AJV instance', (t, testDone) => {
246
253
  t.plan(5)
247
254
 
248
255
  const fastify = Fastify()
@@ -255,7 +262,7 @@ test('External AJV instance', t => {
255
262
  fastify.addSchema(schemaBRefToA)
256
263
 
257
264
  fastify.setValidatorCompiler(({ schema, method, url, httpPart }) => {
258
- t.pass('custom validator compiler called')
265
+ t.assert.ok('custom validator compiler called')
259
266
  return ajv.compile(schema)
260
267
  })
261
268
 
@@ -269,26 +276,29 @@ test('External AJV instance', t => {
269
276
  }
270
277
  })
271
278
 
279
+ const completion = waitForCb({ steps: 2 })
272
280
  fastify.inject({
273
281
  method: 'POST',
274
282
  url: '/',
275
283
  payload: { foo: 42 }
276
284
  }, (err, res) => {
277
- t.error(err)
278
- t.equal(res.statusCode, 200)
285
+ t.assert.ifError(err)
286
+ t.assert.strictEqual(res.statusCode, 200)
287
+ completion.stepIn()
279
288
  })
280
-
281
289
  fastify.inject({
282
290
  method: 'POST',
283
291
  url: '/',
284
292
  payload: { foo: 'not a number' }
285
293
  }, (err, res) => {
286
- t.error(err)
287
- t.equal(res.statusCode, 400)
294
+ t.assert.ifError(err)
295
+ t.assert.strictEqual(res.statusCode, 400)
296
+ completion.stepIn()
288
297
  })
298
+ completion.patience.then(testDone)
289
299
  })
290
300
 
291
- test('Encapsulation', t => {
301
+ test('Encapsulation', (t, testDone) => {
292
302
  t.plan(21)
293
303
 
294
304
  const fastify = Fastify()
@@ -302,7 +312,7 @@ test('Encapsulation', t => {
302
312
 
303
313
  fastify.register((instance, opts, done) => {
304
314
  const validator = ({ schema, method, url, httpPart }) => {
305
- t.pass('custom validator compiler called')
315
+ t.assert.ok('custom validator compiler called')
306
316
  return ajv.compile(schema)
307
317
  }
308
318
  instance.setValidatorCompiler(validator)
@@ -316,7 +326,7 @@ test('Encapsulation', t => {
316
326
  instance.register((instance, opts, done) => {
317
327
  instance.post('/two', {
318
328
  handler (req, reply) {
319
- t.same(instance.validatorCompiler, validator)
329
+ t.assert.deepStrictEqual(instance.validatorCompiler, validator)
320
330
  reply.send({ foo: 'two' })
321
331
  },
322
332
  schema: {
@@ -330,7 +340,7 @@ test('Encapsulation', t => {
330
340
  instance.post('/three', {
331
341
  validatorCompiler: anotherValidator,
332
342
  handler (req, reply) {
333
- t.same(instance.validatorCompiler, validator, 'the route validator does not change the instance one')
343
+ t.assert.deepStrictEqual(instance.validatorCompiler, validator, 'the route validator does not change the instance one')
334
344
  reply.send({ foo: 'three' })
335
345
  },
336
346
  schema: {
@@ -344,72 +354,75 @@ test('Encapsulation', t => {
344
354
 
345
355
  fastify.register((instance, opts, done) => {
346
356
  instance.post('/clean', function (req, reply) {
347
- t.equal(instance.validatorCompiler, undefined)
357
+ t.assert.strictEqual(instance.validatorCompiler, undefined)
348
358
  reply.send({ foo: 'bar' })
349
359
  })
350
360
  done()
351
361
  })
352
362
 
363
+ const completion = waitForCb({ steps: 6 })
353
364
  fastify.inject({
354
365
  method: 'POST',
355
366
  url: '/one',
356
367
  payload: { foo: 1 }
357
368
  }, (err, res) => {
358
- t.error(err)
359
- t.equal(res.statusCode, 200)
360
- t.same(res.json(), { foo: 'one' })
369
+ t.assert.ifError(err)
370
+ t.assert.strictEqual(res.statusCode, 200)
371
+ t.assert.deepStrictEqual(res.json(), { foo: 'one' })
372
+ completion.stepIn()
361
373
  })
362
-
363
374
  fastify.inject({
364
375
  method: 'POST',
365
376
  url: '/one',
366
377
  payload: { wrongFoo: 'bar' }
367
378
  }, (err, res) => {
368
- t.error(err)
369
- t.equal(res.statusCode, 400)
379
+ t.assert.ifError(err)
380
+ t.assert.strictEqual(res.statusCode, 400)
381
+ completion.stepIn()
370
382
  })
371
-
372
383
  fastify.inject({
373
384
  method: 'POST',
374
385
  url: '/two',
375
386
  payload: { foo: 2 }
376
387
  }, (err, res) => {
377
- t.error(err)
378
- t.equal(res.statusCode, 200)
379
- t.same(res.json(), { foo: 'two' })
388
+ t.assert.ifError(err)
389
+ t.assert.strictEqual(res.statusCode, 200)
390
+ t.assert.deepStrictEqual(res.json(), { foo: 'two' })
391
+ completion.stepIn()
380
392
  })
381
-
382
393
  fastify.inject({
383
394
  method: 'POST',
384
395
  url: '/two',
385
396
  payload: { wrongFoo: 'bar' }
386
397
  }, (err, res) => {
387
- t.error(err)
388
- t.equal(res.statusCode, 400)
398
+ t.assert.ifError(err)
399
+ t.assert.strictEqual(res.statusCode, 400)
400
+ completion.stepIn()
389
401
  })
390
-
391
402
  fastify.inject({
392
403
  method: 'POST',
393
404
  url: '/three',
394
405
  payload: { wrongFoo: 'but works' }
395
406
  }, (err, res) => {
396
- t.error(err)
397
- t.equal(res.statusCode, 200)
398
- t.same(res.json(), { foo: 'three' })
407
+ t.assert.ifError(err)
408
+ t.assert.strictEqual(res.statusCode, 200)
409
+ t.assert.deepStrictEqual(res.json(), { foo: 'three' })
410
+ completion.stepIn()
399
411
  })
400
-
401
412
  fastify.inject({
402
413
  method: 'POST',
403
414
  url: '/clean',
404
415
  payload: { wrongFoo: 'bar' }
405
416
  }, (err, res) => {
406
- t.error(err)
407
- t.equal(res.statusCode, 200)
408
- t.same(res.json(), { foo: 'bar' })
417
+ t.assert.ifError(err)
418
+ t.assert.strictEqual(res.statusCode, 200)
419
+ t.assert.deepStrictEqual(res.json(), { foo: 'bar' })
420
+ completion.stepIn()
409
421
  })
422
+ completion.patience.then(testDone)
410
423
  })
411
424
 
412
- test('Triple $ref with a simple $id', t => {
425
+ test('Triple $ref with a simple $id', (t, testDone) => {
413
426
  t.plan(7)
414
427
 
415
428
  const fastify = Fastify()
@@ -424,7 +437,7 @@ test('Triple $ref with a simple $id', t => {
424
437
  fastify.addSchema(schemaCRefToB)
425
438
 
426
439
  fastify.setValidatorCompiler(({ schema, method, url, httpPart }) => {
427
- t.pass('custom validator compiler called')
440
+ t.assert.ok('custom validator compiler called')
428
441
  return ajv.compile(schema)
429
442
  })
430
443
 
@@ -438,28 +451,31 @@ test('Triple $ref with a simple $id', t => {
438
451
  }
439
452
  })
440
453
 
454
+ const completion = waitForCb({ steps: 2 })
441
455
  fastify.inject({
442
456
  method: 'POST',
443
457
  url: '/',
444
458
  payload: { foo: 43 }
445
459
  }, (err, res) => {
446
- t.error(err)
447
- t.equal(res.statusCode, 200)
448
- t.same(res.json(), { foo: 105 })
460
+ t.assert.ifError(err)
461
+ t.assert.strictEqual(res.statusCode, 200)
462
+ t.assert.deepStrictEqual(res.json(), { foo: 105 })
463
+ completion.stepIn()
449
464
  })
450
-
451
465
  fastify.inject({
452
466
  method: 'POST',
453
467
  url: '/',
454
468
  payload: { fool: 'bar' }
455
469
  }, (err, res) => {
456
- t.error(err)
457
- t.equal(res.statusCode, 400)
458
- t.same(res.json().message, "body must have required property 'foo'")
470
+ t.assert.ifError(err)
471
+ t.assert.strictEqual(res.statusCode, 400)
472
+ t.assert.deepStrictEqual(res.json().message, "body must have required property 'foo'")
473
+ completion.stepIn()
459
474
  })
475
+ completion.patience.then(testDone)
460
476
  })
461
477
 
462
- test('Extending schema', t => {
478
+ test('Extending schema', (t, testDone) => {
463
479
  t.plan(4)
464
480
  const fastify = Fastify()
465
481
 
@@ -499,7 +515,6 @@ test('Extending schema', t => {
499
515
  }
500
516
  }
501
517
  })
502
-
503
518
  fastify.inject({
504
519
  method: 'POST',
505
520
  url: '/',
@@ -510,10 +525,9 @@ test('Extending schema', t => {
510
525
  }
511
526
  }
512
527
  }, (err, res) => {
513
- t.error(err)
514
- t.equal(res.statusCode, 400)
528
+ t.assert.ifError(err)
529
+ t.assert.strictEqual(res.statusCode, 400)
515
530
  })
516
-
517
531
  fastify.inject({
518
532
  method: 'POST',
519
533
  url: '/',
@@ -525,12 +539,13 @@ test('Extending schema', t => {
525
539
  }
526
540
  }
527
541
  }, (err, res) => {
528
- t.error(err)
529
- t.equal(res.statusCode, 200)
542
+ t.assert.ifError(err)
543
+ t.assert.strictEqual(res.statusCode, 200)
544
+ testDone()
530
545
  })
531
546
  })
532
547
 
533
- test('Should work with nested ids', t => {
548
+ test('Should work with nested ids', (t, testDone) => {
534
549
  t.plan(6)
535
550
  const fastify = Fastify()
536
551
 
@@ -560,6 +575,7 @@ test('Should work with nested ids', t => {
560
575
  }
561
576
  })
562
577
 
578
+ const completion = waitForCb({ steps: 2 })
563
579
  fastify.inject({
564
580
  method: 'POST',
565
581
  url: '/123',
@@ -567,11 +583,11 @@ test('Should work with nested ids', t => {
567
583
  hello: 'world'
568
584
  }
569
585
  }, (err, res) => {
570
- t.error(err)
571
- t.equal(res.statusCode, 200)
572
- t.equal(res.payload, 'number')
586
+ t.assert.ifError(err)
587
+ t.assert.strictEqual(res.statusCode, 200)
588
+ t.assert.strictEqual(res.payload, 'number')
589
+ completion.stepIn()
573
590
  })
574
-
575
591
  fastify.inject({
576
592
  method: 'POST',
577
593
  url: '/abc',
@@ -579,14 +595,16 @@ test('Should work with nested ids', t => {
579
595
  hello: 'world'
580
596
  }
581
597
  }, (err, res) => {
582
- t.error(err)
583
- t.equal(res.statusCode, 400)
584
- t.equal(res.json().message, 'params/id must be number')
598
+ t.assert.ifError(err)
599
+ t.assert.strictEqual(res.statusCode, 400)
600
+ t.assert.strictEqual(res.json().message, 'params/id must be number')
601
+ completion.stepIn()
585
602
  })
603
+ completion.patience.then(testDone)
586
604
  })
587
605
 
588
- test('Use the same schema across multiple routes', t => {
589
- t.plan(8)
606
+ test('Use the same schema across multiple routes', async (t) => {
607
+ t.plan(4)
590
608
  const fastify = Fastify()
591
609
 
592
610
  fastify.addSchema({
@@ -611,34 +629,35 @@ test('Use the same schema across multiple routes', t => {
611
629
  }
612
630
  })
613
631
 
614
- ;[
632
+ const validTestCases = [
615
633
  '/first/123',
616
634
  '/second/123'
617
- ].forEach(url => {
618
- fastify.inject({
635
+ ]
636
+
637
+ for (const url of validTestCases) {
638
+ const res = await fastify.inject({
619
639
  url,
620
640
  method: 'GET'
621
- }, (err, res) => {
622
- t.error(err)
623
- t.equal(res.payload, 'number')
624
641
  })
625
- })
626
642
 
627
- ;[
643
+ t.assert.strictEqual(res.payload, 'number')
644
+ }
645
+
646
+ const invalidTestCases = [
628
647
  '/first/abc',
629
648
  '/second/abc'
630
- ].forEach(url => {
631
- fastify.inject({
649
+ ]
650
+
651
+ for (const url of invalidTestCases) {
652
+ const res = await fastify.inject({
632
653
  url,
633
654
  method: 'GET'
634
- }, (err, res) => {
635
- t.error(err)
636
- t.equal(res.statusCode, 400)
637
655
  })
638
- })
656
+ t.assert.strictEqual(res.statusCode, 400)
657
+ }
639
658
  })
640
659
 
641
- test('JSON Schema validation keywords', t => {
660
+ test('JSON Schema validation keywords', (t, testDone) => {
642
661
  t.plan(6)
643
662
  const fastify = Fastify()
644
663
 
@@ -660,31 +679,34 @@ test('JSON Schema validation keywords', t => {
660
679
  }
661
680
  })
662
681
 
682
+ const completion = waitForCb({ steps: 2 })
663
683
  fastify.inject({
664
684
  method: 'GET',
665
685
  url: '/127.0.0.1'
666
686
  }, (err, res) => {
667
- t.error(err)
668
- t.equal(res.statusCode, 200)
669
- t.equal(res.payload, 'string')
687
+ t.assert.ifError(err)
688
+ t.assert.strictEqual(res.statusCode, 200)
689
+ t.assert.strictEqual(res.payload, 'string')
690
+ completion.stepIn()
670
691
  })
671
-
672
692
  fastify.inject({
673
693
  method: 'GET',
674
694
  url: '/localhost'
675
695
  }, (err, res) => {
676
- t.error(err)
677
- t.equal(res.statusCode, 400)
678
- t.same(res.json(), {
696
+ t.assert.ifError(err)
697
+ t.assert.strictEqual(res.statusCode, 400)
698
+ t.assert.deepStrictEqual(res.json(), {
679
699
  statusCode: 400,
680
700
  code: 'FST_ERR_VALIDATION',
681
701
  error: 'Bad Request',
682
702
  message: 'params/ip must match format "ipv4"'
683
703
  })
704
+ completion.stepIn()
684
705
  })
706
+ completion.patience.then(testDone)
685
707
  })
686
708
 
687
- test('Nested id calls', t => {
709
+ test('Nested id calls', (t, testDone) => {
688
710
  t.plan(6)
689
711
  const fastify = Fastify()
690
712
 
@@ -714,33 +736,36 @@ test('Nested id calls', t => {
714
736
  }
715
737
  })
716
738
 
739
+ const completion = waitForCb({ steps: 2 })
717
740
  fastify.inject({
718
741
  method: 'POST',
719
742
  url: '/',
720
743
  payload: { host: { ip: '127.0.0.1' } }
721
744
  }, (err, res) => {
722
- t.error(err)
723
- t.equal(res.statusCode, 200)
724
- t.equal(res.payload, 'string')
745
+ t.assert.ifError(err)
746
+ t.assert.strictEqual(res.statusCode, 200)
747
+ t.assert.strictEqual(res.payload, 'string')
748
+ completion.stepIn()
725
749
  })
726
-
727
750
  fastify.inject({
728
751
  method: 'POST',
729
752
  url: '/',
730
753
  payload: { host: { ip: 'localhost' } }
731
754
  }, (err, res) => {
732
- t.error(err)
733
- t.equal(res.statusCode, 400)
734
- t.same(res.json(), {
755
+ t.assert.ifError(err)
756
+ t.assert.strictEqual(res.statusCode, 400)
757
+ t.assert.deepStrictEqual(res.json(), {
735
758
  error: 'Bad Request',
736
759
  message: 'body/host/ip must match format "ipv4"',
737
760
  statusCode: 400,
738
761
  code: 'FST_ERR_VALIDATION'
739
762
  })
763
+ completion.stepIn()
740
764
  })
765
+ completion.patience.then(testDone)
741
766
  })
742
767
 
743
- test('Use the same schema id in different places', t => {
768
+ test('Use the same schema id in different places', (t, testDone) => {
744
769
  t.plan(2)
745
770
  const fastify = Fastify()
746
771
 
@@ -761,18 +786,18 @@ test('Use the same schema id in different places', t => {
761
786
  }
762
787
  }
763
788
  })
764
-
765
789
  fastify.inject({
766
790
  method: 'POST',
767
791
  url: '/',
768
792
  payload: { id: 42 }
769
793
  }, (err, res) => {
770
- t.error(err)
771
- t.same(res.json(), { id: 21 })
794
+ t.assert.ifError(err)
795
+ t.assert.deepStrictEqual(res.json(), { id: 21 })
796
+ testDone()
772
797
  })
773
798
  })
774
799
 
775
- test('Use shared schema and $ref with $id ($ref to $id)', t => {
800
+ test('Use shared schema and $ref with $id ($ref to $id)', (t, testDone) => {
776
801
  t.plan(5)
777
802
  const fastify = Fastify()
778
803
 
@@ -815,6 +840,7 @@ test('Use shared schema and $ref with $id ($ref to $id)', t => {
815
840
  })
816
841
 
817
842
  const id = Date.now()
843
+ const completion = waitForCb({ steps: 2 })
818
844
  fastify.inject({
819
845
  method: 'POST',
820
846
  url: '/',
@@ -823,27 +849,29 @@ test('Use shared schema and $ref with $id ($ref to $id)', t => {
823
849
  test: { id }
824
850
  }
825
851
  }, (err, res) => {
826
- t.error(err)
827
- t.same(res.json(), { id })
852
+ t.assert.ifError(err)
853
+ t.assert.deepStrictEqual(res.json(), { id })
854
+ completion.stepIn()
828
855
  })
829
-
830
856
  fastify.inject({
831
857
  method: 'POST',
832
858
  url: '/',
833
859
  payload: { test: { id } }
834
860
  }, (err, res) => {
835
- t.error(err)
836
- t.equal(res.statusCode, 400)
837
- t.same(res.json(), {
861
+ t.assert.ifError(err)
862
+ t.assert.strictEqual(res.statusCode, 400)
863
+ t.assert.deepStrictEqual(res.json(), {
838
864
  error: 'Bad Request',
839
865
  message: "body must have required property 'address'",
840
866
  statusCode: 400,
841
867
  code: 'FST_ERR_VALIDATION'
842
868
  })
869
+ completion.stepIn()
843
870
  })
871
+ completion.patience.then(testDone)
844
872
  })
845
873
 
846
- test('Use items with $ref', t => {
874
+ test('Use items with $ref', (t, testDone) => {
847
875
  t.plan(4)
848
876
  const fastify = Fastify()
849
877
 
@@ -865,26 +893,29 @@ test('Use items with $ref', t => {
865
893
  handler: (_, r) => { r.send('ok') }
866
894
  })
867
895
 
896
+ const completion = waitForCb({ steps: 2 })
868
897
  fastify.inject({
869
898
  method: 'POST',
870
899
  url: '/',
871
900
  payload: [{ hello: 'world' }]
872
901
  }, (err, res) => {
873
- t.error(err)
874
- t.equal(res.payload, 'ok')
902
+ t.assert.ifError(err)
903
+ t.assert.strictEqual(res.payload, 'ok')
904
+ completion.stepIn()
875
905
  })
876
-
877
906
  fastify.inject({
878
907
  method: 'POST',
879
908
  url: '/',
880
909
  payload: { hello: 'world' }
881
910
  }, (err, res) => {
882
- t.error(err)
883
- t.equal(res.statusCode, 400)
911
+ t.assert.ifError(err)
912
+ t.assert.strictEqual(res.statusCode, 400)
913
+ completion.stepIn()
884
914
  })
915
+ completion.patience.then(testDone)
885
916
  })
886
917
 
887
- test('Use $ref to /definitions', t => {
918
+ test('Use $ref to /definitions', (t, testDone) => {
888
919
  t.plan(6)
889
920
  const fastify = Fastify()
890
921
 
@@ -931,16 +962,17 @@ test('Use $ref to /definitions', t => {
931
962
  address: { city: 'New Node' },
932
963
  test: { id: Date.now() }
933
964
  }
965
+ const completion = waitForCb({ steps: 2 })
934
966
  fastify.inject({
935
967
  method: 'POST',
936
968
  url: '/',
937
969
  payload
938
970
  }, (err, res) => {
939
- t.error(err)
940
- t.equal(res.statusCode, 200)
941
- t.same(res.json(), payload)
971
+ t.assert.ifError(err)
972
+ t.assert.strictEqual(res.statusCode, 200)
973
+ t.assert.deepStrictEqual(res.json(), payload)
974
+ completion.stepIn()
942
975
  })
943
-
944
976
  fastify.inject({
945
977
  method: 'POST',
946
978
  url: '/',
@@ -949,18 +981,20 @@ test('Use $ref to /definitions', t => {
949
981
  test: { id: 'wrong' }
950
982
  }
951
983
  }, (err, res) => {
952
- t.error(err)
953
- t.equal(res.statusCode, 400)
954
- t.same(res.json(), {
984
+ t.assert.ifError(err)
985
+ t.assert.strictEqual(res.statusCode, 400)
986
+ t.assert.deepStrictEqual(res.json(), {
955
987
  error: 'Bad Request',
956
988
  message: 'body/test/id must be number',
957
989
  statusCode: 400,
958
990
  code: 'FST_ERR_VALIDATION'
959
991
  })
992
+ completion.stepIn()
960
993
  })
994
+ completion.patience.then(testDone)
961
995
  })
962
996
 
963
- test('Custom AJV settings - pt1', t => {
997
+ test('Custom AJV settings - pt1', (t, testDone) => {
964
998
  t.plan(4)
965
999
  const fastify = Fastify()
966
1000
 
@@ -974,11 +1008,10 @@ test('Custom AJV settings - pt1', t => {
974
1008
  }
975
1009
  },
976
1010
  handler: (req, reply) => {
977
- t.equal(req.body.num, 12)
1011
+ t.assert.strictEqual(req.body.num, 12)
978
1012
  reply.send(req.body)
979
1013
  }
980
1014
  })
981
-
982
1015
  fastify.inject({
983
1016
  method: 'POST',
984
1017
  url: '/',
@@ -986,13 +1019,14 @@ test('Custom AJV settings - pt1', t => {
986
1019
  num: '12'
987
1020
  }
988
1021
  }, (err, res) => {
989
- t.error(err)
990
- t.equal(res.statusCode, 200)
991
- t.same(res.json(), { num: 12 })
1022
+ t.assert.ifError(err)
1023
+ t.assert.strictEqual(res.statusCode, 200)
1024
+ t.assert.deepStrictEqual(res.json(), { num: 12 })
1025
+ testDone()
992
1026
  })
993
1027
  })
994
1028
 
995
- test('Custom AJV settings - pt2', t => {
1029
+ test('Custom AJV settings - pt2', (t, testDone) => {
996
1030
  t.plan(2)
997
1031
  const fastify = Fastify({
998
1032
  ajv: {
@@ -1015,7 +1049,6 @@ test('Custom AJV settings - pt2', t => {
1015
1049
  t.fail('the handler is not called because the "12" is not coerced to number')
1016
1050
  }
1017
1051
  })
1018
-
1019
1052
  fastify.inject({
1020
1053
  method: 'POST',
1021
1054
  url: '/',
@@ -1023,12 +1056,13 @@ test('Custom AJV settings - pt2', t => {
1023
1056
  num: '12'
1024
1057
  }
1025
1058
  }, (err, res) => {
1026
- t.error(err)
1027
- t.equal(res.statusCode, 400)
1059
+ t.assert.ifError(err)
1060
+ t.assert.strictEqual(res.statusCode, 400)
1061
+ testDone()
1028
1062
  })
1029
1063
  })
1030
1064
 
1031
- test('Custom AJV settings on different parameters - pt1', t => {
1065
+ test('Custom AJV settings on different parameters - pt1', (t, testDone) => {
1032
1066
  t.plan(2)
1033
1067
  const fastify = Fastify()
1034
1068
 
@@ -1054,7 +1088,6 @@ test('Custom AJV settings on different parameters - pt1', t => {
1054
1088
  t.fail('the handler is not called because the "12" is not coerced to number')
1055
1089
  }
1056
1090
  })
1057
-
1058
1091
  fastify.inject({
1059
1092
  method: 'POST',
1060
1093
  url: '/api/42',
@@ -1062,12 +1095,13 @@ test('Custom AJV settings on different parameters - pt1', t => {
1062
1095
  num: '12'
1063
1096
  }
1064
1097
  }, (err, res) => {
1065
- t.error(err)
1066
- t.equal(res.statusCode, 400)
1098
+ t.assert.ifError(err)
1099
+ t.assert.strictEqual(res.statusCode, 400)
1100
+ testDone()
1067
1101
  })
1068
1102
  })
1069
1103
 
1070
- test('Custom AJV settings on different parameters - pt2', t => {
1104
+ test('Custom AJV settings on different parameters - pt2', (t, testDone) => {
1071
1105
  t.plan(4)
1072
1106
  const fastify = Fastify()
1073
1107
 
@@ -1091,13 +1125,13 @@ test('Custom AJV settings on different parameters - pt2', t => {
1091
1125
  }
1092
1126
  },
1093
1127
  handler: (req, reply) => {
1094
- t.same(typeof req.params.id, 'number')
1095
- t.same(typeof req.body.num, 'number')
1096
- t.same(req.params.id, 42)
1097
- t.same(req.body.num, 12)
1128
+ t.assert.deepStrictEqual(typeof req.params.id, 'number')
1129
+ t.assert.deepStrictEqual(typeof req.body.num, 'number')
1130
+ t.assert.deepStrictEqual(req.params.id, 42)
1131
+ t.assert.deepStrictEqual(req.body.num, 12)
1132
+ testDone()
1098
1133
  }
1099
1134
  })
1100
-
1101
1135
  fastify.inject({
1102
1136
  method: 'POST',
1103
1137
  url: '/api/42',
@@ -1107,7 +1141,7 @@ test('Custom AJV settings on different parameters - pt2', t => {
1107
1141
  })
1108
1142
  })
1109
1143
 
1110
- test("The same $id in route's schema must not overwrite others", t => {
1144
+ test("The same $id in route's schema must not overwrite others", (t, testDone) => {
1111
1145
  t.plan(4)
1112
1146
  const fastify = Fastify()
1113
1147
 
@@ -1158,23 +1192,26 @@ test("The same $id in route's schema must not overwrite others", t => {
1158
1192
  handler: () => { return 'ok' }
1159
1193
  })
1160
1194
 
1195
+ const completion = waitForCb({ steps: 2 })
1161
1196
  fastify.inject({
1162
1197
  method: 'POST',
1163
1198
  url: '/user',
1164
1199
  body: {}
1165
1200
  }, (err, res) => {
1166
- t.error(err)
1167
- t.same(res.json().message, "body must have required property 'username'")
1201
+ t.assert.ifError(err)
1202
+ t.assert.deepStrictEqual(res.json().message, "body must have required property 'username'")
1203
+ completion.stepIn()
1168
1204
  })
1169
-
1170
1205
  fastify.inject({
1171
1206
  url: '/user/1',
1172
1207
  method: 'PATCH',
1173
1208
  body: {}
1174
1209
  }, (err, res) => {
1175
- t.error(err)
1176
- t.same(res.payload, 'ok')
1210
+ t.assert.ifError(err)
1211
+ t.assert.deepStrictEqual(res.payload, 'ok')
1212
+ completion.stepIn()
1177
1213
  })
1214
+ completion.patience.then(testDone)
1178
1215
  })
1179
1216
 
1180
1217
  test('Custom validator compiler should not mutate schema', async t => {
@@ -1183,7 +1220,7 @@ test('Custom validator compiler should not mutate schema', async t => {
1183
1220
  const fastify = Fastify()
1184
1221
 
1185
1222
  fastify.setValidatorCompiler(({ schema, method, url, httpPart }) => {
1186
- t.type(schema, Headers)
1223
+ t.assert.ok(schema instanceof Headers)
1187
1224
  return () => { }
1188
1225
  })
1189
1226
 
@@ -1221,8 +1258,8 @@ test('Custom validator builder override by custom validator compiler', async t =
1221
1258
  }
1222
1259
  },
1223
1260
  handler: (req, _reply) => {
1224
- t.same(typeof req.params.id, 'number')
1225
- t.same(req.params.id, 43)
1261
+ t.assert.deepStrictEqual(typeof req.params.id, 'number')
1262
+ t.assert.deepStrictEqual(req.params.id, 43)
1226
1263
  return 'ok'
1227
1264
  }
1228
1265
  })
@@ -1233,7 +1270,7 @@ test('Custom validator builder override by custom validator compiler', async t =
1233
1270
  method: 'POST',
1234
1271
  url: '/two/43'
1235
1272
  })
1236
- t.equal(two.statusCode, 200)
1273
+ t.assert.strictEqual(two.statusCode, 200)
1237
1274
  })
1238
1275
 
1239
1276
  test('Custom validator builder override by custom validator compiler in child instance', async t => {
@@ -1261,8 +1298,8 @@ test('Custom validator builder override by custom validator compiler in child in
1261
1298
  }
1262
1299
  },
1263
1300
  handler: (req, _reply) => {
1264
- t.same(typeof req.params.id, 'number')
1265
- t.same(req.params.id, 43)
1301
+ t.assert.deepStrictEqual(typeof req.params.id, 'number')
1302
+ t.assert.deepStrictEqual(req.params.id, 43)
1266
1303
  return 'ok'
1267
1304
  }
1268
1305
  })
@@ -1281,8 +1318,8 @@ test('Custom validator builder override by custom validator compiler in child in
1281
1318
  }
1282
1319
  },
1283
1320
  handler: (req, _reply) => {
1284
- t.same(typeof req.params.id, 'number')
1285
- t.same(req.params.id, 42)
1321
+ t.assert.deepStrictEqual(typeof req.params.id, 'number')
1322
+ t.assert.deepStrictEqual(req.params.id, 42)
1286
1323
  return 'ok'
1287
1324
  }
1288
1325
  })
@@ -1293,13 +1330,13 @@ test('Custom validator builder override by custom validator compiler in child in
1293
1330
  method: 'POST',
1294
1331
  url: '/one/42'
1295
1332
  })
1296
- t.equal(one.statusCode, 200)
1333
+ t.assert.strictEqual(one.statusCode, 200)
1297
1334
 
1298
1335
  const two = await fastify.inject({
1299
1336
  method: 'POST',
1300
1337
  url: '/two/43'
1301
1338
  })
1302
- t.equal(two.statusCode, 200)
1339
+ t.assert.strictEqual(two.statusCode, 200)
1303
1340
  })
1304
1341
 
1305
1342
  test('Schema validation when no content type is provided', async t => {
@@ -1339,12 +1376,10 @@ test('Schema validation when no content type is provided', async t => {
1339
1376
  },
1340
1377
  body: { invalid: 'string' }
1341
1378
  })
1342
- t.equal(invalid.statusCode, 200)
1379
+ t.assert.strictEqual(invalid.statusCode, 200)
1343
1380
  })
1344
1381
 
1345
1382
  test('Schema validation will not be bypass by different content type', async t => {
1346
- t.plan(10)
1347
-
1348
1383
  const fastify = Fastify()
1349
1384
 
1350
1385
  fastify.post('/', {
@@ -1367,7 +1402,7 @@ test('Schema validation will not be bypass by different content type', async t =
1367
1402
  }, async () => 'ok')
1368
1403
 
1369
1404
  await fastify.listen({ port: 0 })
1370
- t.teardown(() => fastify.close())
1405
+ t.after(() => fastify.close())
1371
1406
  const address = fastify.listeningOrigin
1372
1407
 
1373
1408
  const correct1 = await request(address, {
@@ -1378,7 +1413,7 @@ test('Schema validation will not be bypass by different content type', async t =
1378
1413
  },
1379
1414
  body: JSON.stringify({ foo: 'string' })
1380
1415
  })
1381
- t.equal(correct1.statusCode, 200)
1416
+ t.assert.strictEqual(correct1.statusCode, 200)
1382
1417
  await correct1.body.dump()
1383
1418
 
1384
1419
  const correct2 = await request(address, {
@@ -1389,7 +1424,7 @@ test('Schema validation will not be bypass by different content type', async t =
1389
1424
  },
1390
1425
  body: JSON.stringify({ foo: 'string' })
1391
1426
  })
1392
- t.equal(correct2.statusCode, 200)
1427
+ t.assert.strictEqual(correct2.statusCode, 200)
1393
1428
  await correct2.body.dump()
1394
1429
 
1395
1430
  const invalid1 = await request(address, {
@@ -1400,8 +1435,8 @@ test('Schema validation will not be bypass by different content type', async t =
1400
1435
  },
1401
1436
  body: JSON.stringify({ invalid: 'string' })
1402
1437
  })
1403
- t.equal(invalid1.statusCode, 400)
1404
- t.equal((await invalid1.body.json()).code, 'FST_ERR_VALIDATION')
1438
+ t.assert.strictEqual(invalid1.statusCode, 400)
1439
+ t.assert.strictEqual((await invalid1.body.json()).code, 'FST_ERR_VALIDATION')
1405
1440
 
1406
1441
  const invalid2 = await request(address, {
1407
1442
  method: 'POST',
@@ -1411,8 +1446,8 @@ test('Schema validation will not be bypass by different content type', async t =
1411
1446
  },
1412
1447
  body: JSON.stringify({ invalid: 'string' })
1413
1448
  })
1414
- t.equal(invalid2.statusCode, 400)
1415
- t.equal((await invalid2.body.json()).code, 'FST_ERR_VALIDATION')
1449
+ t.assert.strictEqual(invalid2.statusCode, 400)
1450
+ t.assert.strictEqual((await invalid2.body.json()).code, 'FST_ERR_VALIDATION')
1416
1451
 
1417
1452
  const invalid3 = await request(address, {
1418
1453
  method: 'POST',
@@ -1422,8 +1457,8 @@ test('Schema validation will not be bypass by different content type', async t =
1422
1457
  },
1423
1458
  body: JSON.stringify({ invalid: 'string' })
1424
1459
  })
1425
- t.equal(invalid3.statusCode, 400)
1426
- t.equal((await invalid3.body.json()).code, 'FST_ERR_VALIDATION')
1460
+ t.assert.strictEqual(invalid3.statusCode, 400)
1461
+ t.assert.strictEqual((await invalid3.body.json()).code, 'FST_ERR_VALIDATION')
1427
1462
 
1428
1463
  const invalid4 = await request(address, {
1429
1464
  method: 'POST',
@@ -1433,6 +1468,50 @@ test('Schema validation will not be bypass by different content type', async t =
1433
1468
  },
1434
1469
  body: JSON.stringify({ invalid: 'string' })
1435
1470
  })
1436
- t.equal(invalid4.statusCode, 400)
1437
- t.equal((await invalid4.body.json()).code, 'FST_ERR_VALIDATION')
1471
+ t.assert.strictEqual(invalid4.statusCode, 400)
1472
+ t.assert.strictEqual((await invalid4.body.json()).code, 'FST_ERR_VALIDATION')
1473
+
1474
+ const invalid5 = await request(address, {
1475
+ method: 'POST',
1476
+ url: '/',
1477
+ headers: {
1478
+ 'content-type': 'ApPlIcAtIoN/JsOn \tfoo;'
1479
+ },
1480
+ body: JSON.stringify({ invalid: 'string' })
1481
+ })
1482
+ t.assert.strictEqual(invalid5.statusCode, 400)
1483
+ t.assert.strictEqual((await invalid5.body.json()).code, 'FST_ERR_VALIDATION')
1484
+
1485
+ const invalid6 = await request(address, {
1486
+ method: 'POST',
1487
+ url: '/',
1488
+ headers: {
1489
+ 'content-type': 'ApPlIcAtIoN/JsOn\t foo;'
1490
+ },
1491
+ body: JSON.stringify({ invalid: 'string' })
1492
+ })
1493
+ t.assert.strictEqual(invalid6.statusCode, 415)
1494
+ t.assert.strictEqual((await invalid6.body.json()).code, 'FST_ERR_CTP_INVALID_MEDIA_TYPE')
1495
+
1496
+ const invalid7 = await request(address, {
1497
+ method: 'POST',
1498
+ url: '/',
1499
+ headers: {
1500
+ 'content-type': 'ApPlIcAtIoN/JsOn \t'
1501
+ },
1502
+ body: JSON.stringify({ invalid: 'string' })
1503
+ })
1504
+ t.assert.strictEqual(invalid7.statusCode, 400)
1505
+ t.assert.strictEqual((await invalid7.body.json()).code, 'FST_ERR_VALIDATION')
1506
+
1507
+ const invalid8 = await request(address, {
1508
+ method: 'POST',
1509
+ url: '/',
1510
+ headers: {
1511
+ 'content-type': 'ApPlIcAtIoN/JsOn\t'
1512
+ },
1513
+ body: JSON.stringify({ invalid: 'string' })
1514
+ })
1515
+ t.assert.strictEqual(invalid8.statusCode, 400)
1516
+ t.assert.strictEqual((await invalid8.body.json()).code, 'FST_ERR_VALIDATION')
1438
1517
  })