fastify 3.27.3 → 4.0.0-alpha.2

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 (164) hide show
  1. package/.taprc +3 -0
  2. package/README.md +7 -7
  3. package/build/build-error-serializer.js +27 -0
  4. package/build/build-validation.js +47 -35
  5. package/docs/Guides/Database.md +320 -0
  6. package/docs/Guides/Getting-Started.md +7 -7
  7. package/docs/Guides/Plugins-Guide.md +1 -1
  8. package/docs/Guides/Serverless.md +3 -3
  9. package/docs/Guides/Testing.md +2 -2
  10. package/docs/Migration-Guide-V4.md +12 -0
  11. package/docs/Reference/ContentTypeParser.md +4 -0
  12. package/docs/Reference/Decorators.md +2 -2
  13. package/docs/Reference/Encapsulation.md +2 -2
  14. package/docs/Reference/Errors.md +51 -6
  15. package/docs/Reference/HTTP2.md +3 -3
  16. package/docs/Reference/Hooks.md +4 -7
  17. package/docs/Reference/LTS.md +5 -4
  18. package/docs/Reference/Plugins.md +3 -3
  19. package/docs/Reference/Reply.md +23 -22
  20. package/docs/Reference/Request.md +1 -3
  21. package/docs/Reference/Routes.md +22 -15
  22. package/docs/Reference/Server.md +69 -119
  23. package/docs/Reference/TypeScript.md +20 -22
  24. package/docs/Reference/Validation-and-Serialization.md +30 -55
  25. package/docs/Type-Providers.md +257 -0
  26. package/examples/asyncawait.js +1 -1
  27. package/examples/benchmark/hooks-benchmark-async-await.js +1 -1
  28. package/examples/benchmark/hooks-benchmark.js +1 -1
  29. package/examples/benchmark/simple.js +1 -1
  30. package/examples/hooks.js +2 -2
  31. package/examples/http2.js +1 -1
  32. package/examples/https.js +1 -1
  33. package/examples/parser.js +1 -1
  34. package/examples/route-prefix.js +1 -1
  35. package/examples/shared-schema.js +1 -1
  36. package/examples/simple-stream.js +18 -0
  37. package/examples/simple.js +1 -1
  38. package/examples/simple.mjs +1 -1
  39. package/examples/typescript-server.ts +1 -1
  40. package/examples/use-plugin.js +1 -1
  41. package/fastify.d.ts +34 -22
  42. package/fastify.js +40 -36
  43. package/lib/configValidator.js +902 -1023
  44. package/lib/contentTypeParser.js +6 -16
  45. package/lib/context.js +36 -10
  46. package/lib/decorate.js +3 -1
  47. package/lib/error-handler.js +158 -0
  48. package/lib/error-serializer.js +257 -0
  49. package/lib/errors.js +43 -9
  50. package/lib/fourOhFour.js +31 -20
  51. package/lib/handleRequest.js +10 -13
  52. package/lib/hooks.js +14 -9
  53. package/lib/pluginOverride.js +0 -3
  54. package/lib/pluginUtils.js +3 -2
  55. package/lib/reply.js +29 -158
  56. package/lib/request.js +13 -10
  57. package/lib/route.js +131 -138
  58. package/lib/schema-controller.js +2 -2
  59. package/lib/schemas.js +27 -1
  60. package/lib/server.js +241 -116
  61. package/lib/symbols.js +4 -3
  62. package/lib/validation.js +2 -1
  63. package/lib/warnings.js +4 -12
  64. package/lib/wrapThenable.js +4 -11
  65. package/package.json +37 -39
  66. package/test/404s.test.js +258 -125
  67. package/test/500s.test.js +3 -3
  68. package/test/als.test.js +1 -1
  69. package/test/async-await.test.js +20 -76
  70. package/test/bodyLimit.test.js +1 -1
  71. package/test/build-certificate.js +6 -7
  72. package/test/case-insensitive.test.js +4 -4
  73. package/test/close-pipelining.test.js +2 -2
  74. package/test/close.test.js +11 -11
  75. package/test/content-parser.test.js +32 -0
  76. package/test/context-config.test.js +52 -0
  77. package/test/custom-http-server.test.js +14 -7
  78. package/test/custom-parser-async.test.js +1 -66
  79. package/test/custom-parser.test.js +92 -159
  80. package/test/custom-querystring-parser.test.js +3 -3
  81. package/test/decorator.test.js +11 -13
  82. package/test/delete.test.js +6 -6
  83. package/test/encapsulated-error-handler.test.js +50 -0
  84. package/test/esm/index.test.js +0 -14
  85. package/test/fastify-instance.test.js +4 -4
  86. package/test/fluent-schema.test.js +4 -4
  87. package/test/genReqId.test.js +1 -1
  88. package/test/get.test.js +4 -4
  89. package/test/handler-context.test.js +2 -2
  90. package/test/head.test.js +1 -1
  91. package/test/helper.js +19 -4
  92. package/test/hooks-async.test.js +15 -48
  93. package/test/hooks.on-ready.test.js +10 -5
  94. package/test/hooks.test.js +78 -119
  95. package/test/http2/closing.test.js +10 -16
  96. package/test/http2/constraint.test.js +1 -1
  97. package/test/http2/head.test.js +1 -1
  98. package/test/http2/plain.test.js +1 -1
  99. package/test/http2/secure-with-fallback.test.js +1 -1
  100. package/test/http2/secure.test.js +1 -1
  101. package/test/http2/unknown-http-method.test.js +4 -10
  102. package/test/https/custom-https-server.test.js +12 -6
  103. package/test/https/https.test.js +1 -1
  104. package/test/input-validation.js +3 -3
  105. package/test/internals/handleRequest.test.js +6 -43
  106. package/test/internals/initialConfig.test.js +41 -12
  107. package/test/internals/logger.test.js +2 -2
  108. package/test/internals/reply.test.js +281 -40
  109. package/test/internals/request.test.js +13 -7
  110. package/test/internals/server.test.js +88 -0
  111. package/test/listen.deprecated.test.js +202 -0
  112. package/test/listen.test.js +118 -150
  113. package/test/logger.test.js +82 -42
  114. package/test/maxRequestsPerSocket.test.js +8 -6
  115. package/test/middleware.test.js +2 -25
  116. package/test/nullable-validation.test.js +53 -16
  117. package/test/output-validation.test.js +1 -1
  118. package/test/plugin.test.js +47 -21
  119. package/test/pretty-print.test.js +22 -10
  120. package/test/promises.test.js +1 -1
  121. package/test/proto-poisoning.test.js +6 -6
  122. package/test/register.test.js +3 -3
  123. package/test/reply-error.test.js +126 -15
  124. package/test/request-error.test.js +3 -6
  125. package/test/route-hooks.test.js +18 -18
  126. package/test/route-prefix.test.js +2 -1
  127. package/test/route.test.js +206 -22
  128. package/test/router-options.test.js +2 -2
  129. package/test/schema-examples.test.js +11 -5
  130. package/test/schema-feature.test.js +25 -20
  131. package/test/schema-serialization.test.js +9 -9
  132. package/test/schema-special-usage.test.js +5 -153
  133. package/test/schema-validation.test.js +9 -9
  134. package/test/skip-reply-send.test.js +2 -2
  135. package/test/stream.test.js +82 -23
  136. package/test/throw.test.js +8 -5
  137. package/test/trust-proxy.test.js +6 -6
  138. package/test/type-provider.test.js +20 -0
  139. package/test/types/fastify.test-d.ts +10 -18
  140. package/test/types/import.js +2 -0
  141. package/test/types/import.ts +1 -0
  142. package/test/types/instance.test-d.ts +68 -17
  143. package/test/types/logger.test-d.ts +44 -15
  144. package/test/types/reply.test-d.ts +2 -1
  145. package/test/types/route.test-d.ts +8 -2
  146. package/test/types/schema.test-d.ts +2 -39
  147. package/test/types/type-provider.test-d.ts +417 -0
  148. package/test/url-rewriting.test.js +3 -3
  149. package/test/validation-error-handling.test.js +8 -8
  150. package/test/versioned-routes.test.js +30 -18
  151. package/test/wrapThenable.test.js +7 -6
  152. package/types/content-type-parser.d.ts +17 -8
  153. package/types/hooks.d.ts +102 -59
  154. package/types/instance.d.ts +244 -118
  155. package/types/logger.d.ts +18 -104
  156. package/types/plugin.d.ts +10 -4
  157. package/types/reply.d.ts +18 -12
  158. package/types/request.d.ts +10 -5
  159. package/types/route.d.ts +42 -31
  160. package/types/schema.d.ts +1 -1
  161. package/types/type-provider.d.ts +99 -0
  162. package/types/utils.d.ts +1 -1
  163. package/lib/schema-compilers.js +0 -12
  164. package/test/emit-warning.test.js +0 -166
