fastify 5.3.3 → 5.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.vscode/settings.json +15 -15
- package/LICENSE +1 -1
- package/README.md +2 -0
- package/SECURITY.md +158 -2
- package/build/build-validation.js +20 -1
- package/docs/Guides/Delay-Accepting-Requests.md +8 -5
- package/docs/Guides/Ecosystem.md +20 -5
- package/docs/Guides/Migration-Guide-V5.md +6 -10
- package/docs/Guides/Recommendations.md +1 -1
- package/docs/Reference/ContentTypeParser.md +1 -1
- package/docs/Reference/Errors.md +5 -3
- package/docs/Reference/Hooks.md +16 -20
- package/docs/Reference/Lifecycle.md +2 -2
- package/docs/Reference/Logging.md +3 -3
- package/docs/Reference/Middleware.md +1 -1
- package/docs/Reference/Reply.md +8 -8
- package/docs/Reference/Request.md +2 -2
- package/docs/Reference/Routes.md +7 -6
- package/docs/Reference/Server.md +341 -200
- package/docs/Reference/TypeScript.md +1 -3
- package/docs/Reference/Validation-and-Serialization.md +56 -4
- package/docs/Reference/Warnings.md +2 -1
- package/fastify.d.ts +4 -3
- package/fastify.js +47 -34
- package/lib/configValidator.js +196 -28
- package/lib/contentTypeParser.js +41 -48
- package/lib/error-handler.js +3 -3
- package/lib/errors.js +11 -0
- package/lib/handleRequest.js +13 -17
- package/lib/pluginOverride.js +3 -1
- package/lib/promise.js +23 -0
- package/lib/reply.js +24 -30
- package/lib/request.js +3 -10
- package/lib/route.js +37 -3
- package/lib/server.js +36 -35
- package/lib/symbols.js +1 -0
- package/lib/warnings.js +19 -1
- package/package.json +14 -10
- package/test/404s.test.js +226 -325
- package/test/allow-unsafe-regex.test.js +19 -48
- package/test/als.test.js +28 -40
- package/test/async-await.test.js +84 -128
- package/test/async_hooks.test.js +18 -37
- package/test/body-limit.test.js +90 -63
- package/test/buffer.test.js +22 -0
- package/test/build-certificate.js +1 -1
- package/test/case-insensitive.test.js +44 -65
- package/test/check.test.js +17 -21
- package/test/close-pipelining.test.js +24 -15
- package/test/constrained-routes.test.js +231 -0
- package/test/custom-http-server.test.js +7 -15
- package/test/custom-parser-async.test.js +17 -22
- package/test/custom-parser.0.test.js +267 -348
- package/test/custom-parser.1.test.js +141 -191
- package/test/custom-parser.2.test.js +34 -44
- package/test/custom-parser.3.test.js +56 -104
- package/test/custom-parser.4.test.js +106 -144
- package/test/custom-parser.5.test.js +56 -75
- package/test/custom-querystring-parser.test.js +51 -77
- package/test/decorator-namespace.test._js_ +3 -4
- package/test/decorator.test.js +76 -259
- package/test/delete.test.js +101 -110
- package/test/diagnostics-channel/404.test.js +7 -15
- package/test/diagnostics-channel/async-delay-request.test.js +7 -16
- package/test/diagnostics-channel/async-request.test.js +8 -16
- package/test/diagnostics-channel/error-request.test.js +7 -15
- package/test/diagnostics-channel/sync-delay-request.test.js +7 -16
- package/test/diagnostics-channel/sync-request-reply.test.js +9 -16
- package/test/diagnostics-channel/sync-request.test.js +9 -16
- package/test/fastify-instance.test.js +1 -1
- package/test/header-overflow.test.js +18 -29
- package/test/helper.js +139 -135
- package/test/hooks-async.test.js +259 -235
- package/test/hooks.test.js +951 -996
- package/test/http-methods/copy.test.js +14 -19
- package/test/http-methods/get.test.js +131 -143
- package/test/http-methods/head.test.js +53 -84
- package/test/http-methods/lock.test.js +31 -31
- package/test/http-methods/mkcalendar.test.js +45 -72
- package/test/http-methods/mkcol.test.js +5 -9
- package/test/http-methods/move.test.js +6 -10
- package/test/http-methods/propfind.test.js +34 -44
- package/test/http-methods/proppatch.test.js +23 -29
- package/test/http-methods/report.test.js +44 -69
- package/test/http-methods/search.test.js +67 -82
- package/test/http-methods/unlock.test.js +5 -9
- package/test/http2/closing.test.js +38 -20
- package/test/http2/secure-with-fallback.test.js +31 -28
- package/test/https/custom-https-server.test.js +9 -13
- package/test/https/https.test.js +56 -53
- package/test/input-validation.js +139 -150
- package/test/internals/errors.test.js +50 -1
- package/test/internals/handle-request.test.js +72 -65
- package/test/internals/promise.test.js +63 -0
- package/test/internals/reply.test.js +277 -496
- package/test/issue-4959.test.js +12 -3
- package/test/listen.4.test.js +31 -43
- package/test/nullable-validation.test.js +33 -46
- package/test/output-validation.test.js +24 -26
- package/test/plugin.1.test.js +40 -68
- package/test/plugin.2.test.js +108 -120
- package/test/plugin.3.test.js +50 -72
- package/test/plugin.4.test.js +124 -119
- package/test/promises.test.js +42 -63
- package/test/proto-poisoning.test.js +78 -97
- package/test/register.test.js +8 -18
- package/test/request-error.test.js +57 -146
- package/test/request-id.test.js +30 -49
- package/test/route-hooks.test.js +117 -101
- package/test/route-prefix.test.js +194 -133
- package/test/route-shorthand.test.js +9 -27
- package/test/route.1.test.js +74 -131
- package/test/route.8.test.js +9 -17
- package/test/router-options.test.js +450 -0
- package/test/schema-serialization.test.js +177 -154
- package/test/schema-special-usage.test.js +165 -132
- package/test/schema-validation.test.js +254 -218
- package/test/server.test.js +143 -5
- package/test/set-error-handler.test.js +58 -1
- package/test/skip-reply-send.test.js +64 -69
- package/test/stream.1.test.js +33 -50
- package/test/stream.4.test.js +18 -28
- package/test/stream.5.test.js +11 -19
- package/test/trust-proxy.test.js +32 -58
- package/test/types/errors.test-d.ts +13 -1
- package/test/types/fastify.test-d.ts +3 -0
- package/test/types/request.test-d.ts +1 -0
- package/test/types/type-provider.test-d.ts +55 -0
- package/test/url-rewriting.test.js +45 -62
- package/test/use-semicolon-delimiter.test.js +117 -59
- package/test/versioned-routes.test.js +39 -56
- package/types/errors.d.ts +11 -1
- package/types/hooks.d.ts +1 -1
- package/types/instance.d.ts +1 -1
- package/types/reply.d.ts +2 -2
- package/types/request.d.ts +1 -0
- package/.taprc +0 -7
|
@@ -905,3 +905,234 @@ test('Allow regex constraints in routes', async t => {
|
|
|
905
905
|
t.assert.strictEqual(res.statusCode, 404)
|
|
906
906
|
}
|
|
907
907
|
})
|
|
908
|
+
|
|
909
|
+
test('Should allow registering custom rotuerOptions constrained routes', async t => {
|
|
910
|
+
t.plan(5)
|
|
911
|
+
|
|
912
|
+
const constraint = {
|
|
913
|
+
name: 'secret',
|
|
914
|
+
storage: function () {
|
|
915
|
+
const secrets = {}
|
|
916
|
+
return {
|
|
917
|
+
get: (secret) => { return secrets[secret] || null },
|
|
918
|
+
set: (secret, store) => { secrets[secret] = store }
|
|
919
|
+
}
|
|
920
|
+
},
|
|
921
|
+
deriveConstraint: (req, ctx) => {
|
|
922
|
+
return req.headers['x-secret']
|
|
923
|
+
},
|
|
924
|
+
validate () { return true }
|
|
925
|
+
}
|
|
926
|
+
|
|
927
|
+
const fastify = Fastify({ routerOptions: { constraints: { secret: constraint } } })
|
|
928
|
+
|
|
929
|
+
fastify.route({
|
|
930
|
+
method: 'GET',
|
|
931
|
+
url: '/',
|
|
932
|
+
constraints: { secret: 'alpha' },
|
|
933
|
+
handler: (req, reply) => {
|
|
934
|
+
reply.send({ hello: 'from alpha' })
|
|
935
|
+
}
|
|
936
|
+
})
|
|
937
|
+
|
|
938
|
+
fastify.route({
|
|
939
|
+
method: 'GET',
|
|
940
|
+
url: '/',
|
|
941
|
+
constraints: { secret: 'beta' },
|
|
942
|
+
handler: (req, reply) => {
|
|
943
|
+
reply.send({ hello: 'from beta' })
|
|
944
|
+
}
|
|
945
|
+
})
|
|
946
|
+
|
|
947
|
+
{
|
|
948
|
+
const res = await fastify.inject({
|
|
949
|
+
method: 'GET',
|
|
950
|
+
url: '/',
|
|
951
|
+
headers: {
|
|
952
|
+
'X-Secret': 'alpha'
|
|
953
|
+
}
|
|
954
|
+
})
|
|
955
|
+
t.assert.deepStrictEqual(JSON.parse(res.payload), { hello: 'from alpha' })
|
|
956
|
+
t.assert.strictEqual(res.statusCode, 200)
|
|
957
|
+
}
|
|
958
|
+
|
|
959
|
+
{
|
|
960
|
+
const res = await fastify.inject({
|
|
961
|
+
method: 'GET',
|
|
962
|
+
url: '/',
|
|
963
|
+
headers: {
|
|
964
|
+
'X-Secret': 'beta'
|
|
965
|
+
}
|
|
966
|
+
})
|
|
967
|
+
t.assert.deepStrictEqual(JSON.parse(res.payload), { hello: 'from beta' })
|
|
968
|
+
t.assert.strictEqual(res.statusCode, 200)
|
|
969
|
+
}
|
|
970
|
+
|
|
971
|
+
{
|
|
972
|
+
const res = await fastify.inject({
|
|
973
|
+
method: 'GET',
|
|
974
|
+
url: '/',
|
|
975
|
+
headers: {
|
|
976
|
+
'X-Secret': 'gamma'
|
|
977
|
+
}
|
|
978
|
+
})
|
|
979
|
+
t.assert.strictEqual(res.statusCode, 404)
|
|
980
|
+
}
|
|
981
|
+
})
|
|
982
|
+
|
|
983
|
+
test('Custom rotuerOptions constrained routes registered also for HEAD method generated by fastify', (t, done) => {
|
|
984
|
+
t.plan(3)
|
|
985
|
+
|
|
986
|
+
const constraint = {
|
|
987
|
+
name: 'secret',
|
|
988
|
+
storage: function () {
|
|
989
|
+
const secrets = {}
|
|
990
|
+
return {
|
|
991
|
+
get: (secret) => { return secrets[secret] || null },
|
|
992
|
+
set: (secret, store) => { secrets[secret] = store }
|
|
993
|
+
}
|
|
994
|
+
},
|
|
995
|
+
deriveConstraint: (req, ctx) => {
|
|
996
|
+
return req.headers['x-secret']
|
|
997
|
+
},
|
|
998
|
+
validate () { return true }
|
|
999
|
+
}
|
|
1000
|
+
|
|
1001
|
+
const fastify = Fastify({ routerOptions: { constraints: { secret: constraint } } })
|
|
1002
|
+
|
|
1003
|
+
fastify.route({
|
|
1004
|
+
method: 'GET',
|
|
1005
|
+
url: '/',
|
|
1006
|
+
constraints: { secret: 'mySecret' },
|
|
1007
|
+
handler: (req, reply) => {
|
|
1008
|
+
reply.send('from mySecret - my length is 31')
|
|
1009
|
+
}
|
|
1010
|
+
})
|
|
1011
|
+
|
|
1012
|
+
fastify.inject({
|
|
1013
|
+
method: 'HEAD',
|
|
1014
|
+
url: '/',
|
|
1015
|
+
headers: {
|
|
1016
|
+
'X-Secret': 'mySecret'
|
|
1017
|
+
}
|
|
1018
|
+
}, (err, res) => {
|
|
1019
|
+
t.assert.ifError(err)
|
|
1020
|
+
t.assert.deepStrictEqual(res.headers['content-length'], '31')
|
|
1021
|
+
t.assert.strictEqual(res.statusCode, 200)
|
|
1022
|
+
done()
|
|
1023
|
+
})
|
|
1024
|
+
})
|
|
1025
|
+
|
|
1026
|
+
test('allow async rotuerOptions constraints', async (t) => {
|
|
1027
|
+
t.plan(5)
|
|
1028
|
+
|
|
1029
|
+
const constraint = {
|
|
1030
|
+
name: 'secret',
|
|
1031
|
+
storage: function () {
|
|
1032
|
+
const secrets = {}
|
|
1033
|
+
return {
|
|
1034
|
+
get: (secret) => { return secrets[secret] || null },
|
|
1035
|
+
set: (secret, store) => { secrets[secret] = store }
|
|
1036
|
+
}
|
|
1037
|
+
},
|
|
1038
|
+
deriveConstraint: (req, ctx, done) => {
|
|
1039
|
+
done(null, req.headers['x-secret'])
|
|
1040
|
+
},
|
|
1041
|
+
validate () { return true }
|
|
1042
|
+
}
|
|
1043
|
+
|
|
1044
|
+
const fastify = Fastify({ routerOptions: { constraints: { secret: constraint } } })
|
|
1045
|
+
|
|
1046
|
+
fastify.route({
|
|
1047
|
+
method: 'GET',
|
|
1048
|
+
url: '/',
|
|
1049
|
+
constraints: { secret: 'alpha' },
|
|
1050
|
+
handler: (req, reply) => {
|
|
1051
|
+
reply.send({ hello: 'from alpha' })
|
|
1052
|
+
}
|
|
1053
|
+
})
|
|
1054
|
+
|
|
1055
|
+
fastify.route({
|
|
1056
|
+
method: 'GET',
|
|
1057
|
+
url: '/',
|
|
1058
|
+
constraints: { secret: 'beta' },
|
|
1059
|
+
handler: (req, reply) => {
|
|
1060
|
+
reply.send({ hello: 'from beta' })
|
|
1061
|
+
}
|
|
1062
|
+
})
|
|
1063
|
+
|
|
1064
|
+
{
|
|
1065
|
+
const { statusCode, payload } = await fastify.inject({ method: 'GET', path: '/', headers: { 'X-Secret': 'alpha' } })
|
|
1066
|
+
t.assert.deepStrictEqual(JSON.parse(payload), { hello: 'from alpha' })
|
|
1067
|
+
t.assert.strictEqual(statusCode, 200)
|
|
1068
|
+
}
|
|
1069
|
+
{
|
|
1070
|
+
const { statusCode, payload } = await fastify.inject({ method: 'GET', path: '/', headers: { 'X-Secret': 'beta' } })
|
|
1071
|
+
t.assert.deepStrictEqual(JSON.parse(payload), { hello: 'from beta' })
|
|
1072
|
+
t.assert.strictEqual(statusCode, 200)
|
|
1073
|
+
}
|
|
1074
|
+
{
|
|
1075
|
+
const { statusCode } = await fastify.inject({ method: 'GET', path: '/', headers: { 'X-Secret': 'gamma' } })
|
|
1076
|
+
t.assert.strictEqual(statusCode, 404)
|
|
1077
|
+
}
|
|
1078
|
+
})
|
|
1079
|
+
|
|
1080
|
+
test('error in async rotuerOptions constraints', async (t) => {
|
|
1081
|
+
t.plan(8)
|
|
1082
|
+
|
|
1083
|
+
const constraint = {
|
|
1084
|
+
name: 'secret',
|
|
1085
|
+
storage: function () {
|
|
1086
|
+
const secrets = {}
|
|
1087
|
+
return {
|
|
1088
|
+
get: (secret) => { return secrets[secret] || null },
|
|
1089
|
+
set: (secret, store) => { secrets[secret] = store }
|
|
1090
|
+
}
|
|
1091
|
+
},
|
|
1092
|
+
deriveConstraint: (req, ctx, done) => {
|
|
1093
|
+
done(Error('kaboom'))
|
|
1094
|
+
},
|
|
1095
|
+
validate () { return true }
|
|
1096
|
+
}
|
|
1097
|
+
|
|
1098
|
+
const fastify = Fastify({ routerOptions: { constraints: { secret: constraint } } })
|
|
1099
|
+
|
|
1100
|
+
fastify.route({
|
|
1101
|
+
method: 'GET',
|
|
1102
|
+
url: '/',
|
|
1103
|
+
constraints: { secret: 'alpha' },
|
|
1104
|
+
handler: (req, reply) => {
|
|
1105
|
+
reply.send({ hello: 'from alpha' })
|
|
1106
|
+
}
|
|
1107
|
+
})
|
|
1108
|
+
|
|
1109
|
+
fastify.route({
|
|
1110
|
+
method: 'GET',
|
|
1111
|
+
url: '/',
|
|
1112
|
+
constraints: { secret: 'beta' },
|
|
1113
|
+
handler: (req, reply) => {
|
|
1114
|
+
reply.send({ hello: 'from beta' })
|
|
1115
|
+
}
|
|
1116
|
+
})
|
|
1117
|
+
|
|
1118
|
+
{
|
|
1119
|
+
const { statusCode, payload } = await fastify.inject({ method: 'GET', path: '/', headers: { 'X-Secret': 'alpha' } })
|
|
1120
|
+
t.assert.deepStrictEqual(JSON.parse(payload), { error: 'Internal Server Error', message: 'Unexpected error from async constraint', statusCode: 500 })
|
|
1121
|
+
t.assert.strictEqual(statusCode, 500)
|
|
1122
|
+
}
|
|
1123
|
+
{
|
|
1124
|
+
const { statusCode, payload } = await fastify.inject({ method: 'GET', path: '/', headers: { 'X-Secret': 'beta' } })
|
|
1125
|
+
t.assert.deepStrictEqual(JSON.parse(payload), { error: 'Internal Server Error', message: 'Unexpected error from async constraint', statusCode: 500 })
|
|
1126
|
+
t.assert.strictEqual(statusCode, 500)
|
|
1127
|
+
}
|
|
1128
|
+
{
|
|
1129
|
+
const { statusCode, payload } = await fastify.inject({ method: 'GET', path: '/', headers: { 'X-Secret': 'gamma' } })
|
|
1130
|
+
t.assert.deepStrictEqual(JSON.parse(payload), { error: 'Internal Server Error', message: 'Unexpected error from async constraint', statusCode: 500 })
|
|
1131
|
+
t.assert.strictEqual(statusCode, 500)
|
|
1132
|
+
}
|
|
1133
|
+
{
|
|
1134
|
+
const { statusCode, payload } = await fastify.inject({ method: 'GET', path: '/' })
|
|
1135
|
+
t.assert.deepStrictEqual(JSON.parse(payload), { error: 'Internal Server Error', message: 'Unexpected error from async constraint', statusCode: 500 })
|
|
1136
|
+
t.assert.strictEqual(statusCode, 500)
|
|
1137
|
+
}
|
|
1138
|
+
})
|
|
@@ -3,7 +3,6 @@
|
|
|
3
3
|
const { test } = require('node:test')
|
|
4
4
|
const http = require('node:http')
|
|
5
5
|
const dns = require('node:dns').promises
|
|
6
|
-
const sget = require('simple-get').concat
|
|
7
6
|
const Fastify = require('..')
|
|
8
7
|
const { FST_ERR_FORCE_CLOSE_CONNECTIONS_IDLE_NOT_AVAILABLE } = require('../lib/errors')
|
|
9
8
|
|
|
@@ -11,7 +10,7 @@ async function setup () {
|
|
|
11
10
|
const localAddresses = await dns.lookup('localhost', { all: true })
|
|
12
11
|
|
|
13
12
|
test('Should support a custom http server', { skip: localAddresses.length < 1 }, async t => {
|
|
14
|
-
t.plan(
|
|
13
|
+
t.plan(5)
|
|
15
14
|
|
|
16
15
|
const fastify = Fastify({
|
|
17
16
|
serverFactory: (handler, opts) => {
|
|
@@ -34,20 +33,13 @@ async function setup () {
|
|
|
34
33
|
|
|
35
34
|
await fastify.listen({ port: 0 })
|
|
36
35
|
|
|
37
|
-
await
|
|
38
|
-
|
|
39
|
-
method: 'GET',
|
|
40
|
-
url: 'http://localhost:' + fastify.server.address().port,
|
|
41
|
-
rejectUnauthorized: false
|
|
42
|
-
}, (err, response, body) => {
|
|
43
|
-
if (err) {
|
|
44
|
-
return reject(err)
|
|
45
|
-
}
|
|
46
|
-
t.assert.strictEqual(response.statusCode, 200)
|
|
47
|
-
t.assert.deepStrictEqual(JSON.parse(body), { hello: 'world' })
|
|
48
|
-
resolve()
|
|
49
|
-
})
|
|
36
|
+
const response = await fetch('http://localhost:' + fastify.server.address().port, {
|
|
37
|
+
method: 'GET'
|
|
50
38
|
})
|
|
39
|
+
t.assert.ok(response.ok)
|
|
40
|
+
t.assert.strictEqual(response.status, 200)
|
|
41
|
+
const body = await response.text()
|
|
42
|
+
t.assert.deepStrictEqual(JSON.parse(body), { hello: 'world' })
|
|
51
43
|
})
|
|
52
44
|
|
|
53
45
|
test('Should not allow forceCloseConnection=idle if the server does not support closeIdleConnections', t => {
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
3
|
const { test } = require('node:test')
|
|
4
|
-
const sget = require('simple-get').concat
|
|
5
4
|
const Fastify = require('../fastify')
|
|
6
5
|
|
|
7
6
|
process.removeAllListeners('warning')
|
|
@@ -24,41 +23,37 @@ test('contentTypeParser should add a custom async parser', async t => {
|
|
|
24
23
|
})
|
|
25
24
|
|
|
26
25
|
t.after(() => fastify.close())
|
|
27
|
-
await fastify.listen({ port: 0 })
|
|
26
|
+
const fastifyServer = await fastify.listen({ port: 0 })
|
|
28
27
|
|
|
29
|
-
await t.test('in POST',
|
|
28
|
+
await t.test('in POST', async t => {
|
|
30
29
|
t.plan(3)
|
|
31
30
|
|
|
32
|
-
|
|
31
|
+
const result = await fetch(fastifyServer, {
|
|
33
32
|
method: 'POST',
|
|
34
|
-
url: 'http://localhost:' + fastify.server.address().port,
|
|
35
|
-
body: '{"hello":"world"}',
|
|
36
33
|
headers: {
|
|
37
34
|
'Content-Type': 'application/jsoff'
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
t.assert.ifError(err)
|
|
41
|
-
t.assert.strictEqual(response.statusCode, 200)
|
|
42
|
-
t.assert.deepStrictEqual(body.toString(), JSON.stringify({ hello: 'world' }))
|
|
43
|
-
done()
|
|
35
|
+
},
|
|
36
|
+
body: '{"hello":"world"}'
|
|
44
37
|
})
|
|
38
|
+
|
|
39
|
+
t.assert.ok(result.ok)
|
|
40
|
+
t.assert.strictEqual(result.status, 200)
|
|
41
|
+
t.assert.deepStrictEqual(await result.json(), { hello: 'world' })
|
|
45
42
|
})
|
|
46
43
|
|
|
47
|
-
await t.test('in OPTIONS',
|
|
44
|
+
await t.test('in OPTIONS', async t => {
|
|
48
45
|
t.plan(3)
|
|
49
46
|
|
|
50
|
-
|
|
47
|
+
const result = await fetch(fastifyServer, {
|
|
51
48
|
method: 'OPTIONS',
|
|
52
|
-
url: 'http://localhost:' + fastify.server.address().port,
|
|
53
|
-
body: '{"hello":"world"}',
|
|
54
49
|
headers: {
|
|
55
50
|
'Content-Type': 'application/jsoff'
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
t.assert.ifError(err)
|
|
59
|
-
t.assert.strictEqual(response.statusCode, 200)
|
|
60
|
-
t.assert.deepStrictEqual(body.toString(), JSON.stringify({ hello: 'world' }))
|
|
61
|
-
done()
|
|
51
|
+
},
|
|
52
|
+
body: '{"hello":"world"}'
|
|
62
53
|
})
|
|
54
|
+
|
|
55
|
+
t.assert.ok(result.ok)
|
|
56
|
+
t.assert.strictEqual(result.status, 200)
|
|
57
|
+
t.assert.deepStrictEqual(await result.json(), { hello: 'world' })
|
|
63
58
|
})
|
|
64
59
|
})
|