fastify 5.3.0 → 5.3.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.
@@ -2,17 +2,16 @@
2
2
 
3
3
  const stream = require('node:stream')
4
4
 
5
- const t = require('tap')
5
+ const t = require('node:test')
6
6
  const split = require('split2')
7
7
 
8
8
  const Fastify = require('../../fastify')
9
9
  const helper = require('../helper')
10
10
  const { on } = stream
11
11
  const { request } = require('./logger-test-utils')
12
+ const { partialDeepStrictEqual } = require('../toolkit')
12
13
 
13
- t.test('request', (t) => {
14
- t.setTimeout(60000)
15
-
14
+ t.test('request', { timeout: 60000 }, async (t) => {
16
15
  let localhost
17
16
 
18
17
  t.plan(7)
@@ -20,7 +19,7 @@ t.test('request', (t) => {
20
19
  [localhost] = await helper.getLoopbackHost()
21
20
  })
22
21
 
23
- t.test('The request id header key can be customized', async (t) => {
22
+ await t.test('The request id header key can be customized', async (t) => {
24
23
  const lines = ['incoming request', 'some log message', 'request completed']
25
24
  t.plan(lines.length * 2 + 2)
26
25
  const REQUEST_ID = '42'
@@ -30,26 +29,26 @@ t.test('request', (t) => {
30
29
  logger: { stream, level: 'info' },
31
30
  requestIdHeader: 'my-custom-request-id'
32
31
  })
33
- t.teardown(fastify.close.bind(fastify))
32
+ t.after(() => fastify.close())
34
33
 
35
34
  fastify.get('/', (req, reply) => {
36
- t.equal(req.id, REQUEST_ID)
35
+ t.assert.strictEqual(req.id, REQUEST_ID)
37
36
  req.log.info('some log message')
38
37
  reply.send({ id: req.id })
39
38
  })
40
39
 
41
40
  const response = await fastify.inject({ method: 'GET', url: '/', headers: { 'my-custom-request-id': REQUEST_ID } })
42
41
  const body = await response.json()
43
- t.equal(body.id, REQUEST_ID)
42
+ t.assert.strictEqual(body.id, REQUEST_ID)
44
43
 
45
44
  for await (const [line] of on(stream, 'data')) {
46
- t.equal(line.reqId, REQUEST_ID)
47
- t.equal(line.msg, lines.shift(), 'message is set')
45
+ t.assert.strictEqual(line.reqId, REQUEST_ID)
46
+ t.assert.strictEqual(line.msg, lines.shift(), 'message is set')
48
47
  if (lines.length === 0) break
49
48
  }
50
49
  })
51
50
 
52
- t.test('The request id header key can be ignored', async (t) => {
51
+ await t.test('The request id header key can be ignored', async (t) => {
53
52
  const lines = ['incoming request', 'some log message', 'request completed']
54
53
  t.plan(lines.length * 2 + 2)
55
54
  const REQUEST_ID = 'ignore-me'
@@ -59,33 +58,33 @@ t.test('request', (t) => {
59
58
  logger: { stream, level: 'info' },
60
59
  requestIdHeader: false
61
60
  })
62
- t.teardown(fastify.close.bind(fastify))
61
+ t.after(() => fastify.close())
63
62
 
64
63
  fastify.get('/', (req, reply) => {
65
- t.equal(req.id, 'req-1')
64
+ t.assert.strictEqual(req.id, 'req-1')
66
65
  req.log.info('some log message')
67
66
  reply.send({ id: req.id })
68
67
  })
69
68
  const response = await fastify.inject({ method: 'GET', url: '/', headers: { 'request-id': REQUEST_ID } })
70
69
  const body = await response.json()
71
- t.equal(body.id, 'req-1')
70
+ t.assert.strictEqual(body.id, 'req-1')
72
71
 
73
72
  for await (const [line] of on(stream, 'data')) {
74
- t.equal(line.reqId, 'req-1')
75
- t.equal(line.msg, lines.shift(), 'message is set')
73
+ t.assert.strictEqual(line.reqId, 'req-1')
74
+ t.assert.strictEqual(line.msg, lines.shift(), 'message is set')
76
75
  if (lines.length === 0) break
77
76
  }
78
77
  })
79
78
 
80
- t.test('The request id header key can be customized along with a custom id generator', async (t) => {
79
+ await t.test('The request id header key can be customized along with a custom id generator', async (t) => {
81
80
  const REQUEST_ID = '42'
82
81
  const matches = [
83
- { reqId: REQUEST_ID, msg: /incoming request/ },
84
- { reqId: REQUEST_ID, msg: /some log message/ },
85
- { reqId: REQUEST_ID, msg: /request completed/ },
86
- { reqId: 'foo', msg: /incoming request/ },
87
- { reqId: 'foo', msg: /some log message 2/ },
88
- { reqId: 'foo', msg: /request completed/ }
82
+ { reqId: REQUEST_ID, msg: 'incoming request' },
83
+ { reqId: REQUEST_ID, msg: 'some log message' },
84
+ { reqId: REQUEST_ID, msg: 'request completed' },
85
+ { reqId: 'foo', msg: 'incoming request' },
86
+ { reqId: 'foo', msg: 'some log message 2' },
87
+ { reqId: 'foo', msg: 'request completed' }
89
88
  ]
90
89
  t.plan(matches.length + 4)
91
90
 
@@ -97,16 +96,16 @@ t.test('request', (t) => {
97
96
  return 'foo'
98
97
  }
99
98
  })
100
- t.teardown(fastify.close.bind(fastify))
99
+ t.after(() => fastify.close())
101
100
 
102
101
  fastify.get('/one', (req, reply) => {
103
- t.equal(req.id, REQUEST_ID)
102
+ t.assert.strictEqual(req.id, REQUEST_ID)
104
103
  req.log.info('some log message')
105
104
  reply.send({ id: req.id })
106
105
  })
107
106
 
108
107
  fastify.get('/two', (req, reply) => {
109
- t.equal(req.id, 'foo')
108
+ t.assert.strictEqual(req.id, 'foo')
110
109
  req.log.info('some log message 2')
111
110
  reply.send({ id: req.id })
112
111
  })
@@ -114,30 +113,30 @@ t.test('request', (t) => {
114
113
  {
115
114
  const response = await fastify.inject({ method: 'GET', url: '/one', headers: { 'my-custom-request-id': REQUEST_ID } })
116
115
  const body = await response.json()
117
- t.equal(body.id, REQUEST_ID)
116
+ t.assert.strictEqual(body.id, REQUEST_ID)
118
117
  }
119
118
 
120
119
  {
121
120
  const response = await fastify.inject({ method: 'GET', url: '/two' })
122
121
  const body = await response.json()
123
- t.equal(body.id, 'foo')
122
+ t.assert.strictEqual(body.id, 'foo')
124
123
  }
125
124
 
126
125
  for await (const [line] of on(stream, 'data')) {
127
- t.match(line, matches.shift())
126
+ t.assert.ok(partialDeepStrictEqual(line, matches.shift()))
128
127
  if (matches.length === 0) break
129
128
  }
130
129
  })
131
130
 
132
- t.test('The request id header key can be ignored along with a custom id generator', async (t) => {
131
+ await t.test('The request id header key can be ignored along with a custom id generator', async (t) => {
133
132
  const REQUEST_ID = 'ignore-me'
134
133
  const matches = [
135
- { reqId: 'foo', msg: /incoming request/ },
136
- { reqId: 'foo', msg: /some log message/ },
137
- { reqId: 'foo', msg: /request completed/ },
138
- { reqId: 'foo', msg: /incoming request/ },
139
- { reqId: 'foo', msg: /some log message 2/ },
140
- { reqId: 'foo', msg: /request completed/ }
134
+ { reqId: 'foo', msg: 'incoming request' },
135
+ { reqId: 'foo', msg: 'some log message' },
136
+ { reqId: 'foo', msg: 'request completed' },
137
+ { reqId: 'foo', msg: 'incoming request' },
138
+ { reqId: 'foo', msg: 'some log message 2' },
139
+ { reqId: 'foo', msg: 'request completed' }
141
140
  ]
142
141
  t.plan(matches.length + 4)
143
142
 
@@ -149,16 +148,16 @@ t.test('request', (t) => {
149
148
  return 'foo'
150
149
  }
151
150
  })
152
- t.teardown(fastify.close.bind(fastify))
151
+ t.after(() => fastify.close())
153
152
 
154
153
  fastify.get('/one', (req, reply) => {
155
- t.equal(req.id, 'foo')
154
+ t.assert.strictEqual(req.id, 'foo')
156
155
  req.log.info('some log message')
157
156
  reply.send({ id: req.id })
158
157
  })
159
158
 
160
159
  fastify.get('/two', (req, reply) => {
161
- t.equal(req.id, 'foo')
160
+ t.assert.strictEqual(req.id, 'foo')
162
161
  req.log.info('some log message 2')
163
162
  reply.send({ id: req.id })
164
163
  })
@@ -166,27 +165,27 @@ t.test('request', (t) => {
166
165
  {
167
166
  const response = await fastify.inject({ method: 'GET', url: '/one', headers: { 'request-id': REQUEST_ID } })
168
167
  const body = await response.json()
169
- t.equal(body.id, 'foo')
168
+ t.assert.strictEqual(body.id, 'foo')
170
169
  }
171
170
 
172
171
  {
173
172
  const response = await fastify.inject({ method: 'GET', url: '/two' })
174
173
  const body = await response.json()
175
- t.equal(body.id, 'foo')
174
+ t.assert.strictEqual(body.id, 'foo')
176
175
  }
177
176
 
178
177
  for await (const [line] of on(stream, 'data')) {
179
- t.match(line, matches.shift())
178
+ t.assert.ok(partialDeepStrictEqual(line, matches.shift()))
180
179
  if (matches.length === 0) break
181
180
  }
182
181
  })
183
182
 
184
- t.test('The request id log label can be changed', async (t) => {
183
+ await t.test('The request id log label can be changed', async (t) => {
185
184
  const REQUEST_ID = '42'
186
185
  const matches = [
187
- { traceId: REQUEST_ID, msg: /incoming request/ },
188
- { traceId: REQUEST_ID, msg: /some log message/ },
189
- { traceId: REQUEST_ID, msg: /request completed/ }
186
+ { traceId: REQUEST_ID, msg: 'incoming request' },
187
+ { traceId: REQUEST_ID, msg: 'some log message' },
188
+ { traceId: REQUEST_ID, msg: 'request completed' }
190
189
  ]
191
190
  t.plan(matches.length + 2)
192
191
 
@@ -196,10 +195,10 @@ t.test('request', (t) => {
196
195
  requestIdHeader: 'my-custom-request-id',
197
196
  requestIdLogLabel: 'traceId'
198
197
  })
199
- t.teardown(fastify.close.bind(fastify))
198
+ t.after(() => fastify.close())
200
199
 
201
200
  fastify.get('/one', (req, reply) => {
202
- t.equal(req.id, REQUEST_ID)
201
+ t.assert.strictEqual(req.id, REQUEST_ID)
203
202
  req.log.info('some log message')
204
203
  reply.send({ id: req.id })
205
204
  })
@@ -207,22 +206,16 @@ t.test('request', (t) => {
207
206
  {
208
207
  const response = await fastify.inject({ method: 'GET', url: '/one', headers: { 'my-custom-request-id': REQUEST_ID } })
209
208
  const body = await response.json()
210
- t.equal(body.id, REQUEST_ID)
209
+ t.assert.strictEqual(body.id, REQUEST_ID)
211
210
  }
212
211
 
213
212
  for await (const [line] of on(stream, 'data')) {
214
- t.match(line, matches.shift())
213
+ t.assert.ok(partialDeepStrictEqual(line, matches.shift()))
215
214
  if (matches.length === 0) break
216
215
  }
217
216
  })
218
217
 
219
- t.test('should redact the authorization header if so specified', async (t) => {
220
- const lines = [
221
- { msg: /Server listening at/ },
222
- { req: { headers: { authorization: '[Redacted]' } }, msg: 'incoming request' },
223
- { res: { statusCode: 200 }, msg: 'request completed' }
224
- ]
225
- t.plan(lines.length + 3)
218
+ await t.test('should redact the authorization header if so specified', async (t) => {
226
219
  const stream = split(JSON.parse)
227
220
  const fastify = Fastify({
228
221
  logger: {
@@ -243,15 +236,22 @@ t.test('request', (t) => {
243
236
  }
244
237
  }
245
238
  })
246
- t.teardown(fastify.close.bind(fastify))
239
+ t.after(() => fastify.close())
247
240
 
248
241
  fastify.get('/', function (req, reply) {
249
- t.same(req.headers.authorization, 'Bearer abcde')
242
+ t.assert.deepStrictEqual(req.headers.authorization, 'Bearer abcde')
250
243
  reply.send({ hello: 'world' })
251
244
  })
252
245
 
253
246
  await fastify.ready()
254
- await fastify.listen({ port: 0, host: localhost })
247
+ const server = await fastify.listen({ port: 0, host: localhost })
248
+
249
+ const lines = [
250
+ { msg: `Server listening at ${server}` },
251
+ { req: { headers: { authorization: '[Redacted]' } }, msg: 'incoming request' },
252
+ { res: { statusCode: 200 }, msg: 'request completed' }
253
+ ]
254
+ t.plan(lines.length + 3)
255
255
 
256
256
  await request({
257
257
  method: 'GET',
@@ -262,17 +262,17 @@ t.test('request', (t) => {
262
262
  authorization: 'Bearer abcde'
263
263
  }
264
264
  }, function (response, body) {
265
- t.equal(response.statusCode, 200)
266
- t.same(body, JSON.stringify({ hello: 'world' }))
265
+ t.assert.strictEqual(response.statusCode, 200)
266
+ t.assert.deepStrictEqual(body, JSON.stringify({ hello: 'world' }))
267
267
  })
268
268
 
269
269
  for await (const [line] of on(stream, 'data')) {
270
- t.match(line, lines.shift())
270
+ t.assert.ok(partialDeepStrictEqual(line, lines.shift()))
271
271
  if (lines.length === 0) break
272
272
  }
273
273
  })
274
274
 
275
- t.test('should not throw error when serializing custom req', (t) => {
275
+ await t.test('should not throw error when serializing custom req', (t) => {
276
276
  t.plan(1)
277
277
 
278
278
  const lines = []
@@ -283,10 +283,10 @@ t.test('request', (t) => {
283
283
  }
284
284
  })
285
285
  const fastify = Fastify({ logger: { level: 'info', stream: dest } })
286
- t.teardown(fastify.close.bind(fastify))
286
+ t.after(() => fastify.close())
287
287
 
288
288
  fastify.log.info({ req: {} })
289
289
 
290
- t.same(lines[0].req, {})
290
+ t.assert.deepStrictEqual(lines[0].req, {})
291
291
  })
292
292
  })
@@ -2,6 +2,7 @@
2
2
 
3
3
  const { test } = require('tap')
4
4
  const Fastify = require('..')
5
+ const { request } = require('undici')
5
6
 
6
7
  const AJV = require('ajv')
7
8
  const Schema = require('fluent-json-schema')
@@ -1300,3 +1301,138 @@ test('Custom validator builder override by custom validator compiler in child in
1300
1301
  })
1301
1302
  t.equal(two.statusCode, 200)
1302
1303
  })
1304
+
1305
+ test('Schema validation when no content type is provided', async t => {
1306
+ // this case should not be happened in normal use-case,
1307
+ // it is added for the completeness of code branch
1308
+ const fastify = Fastify()
1309
+
1310
+ fastify.post('/', {
1311
+ schema: {
1312
+ body: {
1313
+ content: {
1314
+ 'application/json': {
1315
+ schema: {
1316
+ type: 'object',
1317
+ properties: {
1318
+ foo: { type: 'string' }
1319
+ },
1320
+ required: ['foo'],
1321
+ additionalProperties: false
1322
+ }
1323
+ }
1324
+ }
1325
+ }
1326
+ },
1327
+ preValidation: async (request) => {
1328
+ request.headers['content-type'] = undefined
1329
+ }
1330
+ }, async () => 'ok')
1331
+
1332
+ await fastify.ready()
1333
+
1334
+ const invalid = await fastify.inject({
1335
+ method: 'POST',
1336
+ url: '/',
1337
+ headers: {
1338
+ 'content-type': 'application/json'
1339
+ },
1340
+ body: { invalid: 'string' }
1341
+ })
1342
+ t.equal(invalid.statusCode, 200)
1343
+ })
1344
+
1345
+ test('Schema validation will not be bypass by different content type', async t => {
1346
+ t.plan(10)
1347
+
1348
+ const fastify = Fastify()
1349
+
1350
+ fastify.post('/', {
1351
+ schema: {
1352
+ body: {
1353
+ content: {
1354
+ 'application/json': {
1355
+ schema: {
1356
+ type: 'object',
1357
+ properties: {
1358
+ foo: { type: 'string' }
1359
+ },
1360
+ required: ['foo'],
1361
+ additionalProperties: false
1362
+ }
1363
+ }
1364
+ }
1365
+ }
1366
+ }
1367
+ }, async () => 'ok')
1368
+
1369
+ await fastify.listen({ port: 0 })
1370
+ t.teardown(() => fastify.close())
1371
+ const address = fastify.listeningOrigin
1372
+
1373
+ const correct1 = await request(address, {
1374
+ method: 'POST',
1375
+ url: '/',
1376
+ headers: {
1377
+ 'content-type': 'application/json'
1378
+ },
1379
+ body: JSON.stringify({ foo: 'string' })
1380
+ })
1381
+ t.equal(correct1.statusCode, 200)
1382
+ await correct1.body.dump()
1383
+
1384
+ const correct2 = await request(address, {
1385
+ method: 'POST',
1386
+ url: '/',
1387
+ headers: {
1388
+ 'content-type': 'application/json; charset=utf-8'
1389
+ },
1390
+ body: JSON.stringify({ foo: 'string' })
1391
+ })
1392
+ t.equal(correct2.statusCode, 200)
1393
+ await correct2.body.dump()
1394
+
1395
+ const invalid1 = await request(address, {
1396
+ method: 'POST',
1397
+ url: '/',
1398
+ headers: {
1399
+ 'content-type': 'application/json ;'
1400
+ },
1401
+ body: JSON.stringify({ invalid: 'string' })
1402
+ })
1403
+ t.equal(invalid1.statusCode, 400)
1404
+ t.equal((await invalid1.body.json()).code, 'FST_ERR_VALIDATION')
1405
+
1406
+ const invalid2 = await request(address, {
1407
+ method: 'POST',
1408
+ url: '/',
1409
+ headers: {
1410
+ 'content-type': 'ApPlIcAtIoN/JsOn;'
1411
+ },
1412
+ body: JSON.stringify({ invalid: 'string' })
1413
+ })
1414
+ t.equal(invalid2.statusCode, 400)
1415
+ t.equal((await invalid2.body.json()).code, 'FST_ERR_VALIDATION')
1416
+
1417
+ const invalid3 = await request(address, {
1418
+ method: 'POST',
1419
+ url: '/',
1420
+ headers: {
1421
+ 'content-type': 'ApPlIcAtIoN/JsOn ;'
1422
+ },
1423
+ body: JSON.stringify({ invalid: 'string' })
1424
+ })
1425
+ t.equal(invalid3.statusCode, 400)
1426
+ t.equal((await invalid3.body.json()).code, 'FST_ERR_VALIDATION')
1427
+
1428
+ const invalid4 = await request(address, {
1429
+ method: 'POST',
1430
+ url: '/',
1431
+ headers: {
1432
+ 'content-type': 'ApPlIcAtIoN/JsOn foo;'
1433
+ },
1434
+ body: JSON.stringify({ invalid: 'string' })
1435
+ })
1436
+ t.equal(invalid4.statusCode, 400)
1437
+ t.equal((await invalid4.body.json()).code, 'FST_ERR_VALIDATION')
1438
+ })
@@ -1,7 +1,6 @@
1
1
  'use strict'
2
2
 
3
- const t = require('tap')
4
- const test = t.test
3
+ const { test } = require('node:test')
5
4
  const sget = require('simple-get').concat
6
5
  const errors = require('http-errors')
7
6
  const JSONStream = require('JSONStream')
@@ -10,7 +9,7 @@ const split = require('split2')
10
9
  const Fastify = require('..')
11
10
  const { kDisableRequestLogging } = require('../lib/symbols.js')
12
11
 
13
- test('Destroying streams prematurely should call abort method', t => {
12
+ test('Destroying streams prematurely should call abort method', (t, testDone) => {
14
13
  t.plan(7)
15
14
 
16
15
  let fastify = null
@@ -23,7 +22,7 @@ test('Destroying streams prematurely should call abort method', t => {
23
22
  }
24
23
  })
25
24
  } catch (e) {
26
- t.fail()
25
+ t.assert.fail()
27
26
  }
28
27
  const stream = require('node:stream')
29
28
  const http = require('node:http')
@@ -31,13 +30,14 @@ test('Destroying streams prematurely should call abort method', t => {
31
30
  // Test that "premature close" errors are logged with level warn
32
31
  logStream.on('data', line => {
33
32
  if (line.res) {
34
- t.equal(line.msg, 'stream closed prematurely')
35
- t.equal(line.level, 30)
33
+ t.assert.strictEqual(line.msg, 'stream closed prematurely')
34
+ t.assert.strictEqual(line.level, 30)
35
+ testDone()
36
36
  }
37
37
  })
38
38
 
39
39
  fastify.get('/', function (request, reply) {
40
- t.pass('Received request')
40
+ t.assert.ok('Received request')
41
41
 
42
42
  let sent = false
43
43
  const reallyLongStream = new stream.Readable({
@@ -50,30 +50,30 @@ test('Destroying streams prematurely should call abort method', t => {
50
50
  })
51
51
  reallyLongStream.destroy = undefined
52
52
  reallyLongStream.close = undefined
53
- reallyLongStream.abort = () => t.ok('called')
53
+ reallyLongStream.abort = () => t.assert.ok('called')
54
54
  reply.send(reallyLongStream)
55
55
  })
56
56
 
57
57
  fastify.listen({ port: 0 }, err => {
58
- t.error(err)
59
- t.teardown(() => { fastify.close() })
58
+ t.assert.ifError(err)
59
+ t.after(() => { fastify.close() })
60
60
 
61
61
  const port = fastify.server.address().port
62
62
 
63
63
  http.get(`http://localhost:${port}`, function (response) {
64
- t.equal(response.statusCode, 200)
64
+ t.assert.strictEqual(response.statusCode, 200)
65
65
  response.on('readable', function () {
66
66
  response.destroy()
67
67
  })
68
68
  // Node bug? Node never emits 'close' here.
69
69
  response.on('aborted', function () {
70
- t.pass('Response closed')
70
+ t.assert.ok('Response closed')
71
71
  })
72
72
  })
73
73
  })
74
74
  })
75
75
 
76
- test('Destroying streams prematurely, log is disabled', t => {
76
+ test('Destroying streams prematurely, log is disabled', (t, testDone) => {
77
77
  t.plan(4)
78
78
 
79
79
  let fastify = null
@@ -82,7 +82,7 @@ test('Destroying streams prematurely, log is disabled', t => {
82
82
  logger: false
83
83
  })
84
84
  } catch (e) {
85
- t.fail()
85
+ t.assert.fail()
86
86
  }
87
87
  const stream = require('node:stream')
88
88
  const http = require('node:http')
@@ -100,30 +100,33 @@ test('Destroying streams prematurely, log is disabled', t => {
100
100
  }
101
101
  })
102
102
  reallyLongStream.destroy = true
103
- reallyLongStream.close = () => t.ok('called')
103
+ reallyLongStream.close = () => {
104
+ t.assert.ok('called')
105
+ testDone()
106
+ }
104
107
  reply.send(reallyLongStream)
105
108
  })
106
109
 
107
110
  fastify.listen({ port: 0 }, err => {
108
- t.error(err)
109
- t.teardown(() => { fastify.close() })
111
+ t.assert.ifError(err)
112
+ t.after(() => { fastify.close() })
110
113
 
111
114
  const port = fastify.server.address().port
112
115
 
113
116
  http.get(`http://localhost:${port}`, function (response) {
114
- t.equal(response.statusCode, 200)
117
+ t.assert.strictEqual(response.statusCode, 200)
115
118
  response.on('readable', function () {
116
119
  response.destroy()
117
120
  })
118
121
  // Node bug? Node never emits 'close' here.
119
122
  response.on('aborted', function () {
120
- t.pass('Response closed')
123
+ t.assert.ok('Response closed')
121
124
  })
122
125
  })
123
126
  })
124
127
  })
125
128
 
126
- test('should respond with a stream1', t => {
129
+ test('should respond with a stream1', (t, testDone) => {
127
130
  t.plan(5)
128
131
  const fastify = Fastify()
129
132
 
@@ -135,25 +138,26 @@ test('should respond with a stream1', t => {
135
138
  })
136
139
 
137
140
  fastify.listen({ port: 0 }, err => {
138
- t.error(err)
139
- t.teardown(() => { fastify.close() })
141
+ t.assert.ifError(err)
142
+ t.after(() => { fastify.close() })
140
143
 
141
144
  sget(`http://localhost:${fastify.server.address().port}`, function (err, response, body) {
142
- t.error(err)
143
- t.equal(response.headers['content-type'], 'application/json')
144
- t.equal(response.statusCode, 200)
145
- t.same(JSON.parse(body), [{ hello: 'world' }, { a: 42 }])
145
+ t.assert.ifError(err)
146
+ t.assert.strictEqual(response.headers['content-type'], 'application/json')
147
+ t.assert.strictEqual(response.statusCode, 200)
148
+ t.assert.deepStrictEqual(JSON.parse(body), [{ hello: 'world' }, { a: 42 }])
149
+ testDone()
146
150
  })
147
151
  })
148
152
  })
149
153
 
150
- test('return a 404 if the stream emits a 404 error', t => {
154
+ test('return a 404 if the stream emits a 404 error', (t, testDone) => {
151
155
  t.plan(5)
152
156
 
153
157
  const fastify = Fastify()
154
158
 
155
159
  fastify.get('/', function (request, reply) {
156
- t.pass('Received request')
160
+ t.assert.ok('Received request')
157
161
 
158
162
  const reallyLongStream = new Readable({
159
163
  read: function () {
@@ -167,15 +171,16 @@ test('return a 404 if the stream emits a 404 error', t => {
167
171
  })
168
172
 
169
173
  fastify.listen({ port: 0 }, err => {
170
- t.error(err)
171
- t.teardown(() => { fastify.close() })
174
+ t.assert.ifError(err)
175
+ t.after(() => { fastify.close() })
172
176
 
173
177
  const port = fastify.server.address().port
174
178
 
175
179
  sget(`http://localhost:${port}`, function (err, response) {
176
- t.error(err)
177
- t.equal(response.headers['content-type'], 'application/json; charset=utf-8')
178
- t.equal(response.statusCode, 404)
180
+ t.assert.ifError(err)
181
+ t.assert.strictEqual(response.headers['content-type'], 'application/json; charset=utf-8')
182
+ t.assert.strictEqual(response.statusCode, 404)
183
+ testDone()
179
184
  })
180
185
  })
181
186
  })
package/test/toolkit.js CHANGED
@@ -30,3 +30,34 @@ exports.waitForCb = function (options) {
30
30
 
31
31
  return { stepIn, patience }
32
32
  }
33
+
34
+ exports.partialDeepStrictEqual = function partialDeepStrictEqual (actual, expected) {
35
+ if (typeof expected !== 'object' || expected === null) {
36
+ return actual === expected
37
+ }
38
+
39
+ if (typeof actual !== 'object' || actual === null) {
40
+ return false
41
+ }
42
+
43
+ if (Array.isArray(expected)) {
44
+ if (!Array.isArray(actual)) return false
45
+ if (expected.length > actual.length) return false
46
+
47
+ for (let i = 0; i < expected.length; i++) {
48
+ if (!partialDeepStrictEqual(actual[i], expected[i])) {
49
+ return false
50
+ }
51
+ }
52
+ return true
53
+ }
54
+
55
+ for (const key of Object.keys(expected)) {
56
+ if (!(key in actual)) return false
57
+ if (!partialDeepStrictEqual(actual[key], expected[key])) {
58
+ return false
59
+ }
60
+ }
61
+
62
+ return true
63
+ }