@@ -0,0 +1,417 @@
1
+ import fastify, { FastifyTypeProvider } from '../../fastify'
2
+ import { expectAssignable, expectError, expectType } from 'tsd'
3
+ import { IncomingHttpHeaders } from 'http'
4
+ import { Type, TSchema, Static } from '@sinclair/typebox'
5
+ import { FromSchema, JSONSchema } from 'json-schema-to-ts'
6
+
7
+ const server = fastify()
8
+
9
+ // -------------------------------------------------------------------
10
+ // Remapping
11
+ // -------------------------------------------------------------------
12
+
13
+ interface NumberProvider extends FastifyTypeProvider { output: number } // remap all schemas to numbers
14
+
15
+ expectAssignable(server.withTypeProvider<NumberProvider>().get(
16
+ '/',
17
+ {
18
+ schema: {
19
+ body: { type: 'string' },
20
+ querystring: { type: 'string' },
21
+ headers: { type: 'string' },
22
+ params: { type: 'string' }
23
+ }
24
+ },
25
+ (req) => {
26
+ expectType<number & IncomingHttpHeaders>(req.headers)
27
+ expectType<number>(req.body)
28
+ expectType<number>(req.query)
29
+ expectType<number>(req.params)
30
+ }
31
+ ))
32
+
33
+ // -------------------------------------------------------------------
34
+ // Override
35
+ // -------------------------------------------------------------------
36
+
37
+ interface OverriddenProvider extends FastifyTypeProvider { output: 'inferenced' }
38
+
39
+ expectAssignable(server.withTypeProvider<OverriddenProvider>().get<{ Body: 'override' }>(
40
+ '/',
41
+ {
42
+ schema: {
43
+ body: Type.Object({
44
+ x: Type.Number(),
45
+ y: Type.Number(),
46
+ z: Type.Number()
47
+ })
48
+ }
49
+ },
50
+ (req) => {
51
+ expectType<'override'>(req.body)
52
+ }
53
+ ))
54
+
55
+ // -------------------------------------------------------------------
56
+ // TypeBox
57
+ // -------------------------------------------------------------------
58
+
59
+ interface TypeBoxProvider extends FastifyTypeProvider { output: this['input'] extends TSchema ? Static<this['input']> : never }
60
+
61
+ expectAssignable(server.withTypeProvider<TypeBoxProvider>().get(
62
+ '/',
63
+ {
64
+ schema: {
65
+ body: Type.Object({
66
+ x: Type.Number(),
67
+ y: Type.Number(),
68
+ z: Type.Number()
69
+ })
70
+ }
71
+ },
72
+ (req) => {
73
+ expectType<number>(req.body.x)
74
+ expectType<number>(req.body.y)
75
+ expectType<number>(req.body.z)
76
+ }
77
+ ))
78
+
79
+ // -------------------------------------------------------------------
80
+ // JsonSchemaToTs
81
+ // -------------------------------------------------------------------
82
+
83
+ interface JsonSchemaToTsProvider extends FastifyTypeProvider { output: this['input'] extends JSONSchema ? FromSchema<this['input']> : never }
84
+
85
+ expectAssignable(server.withTypeProvider<JsonSchemaToTsProvider>().get(
86
+ '/',
87
+ {
88
+ schema: {
89
+ body: {
90
+ type: 'object',
91
+ properties: {
92
+ x: { type: 'number' },
93
+ y: { type: 'string' },
94
+ z: { type: 'boolean' }
95
+ }
96
+ } as const
97
+ }
98
+ },
99
+ (req) => {
100
+ expectType<number | undefined>(req.body.x)
101
+ expectType<string | undefined>(req.body.y)
102
+ expectType<boolean | undefined>(req.body.z)
103
+ }
104
+ ))
105
+
106
+ // -------------------------------------------------------------------
107
+ // Instance Type Remappable
108
+ // -------------------------------------------------------------------
109
+
110
+ expectAssignable(server.withTypeProvider<TypeBoxProvider>().withTypeProvider<JsonSchemaToTsProvider>().get(
111
+ '/',
112
+ {
113
+ schema: {
114
+ body: {
115
+ type: 'object',
116
+ properties: {
117
+ x: { type: 'number' },
118
+ y: { type: 'string' },
119
+ z: { type: 'boolean' }
120
+ }
121
+ } as const
122
+ }
123
+ },
124
+ (req) => {
125
+ expectType<number | undefined>(req.body.x)
126
+ expectType<string | undefined>(req.body.y)
127
+ expectType<boolean | undefined>(req.body.z)
128
+ }
129
+ ))
130
+
131
+ // -------------------------------------------------------------------
132
+ // Request Hooks
133
+ // -------------------------------------------------------------------
134
+
135
+ expectAssignable(server.withTypeProvider<TypeBoxProvider>().get(
136
+ '/',
137
+ {
138
+ schema: {
139
+ body: Type.Object({
140
+ x: Type.Number(),
141
+ y: Type.String(),
142
+ z: Type.Boolean()
143
+ })
144
+ },
145
+ preHandler: req => {
146
+ expectType<number>(req.body.x)
147
+ expectType<string>(req.body.y)
148
+ expectType<boolean>(req.body.z)
149
+ },
150
+ preParsing: req => {
151
+ expectType<number>(req.body.x)
152
+ expectType<string>(req.body.y)
153
+ expectType<boolean>(req.body.z)
154
+ },
155
+ preSerialization: req => {
156
+ expectType<number>(req.body.x)
157
+ expectType<string>(req.body.y)
158
+ expectType<boolean>(req.body.z)
159
+ },
160
+ preValidation: req => {
161
+ expectType<number>(req.body.x)
162
+ expectType<string>(req.body.y)
163
+ expectType<boolean>(req.body.z)
164
+ },
165
+ onError: req => {
166
+ expectType<number>(req.body.x)
167
+ expectType<string>(req.body.y)
168
+ expectType<boolean>(req.body.z)
169
+ },
170
+ onRequest: req => {
171
+ expectType<number>(req.body.x)
172
+ expectType<string>(req.body.y)
173
+ expectType<boolean>(req.body.z)
174
+ },
175
+ onResponse: req => {
176
+ expectType<number>(req.body.x)
177
+ expectType<string>(req.body.y)
178
+ expectType<boolean>(req.body.z)
179
+ },
180
+ onTimeout: req => {
181
+ expectType<number>(req.body.x)
182
+ expectType<string>(req.body.y)
183
+ expectType<boolean>(req.body.z)
184
+ },
185
+ onSend: req => {
186
+ expectType<number>(req.body.x)
187
+ expectType<string>(req.body.y)
188
+ expectType<boolean>(req.body.z)
189
+ }
190
+ },
191
+ req => {
192
+ expectType<number>(req.body.x)
193
+ expectType<string>(req.body.y)
194
+ expectType<boolean>(req.body.z)
195
+ }
196
+ ))
197
+
198
+ // -------------------------------------------------------------------
199
+ // TypeBox Reply Type
200
+ // -------------------------------------------------------------------
201
+
202
+ expectAssignable(server.withTypeProvider<TypeBoxProvider>().get(
203
+ '/',
204
+ {
205
+ schema: {
206
+ response: {
207
+ 200: Type.String(),
208
+ 400: Type.Number(),
209
+ 500: Type.Object({
210
+ error: Type.String()
211
+ })
212
+ }
213
+ }
214
+ },
215
+ async (_, res) => {
216
+ res.send('hello')
217
+ res.send(42)
218
+ res.send({ error: 'error' })
219
+ }
220
+ ))
221
+
222
+ // -------------------------------------------------------------------
223
+ // TypeBox Reply Type: Non Assignable
224
+ // -------------------------------------------------------------------
225
+
226
+ expectError(server.withTypeProvider<TypeBoxProvider>().get(
227
+ '/',
228
+ {
229
+ schema: {
230
+ response: {
231
+ 200: Type.String(),
232
+ 400: Type.Number(),
233
+ 500: Type.Object({
234
+ error: Type.String()
235
+ })
236
+ }
237
+ }
238
+ },
239
+ async (_, res) => {
240
+ res.send(false)
241
+ }
242
+ ))
243
+
244
+ // -------------------------------------------------------------------
245
+ // TypeBox Reply Return Type
246
+ // -------------------------------------------------------------------
247
+
248
+ expectAssignable(server.withTypeProvider<TypeBoxProvider>().get(
249
+ '/',
250
+ {
251
+ schema: {
252
+ response: {
253
+ 200: Type.String(),
254
+ 400: Type.Number(),
255
+ 500: Type.Object({
256
+ error: Type.String()
257
+ })
258
+ }
259
+ }
260
+ },
261
+ async (_, res) => {
262
+ const option = 1 as 1 | 2 | 3
263
+ switch (option) {
264
+ case 1: return 'hello'
265
+ case 2: return 42
266
+ case 3: return { error: 'error' }
267
+ }
268
+ }
269
+ ))
270
+
271
+ // -------------------------------------------------------------------
272
+ // TypeBox Reply Return Type: Non Assignable
273
+ // -------------------------------------------------------------------
274
+
275
+ expectError(server.withTypeProvider<TypeBoxProvider>().get(
276
+ '/',
277
+ {
278
+ schema: {
279
+ response: {
280
+ 200: Type.String(),
281
+ 400: Type.Number(),
282
+ 500: Type.Object({
283
+ error: Type.String()
284
+ })
285
+ }
286
+ }
287
+ },
288
+ async (_, res) => {
289
+ return false
290
+ }
291
+ ))
292
+
293
+ // -------------------------------------------------------------------
294
+ // JsonSchemaToTs Reply Type
295
+ // -------------------------------------------------------------------
296
+
297
+ expectAssignable(server.withTypeProvider<JsonSchemaToTsProvider>().get(
298
+ '/',
299
+ {
300
+ schema: {
301
+ response: {
302
+ 200: { type: 'string' },
303
+ 400: { type: 'number' },
304
+ 500: { type: 'object', properties: { error: { type: 'string' } } }
305
+ } as const
306
+ }
307
+ },
308
+ (_, res) => {
309
+ res.send('hello')
310
+ res.send(42)
311
+ res.send({ error: 'error' })
312
+ }
313
+ ))
314
+
315
+ // -------------------------------------------------------------------
316
+ // JsonSchemaToTs Reply Type: Non Assignable
317
+ // -------------------------------------------------------------------
318
+
319
+ expectError(server.withTypeProvider<JsonSchemaToTsProvider>().get(
320
+ '/',
321
+ {
322
+ schema: {
323
+ response: {
324
+ 200: { type: 'string' },
325
+ 400: { type: 'number' },
326
+ 500: { type: 'object', properties: { error: { type: 'string' } } }
327
+ } as const
328
+ }
329
+ },
330
+ async (_, res) => {
331
+ res.send(false)
332
+ }
333
+ ))
334
+
335
+ // -------------------------------------------------------------------
336
+ // JsonSchemaToTs Reply Type Return
337
+ // -------------------------------------------------------------------
338
+
339
+ expectAssignable(server.withTypeProvider<JsonSchemaToTsProvider>().get(
340
+ '/',
341
+ {
342
+ schema: {
343
+ response: {
344
+ 200: { type: 'string' },
345
+ 400: { type: 'number' },
346
+ 500: { type: 'object', properties: { error: { type: 'string' } } }
347
+ } as const
348
+ }
349
+ },
350
+ async (_, res) => {
351
+ const option = 1 as 1 | 2 | 3
352
+ switch (option) {
353
+ case 1: return 'hello'
354
+ case 2: return 42
355
+ case 3: return { error: 'error' }
356
+ }
357
+ }
358
+ ))
359
+ // -------------------------------------------------------------------
360
+ // JsonSchemaToTs Reply Type Return: Non Assignable
361
+ // -------------------------------------------------------------------
362
+
363
+ expectError(server.withTypeProvider<JsonSchemaToTsProvider>().get(
364
+ '/',
365
+ {
366
+ schema: {
367
+ response: {
368
+ 200: { type: 'string' },
369
+ 400: { type: 'number' },
370
+ 500: { type: 'object', properties: { error: { type: 'string' } } }
371
+ } as const
372
+ }
373
+ },
374
+ async (_, res) => {
375
+ return false
376
+ }
377
+ ))
378
+
379
+ // -------------------------------------------------------------------
380
+ // Reply Type Override
381
+ // -------------------------------------------------------------------
382
+
383
+ expectAssignable(server.withTypeProvider<JsonSchemaToTsProvider>().get<{Reply: boolean}>(
384
+ '/',
385
+ {
386
+ schema: {
387
+ response: {
388
+ 200: { type: 'string' },
389
+ 400: { type: 'number' },
390
+ 500: { type: 'object', properties: { error: { type: 'string' } } }
391
+ } as const
392
+ }
393
+ },
394
+ async (_, res) => {
395
+ res.send(true)
396
+ }
397
+ ))
398
+
399
+ // -------------------------------------------------------------------
400
+ // Reply Type Return Override
401
+ // -------------------------------------------------------------------
402
+
403
+ expectAssignable(server.withTypeProvider<JsonSchemaToTsProvider>().get<{Reply: boolean}>(
404
+ '/',
405
+ {
406
+ schema: {
407
+ response: {
408
+ 200: { type: 'string' },
409
+ 400: { type: 'number' },
410
+ 500: { type: 'object', properties: { error: { type: 'string' } } }
411
+ } as const
412
+ }
413
+ },
414
+ async (_, res) => {
415
+ return true
416
+ }
417
+ ))
@@ -22,7 +22,7 @@ test('Should rewrite url', t => {
22
22
  }
23
23
  })
