fastify 5.4.0 → 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.
Files changed (97) hide show
  1. package/.vscode/settings.json +22 -0
  2. package/LICENSE +1 -1
  3. package/SECURITY.md +158 -2
  4. package/build/build-validation.js +19 -1
  5. package/docs/Guides/Delay-Accepting-Requests.md +8 -5
  6. package/docs/Guides/Ecosystem.md +11 -0
  7. package/docs/Guides/Migration-Guide-V5.md +6 -10
  8. package/docs/Guides/Recommendations.md +1 -1
  9. package/docs/Reference/Errors.md +3 -1
  10. package/docs/Reference/Hooks.md +2 -6
  11. package/docs/Reference/Lifecycle.md +2 -2
  12. package/docs/Reference/Request.md +1 -1
  13. package/docs/Reference/Routes.md +4 -3
  14. package/docs/Reference/Server.md +306 -179
  15. package/docs/Reference/TypeScript.md +1 -3
  16. package/docs/Reference/Validation-and-Serialization.md +55 -3
  17. package/docs/Reference/Warnings.md +2 -1
  18. package/fastify.d.ts +2 -2
  19. package/fastify.js +34 -33
  20. package/lib/configValidator.js +196 -28
  21. package/lib/contentTypeParser.js +41 -48
  22. package/lib/error-handler.js +3 -3
  23. package/lib/errors.js +5 -0
  24. package/lib/handleRequest.js +13 -17
  25. package/lib/promise.js +23 -0
  26. package/lib/reply.js +17 -19
  27. package/lib/route.js +37 -3
  28. package/lib/server.js +36 -35
  29. package/lib/warnings.js +11 -1
  30. package/package.json +7 -7
  31. package/test/async-await.test.js +81 -134
  32. package/test/async_hooks.test.js +18 -37
  33. package/test/body-limit.test.js +51 -0
  34. package/test/buffer.test.js +22 -0
  35. package/test/case-insensitive.test.js +44 -65
  36. package/test/check.test.js +17 -21
  37. package/test/close-pipelining.test.js +24 -15
  38. package/test/constrained-routes.test.js +231 -0
  39. package/test/custom-http-server.test.js +7 -15
  40. package/test/custom-parser.0.test.js +267 -348
  41. package/test/custom-parser.1.test.js +141 -191
  42. package/test/custom-parser.2.test.js +34 -44
  43. package/test/custom-parser.3.test.js +56 -104
  44. package/test/custom-parser.4.test.js +106 -144
  45. package/test/custom-parser.5.test.js +56 -75
  46. package/test/custom-querystring-parser.test.js +51 -77
  47. package/test/decorator.test.js +76 -259
  48. package/test/delete.test.js +101 -110
  49. package/test/diagnostics-channel/404.test.js +7 -15
  50. package/test/diagnostics-channel/async-request.test.js +8 -16
  51. package/test/diagnostics-channel/error-request.test.js +7 -15
  52. package/test/diagnostics-channel/sync-request-reply.test.js +9 -16
  53. package/test/diagnostics-channel/sync-request.test.js +9 -16
  54. package/test/fastify-instance.test.js +1 -1
  55. package/test/header-overflow.test.js +18 -29
  56. package/test/helper.js +138 -134
  57. package/test/hooks-async.test.js +26 -32
  58. package/test/hooks.test.js +261 -447
  59. package/test/http-methods/copy.test.js +14 -19
  60. package/test/http-methods/get.test.js +131 -143
  61. package/test/http-methods/head.test.js +53 -84
  62. package/test/http-methods/mkcalendar.test.js +45 -72
  63. package/test/http-methods/move.test.js +6 -10
  64. package/test/http-methods/propfind.test.js +34 -44
  65. package/test/http-methods/unlock.test.js +5 -9
  66. package/test/http2/secure-with-fallback.test.js +3 -1
  67. package/test/https/custom-https-server.test.js +9 -13
  68. package/test/input-validation.js +139 -150
  69. package/test/internals/errors.test.js +50 -1
  70. package/test/internals/handle-request.test.js +29 -5
  71. package/test/internals/promise.test.js +63 -0
  72. package/test/internals/reply.test.js +277 -496
  73. package/test/plugin.1.test.js +40 -68
  74. package/test/plugin.2.test.js +40 -70
  75. package/test/plugin.3.test.js +25 -68
  76. package/test/promises.test.js +42 -63
  77. package/test/register.test.js +8 -18
  78. package/test/request-error.test.js +57 -100
  79. package/test/request-id.test.js +30 -49
  80. package/test/route-hooks.test.js +12 -16
  81. package/test/route-shorthand.test.js +9 -27
  82. package/test/route.1.test.js +74 -131
  83. package/test/route.8.test.js +9 -17
  84. package/test/router-options.test.js +450 -0
  85. package/test/schema-validation.test.js +30 -31
  86. package/test/server.test.js +143 -5
  87. package/test/stream.1.test.js +33 -50
  88. package/test/stream.4.test.js +18 -28
  89. package/test/stream.5.test.js +11 -19
  90. package/test/types/errors.test-d.ts +13 -1
  91. package/test/types/type-provider.test-d.ts +55 -0
  92. package/test/use-semicolon-delimiter.test.js +117 -59
  93. package/test/versioned-routes.test.js +39 -56
  94. package/types/errors.d.ts +11 -1
  95. package/types/hooks.d.ts +1 -1
  96. package/types/instance.d.ts +1 -1
  97. package/types/reply.d.ts +2 -2