24
24
 
25
- fastify.listen(0, function (err) {
25
+ fastify.listen({ port: 0 }, function (err) {
26
26
  t.error(err)
27
27
 
28
28
  sget({
@@ -55,7 +55,7 @@ test('Should not rewrite if the url is the same', t => {
55
55
  }
56
56
  })
57
57
 
58
- fastify.listen(0, function (err) {
58
+ fastify.listen({ port: 0 }, function (err) {
59
59
  t.error(err)
60
60
 
61
61
  sget({
@@ -86,7 +86,7 @@ test('Should throw an error', t => {
86
86
  }
87
87
  })
88
88
 
89
- fastify.listen(0, function (err) {
89
+ fastify.listen({ port: 0 }, function (err) {
90
90
  t.error(err)
91
91
 
92
92
  sget({
@@ -1,7 +1,7 @@
1
1
  'use strict'
2
2
 
3
3
  const { test } = require('tap')
4
- const Joi = require('@hapi/joi')
4
+ const Joi = require('joi')
5
5
  const Fastify = require('..')
6
6
 
7
7
  const schema = {
@@ -58,7 +58,7 @@ test('should fail immediately with invalid payload', t => {
58
58
  t.same(res.json(), {
59
59
  statusCode: 400,
60
60
  error: 'Bad Request',
61
- message: "body should have required property 'name'"
61
+ message: "body must have required property 'name'"
62
62
  })
63
63
  t.equal(res.statusCode, 400)
64
64
  })
@@ -183,10 +183,10 @@ test('should be able to attach validation to request', t => {
183
183
 
184
184
  t.same(res.json(), [{
185
185
  keyword: 'required',
186
- dataPath: '',
186
+ instancePath: '',
187
187
  schemaPath: '#/required',
188
188
  params: { missingProperty: 'name' },
189
- message: 'should have required property \'name\''
189
+ message: 'must have required property \'name\''
190
190
  }])
191
191
  t.equal(res.statusCode, 400)
192
192
  })
@@ -213,7 +213,7 @@ test('should respect when attachValidation is explicitly set to false', t => {
213
213
  t.same(JSON.parse(res.payload), {
214
214
  statusCode: 400,
215
215
  error: 'Bad Request',
216
- message: "body should have required property 'name'"
216
+ message: "body must have required property 'name'"
217
217
  })
218
218
  t.equal(res.statusCode, 400)
219
219
  })
@@ -243,7 +243,7 @@ test('Attached validation error should take precedence over setErrorHandler', t
243
243
  url: '/'
244
244
  }, (err, res) => {
245
245
  t.error(err)
246
- t.same(res.payload, "Attached: Error: body should have required property 'name'")
246
+ t.same(res.payload, "Attached: Error: body must have required property 'name'")
247
247
  t.equal(res.statusCode, 400)
248
248
  })
249
249
  })
@@ -336,7 +336,7 @@ test('should return a defined output message parsing AJV errors', t => {
336
336
  url: '/'
337
337
  }, (err, res) => {
338
338
  t.error(err)
339
- t.equal(res.payload, '{"statusCode":400,"error":"Bad Request","message":"body should have required property \'name\'"}')
339
+ t.equal(res.payload, '{"statusCode":400,"error":"Bad Request","message":"body must have required property \'name\'"}')
340
340
  })
341
341
  })
342
342
 
@@ -467,7 +467,7 @@ test('should call custom error formatter', t => {
467
467
  const fastify = Fastify({
468
468
  schemaErrorFormatter: (errors, dataVar) => {
469
469
  t.equal(errors.length, 1)
470
- t.equal(errors[0].message, "should have required property 'name'")
470
+ t.equal(errors[0].message, "must have required property 'name'")
471
471
  t.equal(dataVar, 'body')
472
472
  return new Error('my error')
473
473
  }
@@ -1,7 +1,7 @@
1
1
  'use strict'
2
2
 
3
- const t = require('tap')
4
- const test = t.test
3
+ const { test, before } = require('tap')
4
+ const helper = require('./helper')
5
5
  const Fastify = require('..')
6
6
  const sget = require('simple-get').concat
7
7
  const http = require('http')
@@ -9,6 +9,13 @@ const split = require('split2')
9
9
  const append = require('vary').append
10
10
  const proxyquire = require('proxyquire')
11
11
 
12
+ process.removeAllListeners('warning')
13
+
14
+ let localhost
15
+ before(async function () {
16
+ [localhost] = await helper.getLoopbackHost()
17
+ })
18
+
12
19
  test('Should register a versioned route', t => {
13
20
  t.plan(11)
14
21
  const fastify = Fastify()
@@ -235,7 +242,7 @@ test('Should register a versioned route', t => {
235
242
  }
236
243
  })
237
244
 
238
- fastify.listen(0, err => {
245
+ fastify.listen({ port: 0 }, err => {
239
246
  t.error(err)
240
247
  fastify.server.unref()
241
248
 
@@ -400,7 +407,7 @@ test('Bas accept version (server)', t => {
400
407
  }
401
408
  })
402
409
 
403
- fastify.listen(0, err => {
410
+ fastify.listen({ port: 0 }, err => {
404
411
  t.error(err)
405
412
  fastify.server.unref()
406
413
 
@@ -442,12 +449,12 @@ test('test log stream', t => {
442
449
  reply.send(new Error('kaboom'))
443
450
  })
444
451
 
445
- fastify.listen(0, err => {
452
+ fastify.listen({ port: 0, host: localhost }, err => {
446
453
  t.error(err)
447
454
  fastify.server.unref()
448
455
 
449
456
  http.get({
450
- hostname: 'localhost',
457
+ hostname: fastify.server.address().hostname,
451
458
  port: fastify.server.address().port,
452
459
  path: '/',
453
460
  method: 'GET',
@@ -549,7 +556,7 @@ test('Should register a versioned route with custom versioning strategy', t => {
549
556
  })
550
557
 
551
558
  test('Should get error using an invalid a versioned route, using default validation (deprecated versioning option)', t => {
552
- t.plan(1)
559
+ t.plan(3)
553
560
 
554
561
  const fastify = Fastify({
555
562
  versioning: {
@@ -577,15 +584,19 @@ test('Should get error using an invalid a versioned route, using default validat
577
584
  }
578
585
  })
579
586
 
580
- fastify.route({
581
- method: 'GET',
582
- url: '/',
583
- // not a string version
584
- constraints: { version: 2 },
585
- handler: (req, reply) => {
586
- reply.send({ hello: 'cant match route v2' })
587
- }
588
- })
587
+ try {
588
+ fastify.route({
589
+ method: 'GET',
590
+ url: '/',
591
+ // not a string version
592
+ constraints: { version: 2 },
593
+ handler: (req, reply) => {
594
+ reply.send({ hello: 'cant match route v2' })
595
+ }
596
+ })
597
+ } catch (err) {
598
+ t.equal(err.message, 'Version constraint should be a string.')
599
+ }
589
600
 
590
601
  fastify.inject({
591
602
  method: 'GET',
@@ -594,7 +605,8 @@ test('Should get error using an invalid a versioned route, using default validat
594
605
  Accept: 'application/vnd.example.api+json;version=2'
595
606
  }
596
607
  }, (err, res) => {
597
- t.equal(err.message, 'Version constraint should be a string.')
608
+ t.error(err)
609
+ t.equal(res.statusCode, 404)
598
610
  })
599
611
  })
600
612
 
@@ -663,7 +675,7 @@ test('Should trigger a warning when a versioned route is registered via version
663
675
  }
664
676
 
665
677
  const route = proxyquire('../lib/route', { './warnings': warning })
666
- const fastify = proxyquire('..', { './lib/route.js': route })()
678
+ const fastify = proxyquire('..', { './lib/route.js': route })({ exposeHeadRoutes: false })
667
679
 
668
680
  fastify.route({
669
681
  method: 'GET',
@@ -2,21 +2,22 @@
2
2
 
3
3
  const t = require('tap')
4
4
  const test = t.test
5
- const { kReplySentOverwritten } = require('../lib/symbols')
5
+ const { kReplyHijacked } = require('../lib/symbols')
6
6
  const wrapThenable = require('../lib/wrapThenable')
7
+ const Reply = require('../lib/reply')
7
8
 
8
- test('should resolve immediately when reply[kReplySentOverwritten] is true', t => {
9
+ test('should resolve immediately when reply[kReplyHijacked] is true', t => {
9
10
  const reply = {}
10
- reply[kReplySentOverwritten] = true
11
+ reply[kReplyHijacked] = true
11
12
  const thenable = Promise.resolve()
12
13
  wrapThenable(thenable, reply)
13
14
  t.end()
14
15
  })
15
16
 
16
- test('should reject immediately when reply[kReplySentOverwritten] is true', t => {
17
+ test('should reject immediately when reply[kReplyHijacked] is true', t => {
17
18
  t.plan(1)
18
- const reply = { res: {} }
19
- reply[kReplySentOverwritten] = true
19
+ const reply = new Reply({}, {}, {})
20
+ reply[kReplyHijacked] = true
20
21
  reply.log = {
21
22
  error: ({ err }) => {
22
23
  t.equal(err.message, 'Reply sent already')