@@ -1,6 +1,5 @@
1
1
  'use strict'
2
2
 
3
- const sget = require('simple-get').concat
4
3
  const Ajv = require('ajv')
5
4
  const Joi = require('joi')
6
5
  const yup = require('yup')
@@ -139,207 +138,197 @@ module.exports.payloadMethod = function (method, t) {
139
138
 
140
139
  t.after(() => { fastify.close() })
141
140
 
142
- test(`${upMethod} - correctly replies`, (t, testDone) => {
141
+ test(`${upMethod} - correctly replies`, async (t) => {
143
142
  if (upMethod === 'HEAD') {
144
143
  t.plan(2)
145
- sget({
146
- method: upMethod,
147
- url: 'http://localhost:' + fastify.server.address().port
148
- }, (err, response) => {
149
- t.assert.ifError(err)
150
- t.assert.strictEqual(response.statusCode, 200)
151
- testDone()
144
+ const result = await fetch('http://localhost:' + fastify.server.address().port, {
145
+ method: upMethod
152
146
  })
147
+ t.assert.ok(result.ok)
148
+ t.assert.strictEqual(result.status, 200)
153
149
  } else {
154
150
  t.plan(3)
155
- sget({
151
+
152
+ const result = await fetch('http://localhost:' + fastify.server.address().port, {
156
153
  method: upMethod,
157
- url: 'http://localhost:' + fastify.server.address().port,
158
- body: {
159
- hello: 42
160
- },
161
- json: true
162
- }, (err, response, body) => {
163
- t.assert.ifError(err)
164
- t.assert.strictEqual(response.statusCode, 200)
165
- t.assert.deepStrictEqual(body, { hello: 42 })
166
- testDone()
154
+ body: JSON.stringify({ hello: 42 }),
155
+ headers: {
156
+ 'Content-Type': 'application/json'
157
+ }
167
158
  })
159
+
160
+ t.assert.ok(result.ok)
161
+ t.assert.strictEqual(result.status, 200)
162
+ t.assert.deepStrictEqual(await result.json(), { hello: 42 })
168
163
  }
169
164
  })
170
165
 
171
- test(`${upMethod} - 400 on bad parameters`, (t, testDone) => {
166
+ test(`${upMethod} - 400 on bad parameters`, async (t) => {
172
167
  t.plan(3)
173
- sget({
168
+
169
+ const result = await fetch('http://localhost:' + fastify.server.address().port, {
174
170
  method: upMethod,
175
- url: 'http://localhost:' + fastify.server.address().port,
176
- body: {
177
- hello: 'world'
178
- },
179
- json: true
180
- }, (err, response, body) => {
181
- t.assert.ifError(err)
182
- t.assert.strictEqual(response.statusCode, 400)
183
- t.assert.deepStrictEqual(body, {
184
- error: 'Bad Request',
185
- message: 'body/hello must be integer',
186
- statusCode: 400,
187
- code: 'FST_ERR_VALIDATION'
188
- })
189
- testDone()
171
+ body: JSON.stringify({ hello: 'world' }),
172
+ headers: {
173
+ 'Content-Type': 'application/json'
174
+ }
175
+ })
176
+
177
+ t.assert.ok(!result.ok)
178
+ t.assert.strictEqual(result.status, 400)
179
+ t.assert.deepStrictEqual(await result.json(), {
180
+ error: 'Bad Request',
181
+ message: 'body/hello must be integer',
182
+ statusCode: 400,
183
+ code: 'FST_ERR_VALIDATION'
190
184
  })
191
185
  })
192
186
 
193
- test(`${upMethod} - input-validation coerce`, (t, testDone) => {
187
+ test(`${upMethod} - input-validation coerce`, async (t) => {
194
188
  t.plan(3)
195
- sget({
189
+
190
+ const restult = await fetch('http://localhost:' + fastify.server.address().port, {
196
191
  method: upMethod,
197
- url: 'http://localhost:' + fastify.server.address().port,
198
- body: {
199
- hello: '42'
200
- },
201
- json: true
202
- }, (err, response, body) => {
203
- t.assert.ifError(err)
204
- t.assert.strictEqual(response.statusCode, 200)
205
- t.assert.deepStrictEqual(body, { hello: 42 })
206
- testDone()
192
+ body: JSON.stringify({ hello: '42' }),
193
+ headers: {
194
+ 'Content-Type': 'application/json'
195
+ }
207
196
  })
197
+
198
+ t.assert.ok(restult.ok)
199
+ t.assert.strictEqual(restult.status, 200)
200
+ t.assert.deepStrictEqual(await restult.json(), { hello: 42 })
208
201
  })
209
202
 
210
- test(`${upMethod} - input-validation custom schema compiler`, (t, testDone) => {
203
+ test(`${upMethod} - input-validation custom schema compiler`, async (t) => {
211
204
  t.plan(3)
212
- sget({
205
+
206
+ const result = await fetch('http://localhost:' + fastify.server.address().port + '/custom', {
213
207
  method: upMethod,
214
- url: 'http://localhost:' + fastify.server.address().port + '/custom',
215
- body: {
216
- hello: '42',
217
- world: 55
218
- },
219
- json: true
220
- }, (err, response, body) => {
221
- t.assert.ifError(err)
222
- t.assert.strictEqual(response.statusCode, 200)
223
- t.assert.deepStrictEqual(body, { hello: 42 })
224
- testDone()
208
+ body: JSON.stringify({ hello: '42', world: 55 }),
209
+ headers: {
210
+ 'Content-Type': 'application/json'
211
+ }
225
212
  })
213
+
214
+ t.assert.ok(result.ok)
215
+ t.assert.strictEqual(result.status, 200)
216
+ t.assert.deepStrictEqual(await result.json(), { hello: 42 })
226
217
  })
227
218
 
228
- test(`${upMethod} - input-validation joi schema compiler ok`, (t, testDone) => {
219
+ test(`${upMethod} - input-validation joi schema compiler ok`, async (t) => {
229
220
  t.plan(3)
230
- sget({
221
+
222
+ const result = await fetch('http://localhost:' + fastify.server.address().port + '/joi', {
231
223
  method: upMethod,
232
- url: 'http://localhost:' + fastify.server.address().port + '/joi',
233
- body: {
234
- hello: '42'
235
- },
236
- json: true
237
- }, (err, response, body) => {
238
- t.assert.ifError(err)
239
- t.assert.strictEqual(response.statusCode, 200)
240
- t.assert.deepStrictEqual(body, { hello: '42' })
241
- testDone()
224
+ body: JSON.stringify({ hello: '42' }),
225
+ headers: {
226
+ 'Content-Type': 'application/json'
227
+ }
242
228
  })
229
+
230
+ t.assert.ok(result.ok)
231
+ t.assert.strictEqual(result.status, 200)
232
+ t.assert.deepStrictEqual(await result.json(), { hello: '42' })
243
233
  })
244
234
 
245
- test(`${upMethod} - input-validation joi schema compiler ko`, (t, testDone) => {
235
+ test(`${upMethod} - input-validation joi schema compiler ko`, async (t) => {
246
236
  t.plan(3)
247
- sget({
237
+
238
+ const result = await fetch('http://localhost:' + fastify.server.address().port + '/joi', {
248
239
  method: upMethod,
249
- url: 'http://localhost:' + fastify.server.address().port + '/joi',
250
- body: {
251
- hello: 44
252
- },
253
- json: true
254
- }, (err, response, body) => {
255
- t.assert.ifError(err)
256
- t.assert.strictEqual(response.statusCode, 400)
257
- t.assert.deepStrictEqual(body, {
258
- error: 'Bad Request',
259
- message: '"hello" must be a string',
260
- statusCode: 400,
261
- code: 'FST_ERR_VALIDATION'
262
- })
263
- testDone()
240
+ body: JSON.stringify({ hello: 44 }),
241
+ headers: {
242
+ 'Content-Type': 'application/json'
243
+ }
244
+ })
245
+
246
+ t.assert.ok(!result.ok)
247
+ t.assert.strictEqual(result.status, 400)
248
+ t.assert.deepStrictEqual(await result.json(), {
249
+ error: 'Bad Request',
250
+ message: '"hello" must be a string',
251
+ statusCode: 400,
252
+ code: 'FST_ERR_VALIDATION'
264
253
  })
265
254
  })
266
255
 
267
- test(`${upMethod} - input-validation yup schema compiler ok`, (t, testDone) => {
256
+ test(`${upMethod} - input-validation yup schema compiler ok`, async (t) => {
268
257
  t.plan(3)
269
- sget({
258
+
259
+ const result = await fetch('http://localhost:' + fastify.server.address().port + '/yup', {
270
260
  method: upMethod,
271
- url: 'http://localhost:' + fastify.server.address().port + '/yup',
272
- body: {
273
- hello: '42'
274
- },
275
- json: true
276
- }, (err, response, body) => {
277
- t.assert.ifError(err)
278
- t.assert.strictEqual(response.statusCode, 200)
279
- t.assert.deepStrictEqual(body, { hello: '42' })
280
- testDone()
261
+ body: JSON.stringify({ hello: '42' }),
262
+ headers: {
263
+ 'Content-Type': 'application/json'
264
+ }
281
265
  })
266
+
267
+ t.assert.ok(result.ok)
268
+ t.assert.strictEqual(result.status, 200)
269
+ t.assert.deepStrictEqual(await result.json(), { hello: '42' })
282
270
  })
283
271
 
284
- test(`${upMethod} - input-validation yup schema compiler ko`, (t, testDone) => {
272
+ test(`${upMethod} - input-validation yup schema compiler ko`, async (t) => {
285
273
  t.plan(3)
286
- sget({
274
+
275
+ const result = await fetch('http://localhost:' + fastify.server.address().port + '/yup', {
287
276
  method: upMethod,
288
- url: 'http://localhost:' + fastify.server.address().port + '/yup',
289
- body: {
290
- hello: 44
291
- },
292
- json: true
293
- }, (err, response, body) => {
294
- t.assert.ifError(err)
295
- t.assert.strictEqual(response.statusCode, 400)
296
- t.assert.deepStrictEqual(body, {
297
- error: 'Bad Request',
298
- message: 'body hello must be a `string` type, but the final value was: `44`.',
299
- statusCode: 400,
300
- code: 'FST_ERR_VALIDATION'
301
- })
302
- testDone()
277
+ body: JSON.stringify({ hello: 44 }),
278
+ headers: {
279
+ 'Content-Type': 'application/json'
280
+ }
281
+ })
282
+
283
+ t.assert.ok(!result.ok)
284
+ t.assert.strictEqual(result.status, 400)
285
+ t.assert.deepStrictEqual(await result.json(), {
286
+ error: 'Bad Request',
287
+ message: 'body hello must be a `string` type, but the final value was: `44`.',
288
+ statusCode: 400,
289
+ code: 'FST_ERR_VALIDATION'
303
290
  })
304
291
  })
305
292
 
306
- test(`${upMethod} - input-validation instance custom schema compiler encapsulated`, (t, testDone) => {
293
+ test(`${upMethod} - input-validation instance custom schema compiler encapsulated`, async (t) => {
307
294
  t.plan(3)
308
- sget({
295
+
296
+ const result = await fetch('http://localhost:' + fastify.server.address().port + '/plugin', {
309
297
  method: upMethod,
310
- url: 'http://localhost:' + fastify.server.address().port + '/plugin',
311
- body: {},
312
- json: true
313
- }, (err, response, body) => {
314
- t.assert.ifError(err)
315
- t.assert.strictEqual(response.statusCode, 400)
316
- t.assert.deepStrictEqual(body, {
317
- error: 'Bad Request',
318
- message: 'From custom schema compiler!',
319
- statusCode: 400,
320
- code: 'FST_ERR_VALIDATION'
321
- })
322
- testDone()
298
+ body: JSON.stringify({}),
299
+ headers: {
300
+ 'Content-Type': 'application/json'
301
+ }
302
+ })
303
+
304
+ t.assert.ok(!result.ok)
305
+ t.assert.strictEqual(result.status, 400)
306
+ t.assert.deepStrictEqual(await result.json(), {
307
+ error: 'Bad Request',
308
+ message: 'From custom schema compiler!',
309
+ statusCode: 400,
310
+ code: 'FST_ERR_VALIDATION'
323
311
  })
324
312
  })
325
313
 
326
- test(`${upMethod} - input-validation custom schema compiler encapsulated`, (t, testDone) => {
314
+ test(`${upMethod} - input-validation custom schema compiler encapsulated`, async (t) => {
327
315
  t.plan(3)
328
- sget({
316
+
317
+ const result = await fetch('http://localhost:' + fastify.server.address().port + '/plugin/custom', {
329
318
  method: upMethod,
330
- url: 'http://localhost:' + fastify.server.address().port + '/plugin/custom',
331
- body: {},
332
- json: true
333
- }, (err, response, body) => {
334
- t.assert.ifError(err)
335
- t.assert.strictEqual(response.statusCode, 400)
336
- t.assert.deepStrictEqual(body, {
337
- error: 'Bad Request',
338
- message: 'Always fail!',
339
- statusCode: 400,
340
- code: 'FST_ERR_VALIDATION'
341
- })
342
- testDone()
319
+ body: JSON.stringify({}),
320
+ headers: {
321
+ 'Content-Type': 'application/json'
322
+ }
323
+ })
324
+
325
+ t.assert.ok(!result.ok)
326
+ t.assert.strictEqual(result.status, 400)
327
+ t.assert.deepStrictEqual(await result.json(), {
328
+ error: 'Bad Request',
329
+ message: 'Always fail!',
330
+ statusCode: 400,
331
+ code: 'FST_ERR_VALIDATION'
343
332
  })
344
333
  })
345
334
  })
@@ -5,7 +5,7 @@ const errors = require('../../lib/errors')
5
5
  const { readFileSync } = require('node:fs')
6
6
  const { resolve } = require('node:path')
7
7
 
8
- const expectedErrors = 85
8
+ const expectedErrors = 86
9
9
 
10
10
  test(`should expose ${expectedErrors} errors`, t => {
11
11
  t.plan(1)
@@ -190,6 +190,16 @@ test('FST_ERR_CTP_EMPTY_JSON_BODY', t => {
190
190
  t.assert.ok(error instanceof Error)
191
191
  })
192
192
 
193
+ test('FST_ERR_CTP_INVALID_JSON_BODY', t => {
194
+ t.plan(5)
195
+ const error = new errors.FST_ERR_CTP_INVALID_JSON_BODY()
196
+ t.assert.strictEqual(error.name, 'FastifyError')
197
+ t.assert.strictEqual(error.code, 'FST_ERR_CTP_INVALID_JSON_BODY')
198
+ t.assert.strictEqual(error.message, "Body is not valid JSON but content-type is set to 'application/json'")
199
+ t.assert.strictEqual(error.statusCode, 400)
200
+ t.assert.ok(error instanceof Error)
201
+ })
202
+
193
203
  test('FST_ERR_CTP_INSTANCE_ALREADY_STARTED', t => {
194
204
  t.plan(5)
195
205
  const error = new errors.FST_ERR_CTP_INSTANCE_ALREADY_STARTED()
@@ -931,3 +941,42 @@ test('Ensure that non-existing errors are not in Errors.md documented', t => {
931
941
  t.assert.ok(exportedKeys.indexOf(match[1]) !== -1, match[1])
932
942
  }
933
943
  })
944
+
945
+ test('Ensure that all errors are in errors.d.ts', t => {
946
+ t.plan(expectedErrors)
947
+
948
+ const errorsDts = readFileSync(resolve(__dirname, '../../types/errors.d.ts'), 'utf8')
949
+
950
+ const FastifyErrorCodesRE = /export type FastifyErrorCodes = Record<([^>]+),\s*FastifyErrorConstructor>/m
951
+
952
+ const [, errorCodeType] = errorsDts.match(FastifyErrorCodesRE)
953
+
954
+ const errorCodeRE = /'([A-Z0-9_]+)'/g
955
+ const matches = errorCodeType.matchAll(errorCodeRE)
956
+ const errorTypes = [...matches].map(match => match[1])
957
+ const exportedKeys = Object.keys(errors)
958
+
959
+ for (const key of exportedKeys) {
960
+ if (errors[key].name === 'FastifyError') {
961
+ t.assert.ok(errorTypes.includes(key), key)
962
+ }
963
+ }
964
+ })
965
+
966
+ test('Ensure that non-existing errors are not in errors.d.ts', t => {
967
+ t.plan(expectedErrors)
968
+
969
+ const errorsDts = readFileSync(resolve(__dirname, '../../types/errors.d.ts'), 'utf8')
970
+
971
+ const FastifyErrorCodesRE = /export type FastifyErrorCodes = Record<([^>]+),\s*FastifyErrorConstructor>/m
972
+
973
+ const [, errorCodeType] = errorsDts.match(FastifyErrorCodesRE)
974
+
975
+ const errorCodeRE = /'([A-Z0-9_]+)'/g
976
+ const matches = errorCodeType.matchAll(errorCodeRE)
977
+ const exportedKeys = Object.keys(errors)
978
+
979
+ for (const match of matches) {
980
+ t.assert.ok(exportedKeys.indexOf(match[1]) !== -1, match[1])
981
+ }
982
+ })
@@ -191,7 +191,7 @@ test('request should be defined in onSend Hook on post request with content type
191
191
  })
192
192
 
193
193
  test('request should be defined in onSend Hook on options request with content type application/x-www-form-urlencoded', async t => {
194
- t.plan(5)
194
+ t.plan(15)
195
195
  const fastify = require('../..')()
196
196
 
197
197
  t.after(() => {
@@ -209,16 +209,40 @@ test('request should be defined in onSend Hook on options request with content t
209
209
  reply.send(200)
210
210
  })
211
211
 
212
- const fastifyServer = await fastify.listen({ port: 0 })
213
- const result = await fetch(fastifyServer, {
212
+ // Test 1: OPTIONS with body and content-type header
213
+ const result1 = await fastify.inject({
214
+ method: 'OPTIONS',
215
+ url: '/',
216
+ body: 'first-name=OPTIONS&last-name=METHOD',
217
+ headers: {
218
+ 'content-type': 'application/x-www-form-urlencoded'
219
+ }
220
+ })
221
+
222
+ // Content-Type is not supported
223
+ t.assert.strictEqual(result1.statusCode, 415)
224
+
225
+ // Test 2: OPTIONS with content-type header only (no body)
226
+ const result2 = await fastify.inject({
214
227
  method: 'OPTIONS',
228
+ url: '/',
215
229
  headers: {
216
230
  'content-type': 'application/x-www-form-urlencoded'
217
231
  }
218
232
  })
219
233
 
220
- // Body parsing skipped, so no body sent
221
- t.assert.strictEqual(result.status, 200)
234
+ // Content-Type is not supported
235
+ t.assert.strictEqual(result2.statusCode, 415)
236
+
237
+ // Test 3: OPTIONS with body but no content-type header
238
+ const result3 = await fastify.inject({
239
+ method: 'OPTIONS',
240
+ url: '/',
241
+ body: 'first-name=OPTIONS&last-name=METHOD'
242
+ })
243
+
244
+ // No content-type with payload
245
+ t.assert.strictEqual(result3.statusCode, 415)
222
246
  })
223
247
 
224
248
  test('request should respond with an error if an unserialized payload is sent inside an async handler', async t => {
@@ -0,0 +1,63 @@
1
+ 'use strict'
2
+
3
+ const { test } = require('node:test')
4
+
5
+ const { kTestInternals } = require('../../lib/symbols')
6
+ const PonyPromise = require('../../lib/promise')
7
+
8
+ test('withResolvers', async (t) => {
9
+ t.plan(3)
10
+ await t.test('resolve', async (t) => {
11
+ t.plan(1)
12
+ const { promise, resolve } = PonyPromise.withResolvers()
13
+ resolve(true)
14
+ t.assert.ok(await promise)
15
+ })
16
+ await t.test('reject', async (t) => {
17
+ t.plan(1)
18
+ const { promise, reject } = PonyPromise.withResolvers()
19
+ await t.assert.rejects(async () => {
20
+ reject(Error('reject'))
21
+ return promise
22
+ }, {
23
+ name: 'Error',
24
+ message: 'reject'
25
+ })
26
+ })
27
+ await t.test('thenable', async (t) => {
28
+ t.plan(1)
29
+ const { promise, resolve } = PonyPromise.withResolvers()
30
+ resolve(true)
31
+ promise.then((value) => {
32
+ t.assert.ok(value)
33
+ })
34
+ })
35
+ })
36
+
37
+ test('withResolvers - ponyfill', async (t) => {
38
+ await t.test('resolve', async (t) => {
39
+ t.plan(1)
40
+ const { promise, resolve } = PonyPromise[kTestInternals].withResolvers()
41
+ resolve(true)
42
+ t.assert.ok(await promise)
43
+ })
44
+ await t.test('reject', async (t) => {
45
+ t.plan(1)
46
+ const { promise, reject } = PonyPromise[kTestInternals].withResolvers()
47
+ await t.assert.rejects(async () => {
48
+ reject(Error('reject'))
49
+ return promise
50
+ }, {
51
+ name: 'Error',
52
+ message: 'reject'
53
+ })
54
+ })
55
+ await t.test('thenable', async (t) => {
56
+ t.plan(1)
57
+ const { promise, resolve } = PonyPromise.withResolvers()
58
+ resolve(true)
59
+ promise.then((value) => {
60
+ t.assert.ok(value)
61
+ })
62
+ })
63
+ })