From efa01506e3886b1bcb7df621f278d65acf138c19 Mon Sep 17 00:00:00 2001
From: Matteo Pietro Dazzi <matteopietro.dazzi@gmail.com>
Date: Wed, 12 Feb 2025 19:26:17 +0100
Subject: [PATCH 1/9] chore: migrate base to node test runner

---
 README.md         |   2 +-
 package.json      |   4 +-
 test/base.test.js | 142 ++++++++++++++++++++++------------------------
 3 files changed, 70 insertions(+), 78 deletions(-)

diff --git a/README.md b/README.md
index 1a27a26..ab4eed3 100644
--- a/README.md
+++ b/README.md
@@ -339,7 +339,7 @@ test('connect to /', async (t) => {
 
   const fastify = Fastify()
   fastify.register(App)
-  t.teardown(fastify.close.bind(fastify))
+  t.after(() => fastify.close())
   await fastify.ready()
 
   const ws = await fastify.injectWS('/', {headers: { "api-key" : "some-random-key" }})
diff --git a/package.json b/package.json
index 43b6911..b9a387a 100644
--- a/package.json
+++ b/package.json
@@ -9,7 +9,7 @@
     "lint": "eslint",
     "lint:fix": "eslint --fix",
     "test": "npm run test:unit && npm run test:typescript",
-    "test:unit": "tap",
+    "test:unit": "c8 --100 node --test",
     "test:typescript": "tsd"
   },
   "repository": {
@@ -60,12 +60,12 @@
     "@fastify/type-provider-typebox": "^5.0.0",
     "@types/node": "^22.0.0",
     "@types/ws": "^8.5.10",
+    "c8": "^10.1.3",
     "eslint": "^9.17.0",
     "fastify": "^5.0.0",
     "fastify-tsconfig": "^3.0.0",
     "neostandard": "^0.12.0",
     "split2": "^4.2.0",
-    "tap": "^18.7.1",
     "tsd": "^0.31.0"
   },
   "dependencies": {
diff --git a/test/base.test.js b/test/base.test.js
index 4405d3e..5fbb287 100644
--- a/test/base.test.js
+++ b/test/base.test.js
@@ -2,7 +2,7 @@
 
 const http = require('node:http')
 const split = require('split2')
-const test = require('tap').test
+const { test } = require('node:test')
 const Fastify = require('fastify')
 const fastifyWebsocket = require('..')
 const WebSocket = require('ws')
@@ -17,15 +17,15 @@ test('Should expose a websocket', async (t) => {
   t.plan(2)
 
   const fastify = Fastify()
-  t.teardown(() => fastify.close())
+  t.after(() => fastify.close())
 
   await fastify.register(fastifyWebsocket)
 
   fastify.get('/', { websocket: true }, (socket) => {
-    t.teardown(() => socket.terminate())
+    t.after(() => socket.terminate())
 
     socket.once('message', (chunk) => {
-      t.equal(chunk.toString(), 'hello server')
+      t.assert.deepStrictEqual(chunk.toString(), 'hello server')
       socket.send('hello client')
     })
   })
@@ -33,7 +33,7 @@ test('Should expose a websocket', async (t) => {
   await fastify.listen({ port: 0 })
 
   const ws = new WebSocket('ws://localhost:' + fastify.server.address().port)
-  t.teardown(() => {
+  t.after(() => {
     if (ws.readyState) {
       ws.close()
     }
@@ -44,7 +44,7 @@ test('Should expose a websocket', async (t) => {
   ws.send('hello server')
 
   const [chunk] = await chunkPromise
-  t.equal(chunk.toString(), 'hello client')
+  t.assert.deepStrictEqual(chunk.toString(), 'hello client')
   ws.close()
 })
 
@@ -52,22 +52,22 @@ test('Should fail if custom errorHandler is not a function', async (t) => {
   t.plan(2)
 
   const fastify = Fastify()
-  t.teardown(() => fastify.close())
+  t.after(() => fastify.close())
 
   try {
     await fastify.register(fastifyWebsocket, { errorHandler: {} })
   } catch (err) {
-    t.equal(err.message, 'invalid errorHandler function')
+    t.assert.deepStrictEqual(err.message, 'invalid errorHandler function')
   }
 
   fastify.get('/', { websocket: true }, (socket) => {
-    t.teardown(() => socket.terminate())
+    t.after(() => socket.terminate())
   })
 
   try {
     await fastify.listen({ port: 0 })
   } catch (err) {
-    t.equal(err.message, 'invalid errorHandler function')
+    t.assert.deepStrictEqual(err.message, 'invalid errorHandler function')
   }
 })
 
@@ -75,7 +75,7 @@ test('Should run custom errorHandler on wildcard route handler error', async (t)
   t.plan(1)
 
   const fastify = Fastify()
-  t.teardown(() => fastify.close())
+  t.after(() => fastify.close())
 
   let _resolve
   const p = new Promise((resolve) => {
@@ -84,21 +84,21 @@ test('Should run custom errorHandler on wildcard route handler error', async (t)
 
   await fastify.register(fastifyWebsocket, {
     errorHandler: function (error) {
-      t.equal(error.message, 'Fail')
+      t.assert.deepStrictEqual(error.message, 'Fail')
       _resolve()
     }
   })
 
   fastify.get('/*', { websocket: true }, (socket) => {
     socket.on('message', (data) => socket.send(data))
-    t.teardown(() => socket.terminate())
+    t.after(() => socket.terminate())
     return Promise.reject(new Error('Fail'))
   })
 
   await fastify.listen({ port: 0 })
 
   const ws = new WebSocket('ws://localhost:' + fastify.server.address().port)
-  t.teardown(() => {
+  t.after(() => {
     if (ws.readyState) {
       ws.close()
     }
@@ -111,7 +111,7 @@ test('Should run custom errorHandler on error inside websocket handler', async (
   t.plan(1)
 
   const fastify = Fastify()
-  t.teardown(() => fastify.close())
+  t.after(() => fastify.close())
 
   let _resolve
   const p = new Promise((resolve) => {
@@ -120,7 +120,7 @@ test('Should run custom errorHandler on error inside websocket handler', async (
 
   const options = {
     errorHandler: function (error) {
-      t.equal(error.message, 'Fail')
+      t.assert.deepStrictEqual(error.message, 'Fail')
       _resolve()
     }
   }
@@ -129,14 +129,14 @@ test('Should run custom errorHandler on error inside websocket handler', async (
 
   fastify.get('/', { websocket: true }, function wsHandler (socket) {
     socket.on('message', (data) => socket.send(data))
-    t.teardown(() => socket.terminate())
+    t.after(() => socket.terminate())
     throw new Error('Fail')
   })
 
   await fastify.listen({ port: 0 })
   const ws = new WebSocket('ws://localhost:' + fastify.server.address().port)
 
-  t.teardown(() => {
+  t.after(() => {
     if (ws.readyState) {
       ws.close()
     }
@@ -149,7 +149,7 @@ test('Should run custom errorHandler on error inside async websocket handler', a
   t.plan(1)
 
   const fastify = Fastify()
-  t.teardown(() => fastify.close())
+  t.after(() => fastify.close())
 
   let _resolve
   const p = new Promise((resolve) => {
@@ -158,7 +158,7 @@ test('Should run custom errorHandler on error inside async websocket handler', a
 
   const options = {
     errorHandler: function (error) {
-      t.equal(error.message, 'Fail')
+      t.assert.deepStrictEqual(error.message, 'Fail')
       _resolve()
     }
   }
@@ -167,13 +167,13 @@ test('Should run custom errorHandler on error inside async websocket handler', a
 
   fastify.get('/', { websocket: true }, async function wsHandler (socket) {
     socket.on('message', (data) => socket.send(data))
-    t.teardown(() => socket.terminate())
+    t.after(() => socket.terminate())
     throw new Error('Fail')
   })
 
   await fastify.listen({ port: 0 })
   const ws = new WebSocket('ws://localhost:' + fastify.server.address().port)
-  t.teardown(() => {
+  t.after(() => {
     if (ws.readyState) {
       ws.close()
     }
@@ -186,11 +186,11 @@ test('Should be able to pass custom options to ws', async (t) => {
   t.plan(2)
 
   const fastify = Fastify()
-  t.teardown(() => fastify.close())
+  t.after(() => fastify.close())
 
   const options = {
     verifyClient: function (info) {
-      t.equal(info.req.headers['x-custom-header'], 'fastify is awesome !')
+      t.assert.deepStrictEqual(info.req.headers['x-custom-header'], 'fastify is awesome !')
 
       return true
     }
@@ -200,7 +200,7 @@ test('Should be able to pass custom options to ws', async (t) => {
 
   fastify.get('/*', { websocket: true }, (socket) => {
     socket.on('message', (data) => socket.send(data))
-    t.teardown(() => socket.terminate())
+    t.after(() => socket.terminate())
   })
 
   await fastify.listen({ port: 0 })
@@ -209,7 +209,7 @@ test('Should be able to pass custom options to ws', async (t) => {
   const ws = new WebSocket('ws://localhost:' + fastify.server.address().port, clientOptions)
   const chunkPromise = once(ws, 'message')
   await once(ws, 'open')
-  t.teardown(() => {
+  t.after(() => {
     if (ws.readyState) {
       ws.close()
     }
@@ -218,7 +218,7 @@ test('Should be able to pass custom options to ws', async (t) => {
   ws.send('hello')
 
   const [chunk] = await chunkPromise
-  t.equal(chunk.toString(), 'hello')
+  t.assert.deepStrictEqual(chunk.toString(), 'hello')
   ws.close()
 })
 
@@ -233,18 +233,18 @@ test('Should warn if path option is provided to ws', async (t) => {
   })
 
   logStream.once('data', line => {
-    t.equal(line.msg, 'ws server path option shouldn\'t be provided, use a route instead')
-    t.equal(line.level, 40)
+    t.assert.deepStrictEqual(line.msg, 'ws server path option shouldn\'t be provided, use a route instead')
+    t.assert.deepStrictEqual(line.level, 40)
   })
 
-  t.teardown(() => fastify.close())
+  t.after(() => fastify.close())
 
   const options = { path: '/' }
   await fastify.register(fastifyWebsocket, { options })
 
   fastify.get('/*', { websocket: true }, (socket) => {
     socket.on('message', (data) => socket.send(data))
-    t.teardown(() => socket.terminate())
+    t.after(() => socket.terminate())
   })
 
   await fastify.listen({ port: 0 })
@@ -253,7 +253,7 @@ test('Should warn if path option is provided to ws', async (t) => {
   const ws = new WebSocket('ws://localhost:' + fastify.server.address().port, clientOptions)
   const chunkPromise = once(ws, 'message')
   await once(ws, 'open')
-  t.teardown(() => {
+  t.after(() => {
     if (ws.readyState) {
       ws.close()
     }
@@ -262,7 +262,7 @@ test('Should warn if path option is provided to ws', async (t) => {
   ws.send('hello')
 
   const [chunk] = await chunkPromise
-  t.equal(chunk.toString(), 'hello')
+  t.assert.deepStrictEqual(chunk.toString(), 'hello')
   ws.close()
 })
 
@@ -277,7 +277,7 @@ test('Should be able to pass a custom server option to ws', async (t) => {
     .listen(externalServerPort, 'localhost')
 
   const fastify = Fastify()
-  t.teardown(() => {
+  t.after(() => {
     externalServer.close()
     fastify.close()
   })
@@ -290,7 +290,7 @@ test('Should be able to pass a custom server option to ws', async (t) => {
 
   fastify.get('/', { websocket: true }, (socket) => {
     socket.on('message', (data) => socket.send(data))
-    t.teardown(() => socket.terminate())
+    t.after(() => socket.terminate())
   })
 
   await fastify.ready()
@@ -298,7 +298,7 @@ test('Should be able to pass a custom server option to ws', async (t) => {
   const ws = new WebSocket('ws://localhost:' + externalServerPort)
   const chunkPromise = once(ws, 'message')
   await once(ws, 'open')
-  t.teardown(() => {
+  t.after(() => {
     if (ws.readyState) {
       ws.close()
     }
@@ -307,13 +307,11 @@ test('Should be able to pass a custom server option to ws', async (t) => {
   ws.send('hello')
 
   const [chunk] = await chunkPromise
-  t.equal(chunk.toString(), 'hello')
+  t.assert.deepStrictEqual(chunk.toString(), 'hello')
   ws.close()
 })
 
-test('Should be able to pass clientTracking option in false to ws', (t) => {
-  t.plan(2)
-
+test('Should be able to pass clientTracking option in false to ws', async (t) => {
   const fastify = Fastify()
 
   const options = {
@@ -326,13 +324,9 @@ test('Should be able to pass clientTracking option in false to ws', (t) => {
     socket.close()
   })
 
-  fastify.listen({ port: 0 }, (err) => {
-    t.error(err)
+  await fastify.listen({ port: 0 })
 
-    fastify.close(err => {
-      t.error(err)
-    })
-  })
+  await fastify.close()
 })
 
 test('Should be able to pass preClose option to override default', async (t) => {
@@ -341,7 +335,7 @@ test('Should be able to pass preClose option to override default', async (t) =>
   const fastify = Fastify()
 
   const preClose = (done) => {
-    t.pass('Custom preclose successfully called')
+    t.assert.ok('Custom preclose successfully called')
 
     for (const connection of fastify.websocketServer.clients) {
       connection.close()
@@ -352,10 +346,10 @@ test('Should be able to pass preClose option to override default', async (t) =>
   await fastify.register(fastifyWebsocket, { preClose })
 
   fastify.get('/', { websocket: true }, (socket) => {
-    t.teardown(() => socket.terminate())
+    t.after(() => socket.terminate())
 
     socket.once('message', (chunk) => {
-      t.equal(chunk.toString(), 'hello server')
+      t.assert.deepStrictEqual(chunk.toString(), 'hello server')
       socket.send('hello client')
     })
   })
@@ -363,7 +357,7 @@ test('Should be able to pass preClose option to override default', async (t) =>
   await fastify.listen({ port: 0 })
 
   const ws = new WebSocket('ws://localhost:' + fastify.server.address().port)
-  t.teardown(() => {
+  t.after(() => {
     if (ws.readyState) {
       ws.close()
     }
@@ -374,7 +368,7 @@ test('Should be able to pass preClose option to override default', async (t) =>
   ws.send('hello server')
 
   const [chunk] = await chunkPromise
-  t.equal(chunk.toString(), 'hello client')
+  t.assert.deepStrictEqual(chunk.toString(), 'hello client')
   ws.close()
 
   await fastify.close()
@@ -384,24 +378,24 @@ test('Should fail if custom preClose is not a function', async (t) => {
   t.plan(2)
 
   const fastify = Fastify()
-  t.teardown(() => fastify.close())
+  t.after(() => fastify.close())
 
   const preClose = 'Not a function'
 
   try {
     await fastify.register(fastifyWebsocket, { preClose })
   } catch (err) {
-    t.equal(err.message, 'invalid preClose function')
+    t.assert.deepStrictEqual(err.message, 'invalid preClose function')
   }
 
   fastify.get('/', { websocket: true }, (socket) => {
-    t.teardown(() => socket.terminate())
+    t.after(() => socket.terminate())
   })
 
   try {
     await fastify.listen({ port: 0 })
   } catch (err) {
-    t.equal(err.message, 'invalid preClose function')
+    t.assert.deepStrictEqual(err.message, 'invalid preClose function')
   }
 })
 
@@ -417,7 +411,7 @@ test('Should gracefully close with a connected client', async (t) => {
     socket.send('hello client')
 
     socket.once('message', (chunk) => {
-      t.equal(chunk.toString(), 'hello server')
+      t.assert.deepStrictEqual(chunk.toString(), 'hello server')
     })
 
     serverConnEnded = once(socket, 'close')
@@ -433,7 +427,7 @@ test('Should gracefully close with a connected client', async (t) => {
 
   const ended = once(ws, 'close')
   const [chunk] = await chunkPromise
-  t.equal(chunk.toString(), 'hello client')
+  t.assert.deepStrictEqual(chunk.toString(), 'hello client')
   await fastify.close()
   await ended
   await serverConnEnded
@@ -450,7 +444,7 @@ test('Should gracefully close when clients attempt to connect after calling clos
     const ws = new WebSocket('ws://localhost:' + fastify.server.address().port)
 
     p = once(ws, 'close').catch((err) => {
-      t.equal(err.message, 'Unexpected server response: 503')
+      t.assert.deepStrictEqual(err.message, 'Unexpected server response: 503')
       oldClose.call(this, cb)
     })
   }
@@ -458,7 +452,7 @@ test('Should gracefully close when clients attempt to connect after calling clos
   await fastify.register(fastifyWebsocket)
 
   fastify.get('/', { websocket: true }, (socket) => {
-    t.pass('received client connection')
+    t.assert.ok('received client connection')
     socket.close()
     // this connection stays alive until we close the server
   })
@@ -468,7 +462,7 @@ test('Should gracefully close when clients attempt to connect after calling clos
   const ws = new WebSocket('ws://localhost:' + fastify.server.address().port)
 
   ws.on('close', () => {
-    t.pass('client 1 closed')
+    t.assert.ok('client 1 closed')
   })
 
   await once(ws, 'open')
@@ -534,7 +528,7 @@ test('Should keep accepting connection', { skip: !timersPromises }, async t => {
       threshold = unhandled
     } else if (sent === 100) {
       await fastify.close()
-      t.ok(unhandled <= threshold)
+      t.assert.ok(unhandled <= threshold)
       break
     }
   }
@@ -581,7 +575,7 @@ test('Should keep processing message when many medium sized messages are sent',
   }
 
   await fastify.close()
-  t.equal(handled, total)
+  t.assert.deepStrictEqual(handled, total)
 })
 
 test('Should error server if the noServer option is set', (t) => {
@@ -589,28 +583,26 @@ test('Should error server if the noServer option is set', (t) => {
   const fastify = Fastify()
 
   fastify.register(fastifyWebsocket, { options: { noServer: true } })
-  t.rejects(fastify.ready())
+  t.assert.rejects(fastify.ready())
 })
 
-test('Should preserve the prefix in non-websocket routes', (t) => {
-  t.plan(3)
+test('Should preserve the prefix in non-websocket routes', async (t) => {
+  t.plan(2)
 
   const fastify = Fastify()
-  t.teardown(() => fastify.close())
+  t.after(() => fastify.close())
 
   fastify.register(fastifyWebsocket)
 
   fastify.register(async function (fastify) {
-    t.equal(fastify.prefix, '/hello')
+    t.assert.deepStrictEqual(fastify.prefix, '/hello')
     fastify.get('/', function (_, reply) {
-      t.equal(this.prefix, '/hello')
+      t.assert.deepStrictEqual(this.prefix, '/hello')
       reply.send('hello')
     })
   }, { prefix: '/hello' })
 
-  fastify.inject('/hello', function (err) {
-    t.error(err)
-  })
+  await fastify.inject('/hello')
 })
 
 test('Should Handle WebSocket errors to avoid Node.js crashes', async t => {
@@ -621,7 +613,7 @@ test('Should Handle WebSocket errors to avoid Node.js crashes', async t => {
 
   fastify.get('/', { websocket: true }, (socket) => {
     socket.on('error', err => {
-      t.equal(err.code, 'WS_ERR_UNEXPECTED_RSV_2_3')
+      t.assert.deepStrictEqual(err.code, 'WS_ERR_UNEXPECTED_RSV_2_3')
     })
   })
 
@@ -644,12 +636,12 @@ test('remove all others websocket handlers on close', async (t) => {
 
   await fastify.close()
 
-  t.equal(fastify.server.listeners('upgrade').length, 0)
+  t.assert.deepStrictEqual(fastify.server.listeners('upgrade').length, 0)
 })
 
 test('clashing upgrade handler', async (t) => {
   const fastify = Fastify()
-  t.teardown(() => fastify.close())
+  t.after(() => fastify.close())
 
   fastify.server.on('upgrade', (req, socket) => {
     const res = new http.ServerResponse(req)
@@ -661,7 +653,7 @@ test('clashing upgrade handler', async (t) => {
   await fastify.register(fastifyWebsocket)
 
   fastify.get('/', { websocket: true }, () => {
-    t.fail('this should never be invoked')
+    t.assert.fail('this should never be invoked')
   })
 
   await fastify.listen({ port: 0 })

From 858200262edbce569a4a78e0ab31e768c40c36d8 Mon Sep 17 00:00:00 2001
From: Matteo Pietro Dazzi <matteopietro.dazzi@gmail.com>
Date: Wed, 12 Feb 2025 19:28:24 +0100
Subject: [PATCH 2/9] chore: migrate inject

---
 test/inject.test.js | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/test/inject.test.js b/test/inject.test.js
index 3f34330..b0c659f 100644
--- a/test/inject.test.js
+++ b/test/inject.test.js
@@ -1,12 +1,12 @@
 'use strict'
 
-const { test } = require('tap')
+const { test } = require('node:test')
 const Fastify = require('fastify')
 const fastifyWebsocket = require('..')
 
 function buildFastify (t) {
   const fastify = Fastify()
-  t.teardown(() => { fastify.close() })
+  t.after(() => { fastify.close() })
   fastify.register(fastifyWebsocket)
   return fastify
 }
@@ -30,7 +30,7 @@ test('routes correctly the message', async (t) => {
   await fastify.ready()
   const ws = await fastify.injectWS('/ws')
   ws.send(message)
-  t.same(await promise, message)
+  t.assert.deepStrictEqual(await promise, message)
   ws.terminate()
 })
 
@@ -53,7 +53,7 @@ test('redirect on / if no path specified', async (t) => {
   await fastify.ready()
   const ws = await fastify.injectWS()
   ws.send(message)
-  t.same(await promise, message)
+  t.assert.deepStrictEqual(await promise, message)
   ws.terminate()
 })
 
@@ -83,7 +83,7 @@ test('routes correctly the message between two routes', async (t) => {
   await fastify.ready()
   const ws = await fastify.injectWS('/ws-2')
   ws.send(message)
-  t.same(await promise, message)
+  t.assert.deepStrictEqual(await promise, message)
   ws.terminate()
 })
 
@@ -112,7 +112,7 @@ test('use the upgrade context to upgrade if there is some hook', async (t) => {
   await fastify.ready()
   const ws = await fastify.injectWS('/', { headers: { 'api-key': 'some-random-key' } })
   ws.send(message)
-  t.same(await promise, message)
+  t.assert.deepStrictEqual(await promise, message)
   ws.terminate()
 })
 
@@ -130,5 +130,5 @@ test('rejects if the websocket is not upgraded', async (t) => {
     })
 
   await fastify.ready()
-  t.rejects(fastify.injectWS('/'), 'Unexpected server response: 401')
+  t.assert.rejects(fastify.injectWS('/'), 'Unexpected server response: 401')
 })

From e896a3613c21b71cdd05d1d39abf3c13e481b58d Mon Sep 17 00:00:00 2001
From: Matteo Pietro Dazzi <matteopietro.dazzi@gmail.com>
Date: Wed, 12 Feb 2025 19:44:49 +0100
Subject: [PATCH 3/9] chore: migrate hooks

---
 test/hooks.test.js | 186 +++++++++++++++++++++++++--------------------
 1 file changed, 104 insertions(+), 82 deletions(-)

diff --git a/test/hooks.test.js b/test/hooks.test.js
index 9c53ae7..4690d92 100644
--- a/test/hooks.test.js
+++ b/test/hooks.test.js
@@ -1,111 +1,116 @@
 'use strict'
 
-const test = require('tap').test
+const { test } = require('node:test')
 const net = require('node:net')
 const Fastify = require('fastify')
 const fastifyWebsocket = require('..')
 const WebSocket = require('ws')
 const split = require('split2')
 
-test('Should run onRequest, preValidation, preHandler hooks', t => {
+test('Should run onRequest, preValidation, preHandler hooks', (t, end) => {
   t.plan(7)
   const fastify = Fastify()
 
-  t.teardown(() => fastify.close())
+  t.after(() => fastify.close())
 
   fastify.register(fastifyWebsocket)
 
   fastify.register(async function (fastify) {
-    fastify.addHook('onRequest', async () => t.ok('called', 'onRequest'))
-    fastify.addHook('preParsing', async () => t.ok('called', 'preParsing'))
-    fastify.addHook('preValidation', async () => t.ok('called', 'preValidation'))
-    fastify.addHook('preHandler', async () => t.ok('called', 'preHandler'))
+    fastify.addHook('onRequest', async () => t.assert.ok('called', 'onRequest'))
+    fastify.addHook('preParsing', async () => t.assert.ok('called', 'preParsing'))
+    fastify.addHook('preValidation', async () => t.assert.ok('called', 'preValidation'))
+    fastify.addHook('preHandler', async () => t.assert.ok('called', 'preHandler'))
 
     fastify.get('/echo', { websocket: true }, (socket) => {
       socket.send('hello client')
-      t.teardown(() => socket.terminate())
+      t.after(() => socket.terminate())
 
       socket.once('message', (chunk) => {
-        t.equal(chunk.toString(), 'hello server')
+        t.assert.deepStrictEqual(chunk.toString(), 'hello server')
+        end()
       })
     })
   })
 
   fastify.listen({ port: 0 }, err => {
-    t.error(err)
+    t.assert.ifError(err)
     const ws = new WebSocket('ws://localhost:' + (fastify.server.address()).port + '/echo')
     const client = WebSocket.createWebSocketStream(ws, { encoding: 'utf8' })
-    t.teardown(client.destroy.bind(client))
+    t.after(() => client.destroy())
 
     client.setEncoding('utf8')
     client.write('hello server')
 
     client.once('data', chunk => {
-      t.equal(chunk, 'hello client')
+      t.assert.deepStrictEqual(chunk, 'hello client')
       client.end()
     })
   })
 })
 
-test('Should not run onTimeout hook', t => {
+test('Should not run onTimeout hook', (t, end) => {
   t.plan(2)
   const fastify = Fastify()
 
-  t.teardown(() => fastify.close())
+  t.after(() => fastify.close())
 
   fastify.register(fastifyWebsocket)
 
   fastify.register(async function () {
-    fastify.addHook('onTimeout', async () => t.fail('called', 'onTimeout'))
+    fastify.addHook('onTimeout', async () => t.assert.fail('called', 'onTimeout'))
 
     fastify.get('/echo', { websocket: true }, (socket, request) => {
       socket.send('hello client')
       request.raw.setTimeout(50)
-      t.teardown(() => socket.terminate())
+      t.after(() => socket.terminate())
     })
   })
 
   fastify.listen({ port: 0 }, err => {
-    t.error(err)
+    t.assert.ifError(err)
     const ws = new WebSocket('ws://localhost:' + (fastify.server.address()).port + '/echo')
     const client = WebSocket.createWebSocketStream(ws, { encoding: 'utf8' })
-    t.teardown(client.destroy.bind(client))
+    t.after(() => client.destroy())
 
     client.once('data', chunk => {
-      t.equal(chunk, 'hello client')
+      t.assert.deepStrictEqual(chunk, 'hello client')
+      end()
     })
   })
 })
 
-test('Should run onError hook before handler is executed (error thrown in onRequest hook)', t => {
+test('Should run onError hook before handler is executed (error thrown in onRequest hook)', (t, end) => {
   t.plan(3)
   const fastify = Fastify()
 
-  t.teardown(() => fastify.close())
+  t.after(() => fastify.close())
 
   fastify.register(fastifyWebsocket)
 
   fastify.register(async function (fastify) {
     fastify.addHook('onRequest', async () => { throw new Error('Fail') })
-    fastify.addHook('onError', async () => t.ok('called', 'onError'))
+    fastify.addHook('onError', async () => t.assert.ok('called', 'onError'))
 
     fastify.get('/echo', { websocket: true }, () => {
-      t.fail()
+      t.assert.fail()
     })
   })
 
   fastify.listen({ port: 0 }, function (err) {
-    t.error(err)
+    t.assert.ifError(err)
     const ws = new WebSocket('ws://localhost:' + (fastify.server.address()).port + '/echo')
-    ws.on('unexpected-response', (_request, response) => t.equal(response.statusCode, 500))
+    ws.on('unexpected-response', (_request, response) => {
+      t.assert.deepStrictEqual(response.statusCode, 500)
+      end()
+    })
   })
 })
 
-test('Should run onError hook before handler is executed (error thrown in preValidation hook)', t => {
+test('Should run onError hook before handler is executed (error thrown in preValidation hook)', (t, end) => {
   t.plan(3)
   const fastify = Fastify()
 
-  t.teardown(() => fastify.close())
+  t.after(() => fastify.close())
 
   fastify.register(fastifyWebsocket)
 
@@ -115,25 +120,28 @@ test('Should run onError hook before handler is executed (error thrown in preVal
       throw new Error('Fail')
     })
 
-    fastify.addHook('onError', async () => t.ok('called', 'onError'))
+    fastify.addHook('onError', async () => t.assert.ok('called', 'onError'))
 
     fastify.get('/echo', { websocket: true }, () => {
-      t.fail()
+      t.assert.fail()
     })
   })
 
   fastify.listen({ port: 0 }, function (err) {
-    t.error(err)
+    t.assert.ifError(err)
     const ws = new WebSocket('ws://localhost:' + (fastify.server.address()).port + '/echo')
-    ws.on('unexpected-response', (_request, response) => t.equal(response.statusCode, 500))
+    ws.on('unexpected-response', (_request, response) => {
+      t.assert.deepStrictEqual(response.statusCode, 500)
+      end()
+    })
   })
 })
 
-test('onError hooks can send a reply and prevent hijacking', t => {
+test('onError hooks can send a reply and prevent hijacking', (t, end) => {
   t.plan(3)
   const fastify = Fastify()
 
-  t.teardown(() => fastify.close())
+  t.after(() => fastify.close())
 
   fastify.register(fastifyWebsocket)
 
@@ -144,27 +152,30 @@ test('onError hooks can send a reply and prevent hijacking', t => {
     })
 
     fastify.addHook('onError', async (_request, reply) => {
-      t.ok('called', 'onError')
+      t.assert.ok('called', 'onError')
       await reply.code(501).send('there was an error')
     })
 
     fastify.get('/echo', { websocket: true }, () => {
-      t.fail()
+      t.assert.fail()
     })
   })
 
   fastify.listen({ port: 0 }, function (err) {
-    t.error(err)
+    t.assert.ifError(err)
     const ws = new WebSocket('ws://localhost:' + (fastify.server.address()).port + '/echo')
-    ws.on('unexpected-response', (_request, response) => t.equal(response.statusCode, 501))
+    ws.on('unexpected-response', (_request, response) => {
+      t.assert.deepStrictEqual(response.statusCode, 501)
+      end()
+    })
   })
 })
 
-test('setErrorHandler functions can send a reply and prevent hijacking', t => {
+test('setErrorHandler functions can send a reply and prevent hijacking', (t, end) => {
   t.plan(4)
   const fastify = Fastify()
 
-  t.teardown(() => fastify.close())
+  t.after(() => fastify.close())
 
   fastify.register(fastifyWebsocket)
 
@@ -175,85 +186,92 @@ test('setErrorHandler functions can send a reply and prevent hijacking', t => {
     })
 
     fastify.setErrorHandler(async (error, _request, reply) => {
-      t.ok('called', 'onError')
-      t.ok(error)
+      t.assert.ok('called', 'onError')
+      t.assert.ok(error)
       await reply.code(501).send('there was an error')
     })
 
     fastify.get('/echo', { websocket: true }, () => {
-      t.fail()
+      t.assert.fail()
     })
   })
 
   fastify.listen({ port: 0 }, function (err) {
-    t.error(err)
+    t.assert.ifError(err)
     const ws = new WebSocket('ws://localhost:' + (fastify.server.address()).port + '/echo')
-    ws.on('unexpected-response', (_request, response) => t.equal(response.statusCode, 501))
+    ws.on('unexpected-response', (_request, response) => {
+      t.assert.deepStrictEqual(response.statusCode, 501)
+      end()
+    })
   })
 })
 
-test('Should not run onError hook if reply was already hijacked (error thrown in websocket handler)', t => {
+test('Should not run onError hook if reply was already hijacked (error thrown in websocket handler)', (t, end) => {
   t.plan(2)
   const fastify = Fastify()
 
-  t.teardown(() => fastify.close())
+  t.after(() => fastify.close())
 
   fastify.register(fastifyWebsocket)
 
   fastify.register(async function (fastify) {
-    fastify.addHook('onError', async () => t.fail('called', 'onError'))
+    fastify.addHook('onError', async () => t.assert.fail('called', 'onError'))
 
     fastify.get('/echo', { websocket: true }, async (socket) => {
-      t.teardown(() => socket.terminate())
+      t.after(() => socket.terminate())
       throw new Error('Fail')
     })
   })
 
   fastify.listen({ port: 0 }, function (err) {
-    t.error(err)
+    t.assert.ifError(err)
     const ws = new WebSocket('ws://localhost:' + (fastify.server.address()).port + '/echo')
     const client = WebSocket.createWebSocketStream(ws, { encoding: 'utf8' })
-    t.teardown(client.destroy.bind(client))
-    ws.on('close', code => t.equal(code, 1006))
+    t.after(() => client.destroy())
+    ws.on('close', code => {
+      t.assert.deepStrictEqual(code, 1006)
+      end()
+    })
   })
 })
 
-test('Should not run preSerialization/onSend hooks', t => {
+test('Should not run preSerialization/onSend hooks', (t, end) => {
   t.plan(2)
   const fastify = Fastify()
 
-  t.teardown(() => fastify.close())
+  t.after(() => fastify.close())
 
   fastify.register(fastifyWebsocket)
 
   fastify.register(async function (fastify) {
-    fastify.addHook('onSend', async () => t.fail('called', 'onSend'))
-    fastify.addHook('preSerialization', async () => t.fail('called', 'preSerialization'))
+    fastify.addHook('onSend', async () => t.assert.fail('called', 'onSend'))
+    fastify.addHook('preSerialization', async () => t.assert.fail('called', 'preSerialization'))
 
     fastify.get('/echo', { websocket: true }, async (socket) => {
       socket.send('hello client')
-      t.teardown(() => socket.terminate())
+      t.after(() => socket.terminate())
     })
   })
 
   fastify.listen({ port: 0 }, err => {
-    t.error(err)
+    t.assert.ifError(err)
     const ws = new WebSocket('ws://localhost:' + (fastify.server.address()).port + '/echo')
     const client = WebSocket.createWebSocketStream(ws, { encoding: 'utf8' })
-    t.teardown(client.destroy.bind(client))
+    t.after(() => client.destroy())
 
     client.once('data', chunk => {
-      t.equal(chunk, 'hello client')
+      t.assert.deepStrictEqual(chunk, 'hello client')
       client.end()
+      end()
     })
   })
 })
 
-test('Should not hijack reply for a normal http request in the internal onError hook', t => {
+test('Should not hijack reply for a normal http request in the internal onError hook', (t, end) => {
   t.plan(2)
   const fastify = Fastify()
 
-  t.teardown(() => fastify.close())
+  t.after(() => fastify.close())
 
   fastify.register(fastifyWebsocket)
 
@@ -264,27 +282,28 @@ test('Should not hijack reply for a normal http request in the internal onError
   })
 
   fastify.listen({ port: 0 }, err => {
-    t.error(err)
+    t.assert.ifError(err)
 
     const port = fastify.server.address().port
 
     const httpClient = net.createConnection({ port }, () => {
-      t.teardown(httpClient.destroy.bind(httpClient))
+      t.after(() => httpClient.destroy())
 
       httpClient.write('GET / HTTP/1.1\r\nHOST: localhost\r\n\r\n')
       httpClient.once('data', data => {
-        t.match(data.toString(), /Fail/i)
+        t.assert.match(data.toString(), /Fail/i)
+        end()
       })
       httpClient.end()
     })
   })
 })
 
-test('Should run async hooks and still deliver quickly sent messages', (t) => {
+test('Should run async hooks and still deliver quickly sent messages', (t, end) => {
   t.plan(3)
   const fastify = Fastify()
 
-  t.teardown(() => fastify.close())
+  t.after(() => fastify.close())
 
   fastify.register(fastifyWebsocket)
 
@@ -296,36 +315,37 @@ test('Should run async hooks and still deliver quickly sent messages', (t) => {
 
     fastify.get('/echo', { websocket: true }, (socket) => {
       socket.send('hello client')
-      t.teardown(() => socket.terminate())
+      t.after(() => socket.terminate())
 
       socket.on('message', (message) => {
-        t.equal(message.toString('utf-8'), 'hello server')
+        t.assert.deepStrictEqual(message.toString('utf-8'), 'hello server')
+        end()
       })
     })
   })
 
   fastify.listen({ port: 0 }, (err) => {
-    t.error(err)
+    t.assert.ifError(err)
     const ws = new WebSocket(
       'ws://localhost:' + fastify.server.address().port + '/echo'
     )
     const client = WebSocket.createWebSocketStream(ws, { encoding: 'utf8' })
-    t.teardown(client.destroy.bind(client))
+    t.after(() => client.destroy())
 
     client.setEncoding('utf8')
     client.write('hello server')
 
     client.once('data', (chunk) => {
-      t.equal(chunk, 'hello client')
+      t.assert.deepStrictEqual(chunk, 'hello client')
       client.end()
     })
   })
 })
 
-test('Should not hijack reply for an normal request to a websocket route that is sent a normal HTTP response in a hook', t => {
+test('Should not hijack reply for an normal request to a websocket route that is sent a normal HTTP response in a hook', (t, end) => {
   t.plan(2)
   const fastify = Fastify()
-  t.teardown(() => fastify.close())
+  t.after(() => fastify.close())
 
   fastify.register(fastifyWebsocket)
   fastify.register(async function (fastify) {
@@ -334,27 +354,28 @@ test('Should not hijack reply for an normal request to a websocket route that is
       await reply.code(404).send('not found')
     })
     fastify.get('/echo', { websocket: true }, () => {
-      t.fail()
+      t.assert.fail()
     })
   })
 
   fastify.listen({ port: 0 }, err => {
-    t.error(err)
+    t.assert.ifError(err)
 
     const port = fastify.server.address().port
 
     const httpClient = net.createConnection({ port }, () => {
-      t.teardown(httpClient.destroy.bind(httpClient))
+      t.after(() => httpClient.destroy())
       httpClient.write('GET /echo HTTP/1.1\r\nHOST: localhost\r\n\r\n')
       httpClient.once('data', data => {
-        t.match(data.toString(), /not found/i)
+        t.assert.match(data.toString(), /not found/i)
+        end()
       })
       httpClient.end()
     })
   })
 })
 
-test('Should not hijack reply for an WS request to a WS route that gets sent a normal HTTP response in a hook', t => {
+test('Should not hijack reply for an WS request to a WS route that gets sent a normal HTTP response in a hook', (t, end) => {
   t.plan(2)
   const stream = split(JSON.parse)
   const fastify = Fastify({ logger: { stream } })
@@ -365,25 +386,26 @@ test('Should not hijack reply for an WS request to a WS route that gets sent a n
       await reply.code(404).send('not found')
     })
     fastify.get('/echo', { websocket: true }, () => {
-      t.fail()
+      t.assert.fail()
     })
   })
 
   stream.on('data', (chunk) => {
     if (chunk.level >= 50) {
-      t.fail()
+      t.assert.fail()
     }
   })
 
   fastify.listen({ port: 0 }, err => {
-    t.error(err)
+    t.assert.ifError(err)
 
     const ws = new WebSocket('ws://localhost:' + (fastify.server.address()).port + '/echo')
 
     ws.on('error', error => {
-      t.ok(error)
+      t.assert.ok(error)
       ws.close()
       fastify.close()
+      end()
     })
   })
 })

From f8f027dfd7386918d4bdd5c5860c0906a9b31cc4 Mon Sep 17 00:00:00 2001
From: Matteo Pietro Dazzi <matteopietro.dazzi@gmail.com>
Date: Wed, 12 Feb 2025 19:52:50 +0100
Subject: [PATCH 4/9] chore: migrate router

---
 test/router.test.js | 300 +++++++++++++++++++++++---------------------
 1 file changed, 155 insertions(+), 145 deletions(-)

diff --git a/test/router.test.js b/test/router.test.js
index 5936eb9..2464807 100644
--- a/test/router.test.js
+++ b/test/router.test.js
@@ -1,28 +1,29 @@
 'use strict'
 
 const net = require('node:net')
-const test = require('tap').test
+const { test } = require('node:test')
 const Fastify = require('fastify')
 const fastifyWebsocket = require('..')
 const WebSocket = require('ws')
 const get = require('node:http').get
 
-test('Should expose a websocket on prefixed route', t => {
+test('Should expose a websocket on prefixed route', (t, end) => {
   t.plan(4)
   const fastify = Fastify()
 
-  t.teardown(() => fastify.close())
+  t.after(() => fastify.close())
 
   fastify.register(fastifyWebsocket)
   fastify.register(
     function (instance, _opts, next) {
       instance.get('/echo', { websocket: true }, function (socket) {
-        t.equal(this.prefix, '/baz')
+        t.assert.deepStrictEqual(this.prefix, '/baz')
         socket.send('hello client')
-        t.teardown(() => socket.terminate())
+        t.after(() => socket.terminate())
 
         socket.once('message', (chunk) => {
-          t.equal(chunk.toString(), 'hello server')
+          t.assert.deepStrictEqual(chunk.toString(), 'hello server')
+          end()
         })
       })
       next()
@@ -31,36 +32,37 @@ test('Should expose a websocket on prefixed route', t => {
   )
 
   fastify.listen({ port: 0 }, err => {
-    t.error(err)
+    t.assert.ifError(err)
     const ws = new WebSocket('ws://localhost:' + (fastify.server.address()).port + '/baz/echo')
     const client = WebSocket.createWebSocketStream(ws, { encoding: 'utf8' })
-    t.teardown(client.destroy.bind(client))
+    t.after(() => client.destroy())
 
     client.setEncoding('utf8')
     client.write('hello server')
 
     client.once('data', chunk => {
-      t.equal(chunk, 'hello client')
+      t.assert.deepStrictEqual(chunk, 'hello client')
       client.end()
     })
   })
 })
 
-test('Should expose a websocket on prefixed route with /', t => {
+test('Should expose a websocket on prefixed route with /', (t, end) => {
   t.plan(3)
   const fastify = Fastify()
 
-  t.teardown(() => fastify.close())
+  t.after(() => fastify.close())
 
   fastify.register(fastifyWebsocket)
   fastify.register(
     function (instance, _opts, next) {
       instance.get('/', { websocket: true }, (socket) => {
         socket.send('hello client')
-        t.teardown(() => socket.terminate())
+        t.after(() => socket.terminate())
 
         socket.once('message', (chunk) => {
-          t.equal(chunk.toString(), 'hello server')
+          t.assert.deepStrictEqual(chunk.toString(), 'hello server')
+          end()
         })
       })
       next()
@@ -69,26 +71,26 @@ test('Should expose a websocket on prefixed route with /', t => {
   )
 
   fastify.listen({ port: 0 }, err => {
-    t.error(err)
+    t.assert.ifError(err)
     const ws = new WebSocket('ws://localhost:' + (fastify.server.address()).port + '/baz')
     const client = WebSocket.createWebSocketStream(ws, { encoding: 'utf8' })
-    t.teardown(client.destroy.bind(client))
+    t.after(() => client.destroy())
 
     client.setEncoding('utf8')
     client.write('hello server')
 
     client.once('data', chunk => {
-      t.equal(chunk, 'hello client')
+      t.assert.deepStrictEqual(chunk, 'hello client')
       client.end()
     })
   })
 })
 
-test('Should expose websocket and http route', t => {
+test('Should expose websocket and http route', (t, end) => {
   t.plan(4)
   const fastify = Fastify()
 
-  t.teardown(() => fastify.close())
+  t.after(() => fastify.close())
 
   fastify.register(fastifyWebsocket)
   fastify.register(
@@ -101,10 +103,10 @@ test('Should expose websocket and http route', t => {
         },
         wsHandler: (socket) => {
           socket.send('hello client')
-          t.teardown(() => socket.terminate())
+          t.after(() => socket.terminate())
 
           socket.once('message', (chunk) => {
-            t.equal(chunk.toString(), 'hello server')
+            t.assert.deepStrictEqual(chunk.toString(), 'hello server')
           })
         }
       })
@@ -114,17 +116,17 @@ test('Should expose websocket and http route', t => {
   )
 
   fastify.listen({ port: 0 }, err => {
-    t.error(err)
+    t.assert.ifError(err)
     const url = '//localhost:' + (fastify.server.address()).port + '/baz/echo'
     const ws = new WebSocket('ws:' + url)
     const client = WebSocket.createWebSocketStream(ws, { encoding: 'utf8' })
-    t.teardown(client.destroy.bind(client))
+    t.after(() => client.destroy())
 
     client.setEncoding('utf8')
     client.write('hello server')
 
     client.once('data', chunk => {
-      t.equal(chunk, 'hello client')
+      t.assert.deepStrictEqual(chunk, 'hello client')
       client.end()
     })
     get('http:' + url, function (response) {
@@ -137,17 +139,18 @@ test('Should expose websocket and http route', t => {
 
       // The whole response has been received. Print out the result.
       response.on('end', () => {
-        t.equal(data, '{"hello":"world"}')
+        t.assert.deepStrictEqual(data, '{"hello":"world"}')
+        end()
       })
     })
   })
 })
 
-test('Should close on unregistered path (with no wildcard route websocket handler defined)', t => {
+test('Should close on unregistered path (with no wildcard route websocket handler defined)', (t, end) => {
   t.plan(2)
   const fastify = Fastify()
 
-  t.teardown(() => fastify.close())
+  t.after(() => fastify.close())
 
   fastify
     .register(fastifyWebsocket)
@@ -165,26 +168,27 @@ test('Should close on unregistered path (with no wildcard route websocket handle
           }
         })
 
-        t.teardown(() => socket.terminate())
+        t.after(() => socket.terminate())
       })
     })
 
   fastify.listen({ port: 0 }, err => {
-    t.error(err)
+    t.assert.ifError(err)
     const ws = new WebSocket('ws://localhost:' + (fastify.server.address()).port)
     const client = WebSocket.createWebSocketStream(ws, { encoding: 'utf8' })
-    t.teardown(client.destroy.bind(client))
+    t.after(() => client.destroy())
     ws.on('close', () => {
-      t.pass()
+      t.assert.ok(true)
+      end()
     })
   })
 })
 
-test('Should use wildcard websocket route when (with a normal http wildcard route defined as well)', t => {
+test('Should use wildcard websocket route when (with a normal http wildcard route defined as well)', (t, end) => {
   t.plan(2)
   const fastify = Fastify()
 
-  t.teardown(() => fastify.close())
+  t.after(() => fastify.close())
 
   fastify
     .register(fastifyWebsocket)
@@ -197,7 +201,7 @@ test('Should use wildcard websocket route when (with a normal http wildcard rout
         },
         wsHandler: (socket) => {
           socket.send('hello client')
-          t.teardown(() => socket.terminate())
+          t.after(() => socket.terminate())
 
           socket.once('message', () => {
             socket.close()
@@ -207,23 +211,24 @@ test('Should use wildcard websocket route when (with a normal http wildcard rout
     })
 
   fastify.listen({ port: 0 }, err => {
-    t.error(err)
+    t.assert.ifError(err)
     const ws = new WebSocket('ws://localhost:' + (fastify.server.address()).port)
     const client = WebSocket.createWebSocketStream(ws, { encoding: 'utf8' })
-    t.teardown(client.destroy.bind(client))
+    t.after(() => client.destroy())
 
     client.once('data', chunk => {
-      t.equal(chunk, 'hello client')
+      t.assert.deepStrictEqual(chunk, 'hello client')
       client.end()
+      end()
     })
   })
 })
 
-test('Should call wildcard route handler on unregistered path', t => {
+test('Should call wildcard route handler on unregistered path', (t, end) => {
   t.plan(3)
   const fastify = Fastify()
 
-  t.teardown(() => fastify.close())
+  t.after(() => fastify.close())
 
   fastify
     .register(fastifyWebsocket)
@@ -236,7 +241,7 @@ test('Should call wildcard route handler on unregistered path', t => {
             socket.send(err.message)
           }
         })
-        t.teardown(() => socket.terminate())
+        t.after(() => socket.terminate())
       })
     })
 
@@ -249,14 +254,14 @@ test('Should call wildcard route handler on unregistered path', t => {
       }
     })
 
-    t.teardown(() => socket.terminate())
+    t.after(() => socket.terminate())
   })
 
   fastify.listen({ port: 0 }, err => {
-    t.error(err)
+    t.assert.ifError(err)
     const ws = new WebSocket('ws://localhost:' + (fastify.server.address()).port)
     const client = WebSocket.createWebSocketStream(ws, { encoding: 'utf8' })
-    t.teardown(client.destroy.bind(client))
+    t.after(() => client.destroy())
 
     ws.on('open', () => {
       ws.send('hi from client')
@@ -264,20 +269,21 @@ test('Should call wildcard route handler on unregistered path', t => {
     })
 
     ws.on('message', message => {
-      t.equal(message.toString(), 'hi from wildcard route handler')
+      t.assert.deepStrictEqual(message.toString(), 'hi from wildcard route handler')
     })
 
     ws.on('close', () => {
-      t.pass()
+      t.assert.ok(true)
+      end()
     })
   })
 })
 
-test('Should invoke the correct handler depending on the headers', t => {
+test('Should invoke the correct handler depending on the headers', (t, end) => {
   t.plan(4)
   const fastify = Fastify()
 
-  t.teardown(() => fastify.close())
+  t.after(() => fastify.close())
 
   fastify.register(fastifyWebsocket)
   fastify.register(async function () {
@@ -289,97 +295,98 @@ test('Should invoke the correct handler depending on the headers', t => {
       },
       wsHandler: (socket) => {
         socket.send('hi from wsHandler')
-        t.teardown(() => socket.terminate())
+        t.after(() => socket.terminate())
       }
     })
   })
 
   fastify.listen({ port: 0 }, err => {
-    t.error(err)
+    t.assert.ifError(err)
 
     const port = fastify.server.address().port
 
     const httpClient = net.createConnection({ port }, () => {
       httpClient.write('GET / HTTP/1.1\r\nHOST: localhost\r\n\r\n')
       httpClient.once('data', data => {
-        t.match(data.toString(), /hi from handler/i)
+        t.assert.match(data.toString(), /hi from handler/i)
         httpClient.end()
+        end()
       })
     })
 
     const wsClient = net.createConnection({ port }, () => {
       wsClient.write('GET / HTTP/1.1\r\nConnection: upgrade\r\nUpgrade: websocket\r\nSec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\nSec-WebSocket-Version: 13\r\n\r\n')
       wsClient.once('data', data => {
-        t.match(data.toString(), /hi from wsHandler/i)
-        wsClient.end(() => { t.pass() })
+        t.assert.match(data.toString(), /hi from wsHandler/i)
+        wsClient.end(() => { t.assert.ok(true) })
       })
     })
   })
 })
 
-test('Should call the wildcard handler if a no other non-websocket route with path exists', t => {
+test('Should call the wildcard handler if a no other non-websocket route with path exists', (t, end) => {
   const fastify = Fastify()
-  t.teardown(() => fastify.close())
+  t.after(() => fastify.close())
 
   fastify.register(fastifyWebsocket)
 
   fastify.register(async function (fastify) {
     fastify.get('/*', { websocket: true }, (socket) => {
-      t.ok('called', 'wildcard handler')
+      t.assert.ok('called', 'wildcard handler')
       socket.close()
-      t.teardown(() => socket.terminate())
+      t.after(() => socket.terminate())
     })
 
     fastify.get('/http', (_request, reply) => {
-      t.fail('Should not call http handler')
+      t.assert.fail('Should not call http handler')
       reply.send('http route')
     })
   })
 
   fastify.listen({ port: 0 }, err => {
-    t.error(err)
+    t.assert.ifError(err)
     const ws = new WebSocket('ws://localhost:' + (fastify.server.address()).port + '/http2')
     const client = WebSocket.createWebSocketStream(ws, { encoding: 'utf8' })
-    t.teardown(client.destroy.bind(client))
+    t.after(() => client.destroy())
 
     client.setEncoding('utf8')
-    client.end(() => { t.end() })
+    client.end(end)
   })
 })
 
-test('Should close the connection if a non-websocket route with path exists', t => {
+test('Should close the connection if a non-websocket route with path exists', (t, end) => {
   t.plan(2)
   const fastify = Fastify()
-  t.teardown(() => fastify.close())
+  t.after(() => fastify.close())
 
   fastify.register(fastifyWebsocket)
   fastify.register(async function (fastify) {
     fastify.get('/*', { websocket: true }, (socket) => {
-      t.fail('called', 'wildcard handler')
-      t.teardown(() => socket.terminate())
+      t.assert.fail('called', 'wildcard handler')
+      t.after(() => socket.terminate())
     })
 
     fastify.get('/http', (_request, reply) => {
-      t.fail('Should not call /http handler')
+      t.assert.fail('Should not call /http handler')
       reply.send('http route')
     })
   })
 
   fastify.listen({ port: 0 }, err => {
-    t.error(err)
+    t.assert.ifError(err)
     const ws = new WebSocket('ws://localhost:' + (fastify.server.address()).port + '/http')
     ws.on('close', (code) => {
-      t.equal(code, 1005, 'closed websocket')
-      t.end()
+      t.assert.deepStrictEqual(code, 1005, 'closed websocket')
+      end()
     })
   })
 })
 
-test('Should throw on wrong HTTP method', t => {
+test('Should throw on wrong HTTP method', (t, end) => {
   t.plan(2)
   const fastify = Fastify()
 
-  t.teardown(() => fastify.close())
+  t.after(() => fastify.close())
 
   fastify.register(fastifyWebsocket)
   fastify.register(async function (fastify) {
@@ -391,18 +398,19 @@ test('Should throw on wrong HTTP method', t => {
           socket.send(err.message)
         }
       })
-      t.teardown(() => socket.terminate())
+      t.after(() => socket.terminate())
     })
 
     fastify.get('/http', (_request, reply) => {
-      t.fail('Should not call /http handler')
+      t.assert.fail('Should not call /http handler')
       reply.send('http route')
     })
   })
 
   fastify.listen({ port: 0 }, (err) => {
-    t.ok(err)
-    t.equal(err.message, 'websocket handler can only be declared in GET method')
+    t.assert.ok(err)
+    t.assert.deepStrictEqual(err.message, 'websocket handler can only be declared in GET method')
+    end()
   })
 })
 
@@ -410,7 +418,7 @@ test('Should throw on invalid wsHandler', async t => {
   t.plan(1)
   const fastify = Fastify()
 
-  t.teardown(() => fastify.close())
+  t.after(() => fastify.close())
 
   await fastify.register(fastifyWebsocket)
   try {
@@ -423,15 +431,15 @@ test('Should throw on invalid wsHandler', async t => {
       wsHandler: 'hello'
     }, { prefix: '/baz' })
   } catch (err) {
-    t.equal(err.message, 'invalid wsHandler function')
+    t.assert.deepStrictEqual(err.message, 'invalid wsHandler function')
   }
 })
 
-test('Should open on registered path', t => {
+test('Should open on registered path', (t, end) => {
   t.plan(2)
   const fastify = Fastify()
 
-  t.teardown(() => fastify.close())
+  t.after(() => fastify.close())
 
   fastify.register(fastifyWebsocket)
 
@@ -445,54 +453,56 @@ test('Should open on registered path', t => {
         }
       })
 
-      t.teardown(() => socket.terminate())
+      t.after(() => socket.terminate())
     })
   })
 
   fastify.listen({ port: 0 }, err => {
-    t.error(err)
+    t.assert.ifError(err)
     const ws = new WebSocket('ws://localhost:' + (fastify.server.address()).port + '/echo')
     ws.on('open', () => {
-      t.pass()
+      t.assert.ok(true)
       client.end()
+      end()
     })
 
     const client = WebSocket.createWebSocketStream(ws, { encoding: 'utf8' })
-    t.teardown(client.destroy.bind(client))
+    t.after(() => client.destroy())
   })
 })
 
-test('Should send message and close', t => {
+test('Should send message and close', (t, end) => {
   t.plan(5)
   const fastify = Fastify()
 
-  t.teardown(() => fastify.close())
+  t.after(() => fastify.close())
 
   fastify.register(fastifyWebsocket)
 
   fastify.register(async function (fastify) {
     fastify.get('/', { websocket: true }, (socket) => {
       socket.on('message', message => {
-        t.equal(message.toString(), 'hi from client')
+        t.assert.deepStrictEqual(message.toString(), 'hi from client')
         socket.send('hi from server')
       })
 
       socket.on('close', () => {
-        t.pass()
+        t.assert.ok(true)
+        end()
       })
 
-      t.teardown(() => socket.terminate())
+      t.after(() => socket.terminate())
     })
   })
 
   fastify.listen({ port: 0 }, err => {
-    t.error(err)
+    t.assert.ifError(err)
     const ws = new WebSocket('ws://localhost:' + (fastify.server.address()).port + '/')
     const client = WebSocket.createWebSocketStream(ws, { encoding: 'utf8' })
-    t.teardown(client.destroy.bind(client))
+    t.after(() => client.destroy())
 
     ws.on('message', message => {
-      t.equal(message.toString(), 'hi from server')
+      t.assert.deepStrictEqual(message.toString(), 'hi from server')
     })
 
     ws.on('open', () => {
@@ -501,29 +511,29 @@ test('Should send message and close', t => {
     })
 
     ws.on('close', () => {
-      t.pass()
+      t.assert.ok(true)
     })
   })
 })
 
-test('Should return 404 on http request', t => {
+test('Should return 404 on http request', (t, end) => {
   const fastify = Fastify()
 
-  t.teardown(() => fastify.close())
+  t.after(() => fastify.close())
 
   fastify.register(fastifyWebsocket)
   fastify.register(async function (fastify) {
     fastify.get('/', { websocket: true }, (socket) => {
       socket.on('message', message => {
-        t.equal(message.toString(), 'hi from client')
+        t.assert.deepStrictEqual(message.toString(), 'hi from client')
         socket.send('hi from server')
       })
 
       socket.on('close', () => {
-        t.pass()
+        t.assert.ok(true)
       })
 
-      t.teardown(() => socket.terminate())
+      t.after(() => socket.terminate())
     })
   })
 
@@ -531,28 +541,28 @@ test('Should return 404 on http request', t => {
     method: 'GET',
     url: '/'
   }).then((response) => {
-    t.equal(response.payload, '')
-    t.equal(response.statusCode, 404)
-    t.end()
+    t.assert.deepStrictEqual(response.payload, '')
+    t.assert.deepStrictEqual(response.statusCode, 404)
+    end()
   })
 })
 
-test('Should pass route params to per-route handlers', t => {
+test('Should pass route params to per-route handlers', (t, end) => {
   const fastify = Fastify()
 
-  t.teardown(() => fastify.close())
+  t.after(() => fastify.close())
 
   fastify.register(fastifyWebsocket)
   fastify.register(async function (fastify) {
     fastify.get('/ws', { websocket: true }, (socket, request) => {
       const params = request.params
-      t.equal(Object.keys(params).length, 0, 'params are empty')
+      t.assert.deepStrictEqual(Object.keys(params).length, 0, 'params are empty')
       socket.send('empty')
       socket.close()
     })
     fastify.get('/ws/:id', { websocket: true }, (socket, request) => {
       const params = request.params
-      t.equal(params.id, 'foo', 'params are correct')
+      t.assert.deepStrictEqual(params.id, 'foo', 'params are correct')
       socket.send(params.id)
       socket.close()
     })
@@ -560,7 +570,7 @@ test('Should pass route params to per-route handlers', t => {
 
   fastify.listen({ port: 0 }, err => {
     let pending = 2
-    t.error(err)
+    t.assert.ifError(err)
     const ws = new WebSocket(
       'ws://localhost:' + (fastify.server.address()).port + '/ws/foo'
     )
@@ -569,29 +579,29 @@ test('Should pass route params to per-route handlers', t => {
       'ws://localhost:' + (fastify.server.address()).port + '/ws'
     )
     const client2 = WebSocket.createWebSocketStream(ws2, { encoding: 'utf8' })
-    t.teardown(client.destroy.bind(client))
-    t.teardown(client2.destroy.bind(client2))
+    t.after(() => client.destroy())
+    t.after(() => client2.destroy())
 
     client.setEncoding('utf8')
     client2.setEncoding('utf8')
 
     client.once('data', chunk => {
-      t.equal(chunk, 'foo')
+      t.assert.deepStrictEqual(chunk, 'foo')
       client.end()
-      if (--pending === 0) t.end()
+      if (--pending === 0) end()
     })
     client2.once('data', chunk => {
-      t.equal(chunk, 'empty')
+      t.assert.deepStrictEqual(chunk, 'empty')
       client2.end()
-      if (--pending === 0) t.end()
+      if (--pending === 0) end()
     })
   })
 })
 
-test('Should not throw error when register empty get with prefix', t => {
+test('Should not throw error when register empty get with prefix', (t, end) => {
   const fastify = Fastify()
 
-  t.teardown(() => fastify.close())
+  t.after(() => fastify.close())
 
   fastify.register(fastifyWebsocket)
 
@@ -599,7 +609,7 @@ test('Should not throw error when register empty get with prefix', t => {
     function (instance, _opts, next) {
       instance.get('/', { websocket: true }, (socket) => {
         socket.on('message', message => {
-          t.equal(message.toString(), 'hi from client')
+          t.assert.deepStrictEqual(message.toString(), 'hi from client')
           socket.send('hi from server')
         })
       })
@@ -609,115 +619,115 @@ test('Should not throw error when register empty get with prefix', t => {
   )
 
   fastify.listen({ port: 0 }, err => {
-    if (err) t.error(err)
+    if (err) t.assert.ifError(err)
 
     const ws = new WebSocket(
       'ws://localhost:' + fastify.server.address().port + '/baz/'
     )
 
     ws.on('open', () => {
-      t.pass('Done')
+      t.assert.ok('Done')
       ws.close()
-      t.end()
+      end()
     })
   })
 })
 
-test('Should expose fastify instance to websocket per-route handler', t => {
+test('Should expose fastify instance to websocket per-route handler', (t, end) => {
   const fastify = Fastify()
 
-  t.teardown(() => fastify.close())
+  t.after(() => fastify.close())
 
   fastify.register(fastifyWebsocket)
   fastify.register(async function (fastify) {
     fastify.get('/ws', { websocket: true }, function wsHandler (socket) {
-      t.equal(this, fastify, 'this is bound to fastify server')
+      t.assert.deepStrictEqual(this, fastify, 'this is bound to fastify server')
       socket.send('empty')
       socket.close()
     })
   })
 
   fastify.listen({ port: 0 }, err => {
-    t.error(err)
+    t.assert.ifError(err)
     const ws = new WebSocket(
       'ws://localhost:' + (fastify.server.address()).port + '/ws'
     )
     const client = WebSocket.createWebSocketStream(ws, { encoding: 'utf8' })
-    t.teardown(client.destroy.bind(client))
+    t.after(() => client.destroy())
 
     client.setEncoding('utf8')
 
     client.once('data', chunk => {
-      t.equal(chunk, 'empty')
+      t.assert.deepStrictEqual(chunk, 'empty')
       client.end()
-      t.end()
+      end()
     })
   })
 })
 
-test('Should have access to decorators in per-route handler', t => {
+test('Should have access to decorators in per-route handler', (t, end) => {
   const fastify = Fastify()
 
-  t.teardown(() => fastify.close())
+  t.after(() => fastify.close())
 
   fastify.decorateRequest('str', 'it works!')
   fastify.register(fastifyWebsocket)
   fastify.register(async function (fastify) {
     fastify.get('/ws', { websocket: true }, function wsHandler (socket, request) {
-      t.equal(request.str, 'it works!', 'decorator is accessible')
+      t.assert.deepStrictEqual(request.str, 'it works!', 'decorator is accessible')
       socket.send('empty')
       socket.close()
     })
   })
 
   fastify.listen({ port: 0 }, err => {
-    t.error(err)
+    t.assert.ifError(err)
     const ws = new WebSocket('ws://localhost:' + (fastify.server.address()).port + '/ws')
     const client = WebSocket.createWebSocketStream(ws, { encoding: 'utf8' })
-    t.teardown(client.destroy.bind(client))
+    t.after(() => client.destroy())
 
     client.once('data', chunk => {
-      t.equal(chunk, 'empty')
+      t.assert.deepStrictEqual(chunk, 'empty')
       client.end()
-      t.end()
+      end()
     })
   })
 })
 
-test('should call `destroy` when exception is thrown inside async handler', t => {
+test('should call `destroy` when exception is thrown inside async handler', (t, end) => {
   t.plan(2)
   const fastify = Fastify()
 
-  t.teardown(() => fastify.close())
+  t.after(() => fastify.close())
 
   fastify.register(fastifyWebsocket)
   fastify.register(async function (fastify) {
     fastify.get('/ws', { websocket: true }, async function wsHandler (socket) {
       socket.on('close', code => {
-        t.equal(code, 1006)
-        t.end()
+        t.assert.deepStrictEqual(code, 1006)
+        end()
       })
       throw new Error('something wrong')
     })
   })
 
   fastify.listen({ port: 0 }, err => {
-    t.error(err)
+    t.assert.ifError(err)
     const ws = new WebSocket(
       'ws://localhost:' + (fastify.server.address()).port + '/ws'
     )
     const client = WebSocket.createWebSocketStream(ws, { encoding: 'utf8' })
 
     client.on('error', (_) => { })
-    t.teardown(client.destroy.bind(client))
+    t.after(() => client.destroy())
   })
 })
 
-test('should call default non websocket fastify route when no match is found', t => {
+test('should call default non websocket fastify route when no match is found', (t, end) => {
   t.plan(2)
   const fastify = Fastify()
 
-  t.teardown(() => fastify.close())
+  t.after(() => fastify.close())
 
   fastify.register(fastifyWebsocket)
   fastify.register(async function (fastify) {
@@ -727,19 +737,19 @@ test('should call default non websocket fastify route when no match is found', t
   })
 
   fastify.listen({ port: 0 }, err => {
-    t.error(err)
+    t.assert.ifError(err)
     get('http://localhost:' + (fastify.server.address()).port + '/wrong-route', function (response) {
-      t.equal(response.statusCode, 404)
-      t.end()
+      t.assert.deepStrictEqual(response.statusCode, 404)
+      end()
     })
   })
 })
 
-test('register a non websocket route', t => {
+test('register a non websocket route', (t, end) => {
   t.plan(2)
   const fastify = Fastify()
 
-  t.teardown(() => fastify.close())
+  t.after(() => fastify.close())
 
   fastify.register(fastifyWebsocket)
   fastify.register(async function (fastify) {
@@ -749,7 +759,7 @@ test('register a non websocket route', t => {
   })
 
   fastify.listen({ port: 0 }, err => {
-    t.error(err)
+    t.assert.ifError(err)
     get('http://localhost:' + (fastify.server.address()).port + '/ws', function (response) {
       let data = ''
 
@@ -758,8 +768,8 @@ test('register a non websocket route', t => {
       })
 
       response.on('end', () => {
-        t.equal(data, '{"hello":"world"}')
-        t.end()
+        t.assert.deepStrictEqual(data, '{"hello":"world"}')
+        end()
       })
     })
   })

From 9400275bdd6729a46e6edf15cafa7c898f5de201 Mon Sep 17 00:00:00 2001
From: Matteo Pietro Dazzi <matteopietro.dazzi@gmail.com>
Date: Wed, 12 Feb 2025 20:00:19 +0100
Subject: [PATCH 5/9] chore: migrate router

---
 test/inject.test.js | 2 +-
 test/router.test.js | 6 ++++--
 2 files changed, 5 insertions(+), 3 deletions(-)

diff --git a/test/inject.test.js b/test/inject.test.js
index b0c659f..5c4098a 100644
--- a/test/inject.test.js
+++ b/test/inject.test.js
@@ -130,5 +130,5 @@ test('rejects if the websocket is not upgraded', async (t) => {
     })
 
   await fastify.ready()
-  t.assert.rejects(fastify.injectWS('/'), 'Unexpected server response: 401')
+  await t.assert.rejects(fastify.injectWS('/'), new Error('Unexpected server response: 401'))
 })
diff --git a/test/router.test.js b/test/router.test.js
index 2464807..40537b2 100644
--- a/test/router.test.js
+++ b/test/router.test.js
@@ -310,7 +310,6 @@ test('Should invoke the correct handler depending on the headers', (t, end) => {
       httpClient.once('data', data => {
         t.assert.match(data.toString(), /hi from handler/i)
         httpClient.end()
-        end()
       })
     })
 
@@ -318,7 +317,10 @@ test('Should invoke the correct handler depending on the headers', (t, end) => {
       wsClient.write('GET / HTTP/1.1\r\nConnection: upgrade\r\nUpgrade: websocket\r\nSec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\nSec-WebSocket-Version: 13\r\n\r\n')
       wsClient.once('data', data => {
         t.assert.match(data.toString(), /hi from wsHandler/i)
-        wsClient.end(() => { t.assert.ok(true) })
+        wsClient.end(() => {
+          t.assert.ok(true)
+          end()
+        })
       })
     })
   })

From 1b4a5ca74ce8ccf49d64febaa1e1611550ba9346 Mon Sep 17 00:00:00 2001
From: Matteo Pietro Dazzi <matteopietro.dazzi@gmail.com>
Date: Wed, 12 Feb 2025 20:01:26 +0100
Subject: [PATCH 6/9] fix: router migration

---
 test/router.test.js | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/test/router.test.js b/test/router.test.js
index 40537b2..2c7d48a 100644
--- a/test/router.test.js
+++ b/test/router.test.js
@@ -319,7 +319,7 @@ test('Should invoke the correct handler depending on the headers', (t, end) => {
         t.assert.match(data.toString(), /hi from wsHandler/i)
         wsClient.end(() => {
           t.assert.ok(true)
-          end()
+          setTimeout(end, 100)
         })
       })
     })

From 5a35aef31d3e8dc168df78093ace2794b6ed7541 Mon Sep 17 00:00:00 2001
From: Matteo Pietro Dazzi <matteopietro.dazzi@gmail.com>
Date: Thu, 13 Feb 2025 20:52:17 +0100
Subject: [PATCH 7/9] fix: readme content

---
 README.md | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/README.md b/README.md
index ab4eed3..a038417 100644
--- a/README.md
+++ b/README.md
@@ -330,7 +330,7 @@ module.exports = App
 ```js
 'use strict'
 
-const { test } = require('tap')
+const { test } = require('node:test')
 const Fastify = require('fastify')
 const App = require('./app.js')
 
@@ -351,7 +351,7 @@ test('connect to /', async (t) => {
   })
   ws.send('hi from client')
 
-  t.assert(await promise, 'hi from server')
+  t.assert.deepStrictEqual(await promise, 'hi from server')
   // Remember to close the ws at the end
   ws.terminate()
 })

From a35440add7dacd9a0b057208cc5c5cffb31a36de Mon Sep 17 00:00:00 2001
From: Matteo Pietro Dazzi <matteopietro.dazzi@gmail.com>
Date: Tue, 18 Feb 2025 19:17:51 +0100
Subject: [PATCH 8/9] fix: close

---
 test/router.test.js | 19 +++++++++++++++++--
 1 file changed, 17 insertions(+), 2 deletions(-)

diff --git a/test/router.test.js b/test/router.test.js
index 2c7d48a..2b51d1f 100644
--- a/test/router.test.js
+++ b/test/router.test.js
@@ -7,6 +7,15 @@ const fastifyWebsocket = require('..')
 const WebSocket = require('ws')
 const get = require('node:http').get
 
+const withResolvers = function () {
+  let promiseResolve, promiseReject
+  const promise = new Promise((resolve, reject) => {
+    promiseResolve = resolve
+    promiseReject = reject
+  })
+  return { promise, resolve: promiseResolve, reject: promiseReject }
+}
+
 test('Should expose a websocket on prefixed route', (t, end) => {
   t.plan(4)
   const fastify = Fastify()
@@ -473,7 +482,7 @@ test('Should open on registered path', (t, end) => {
   })
 })
 
-test('Should send message and close', (t, end) => {
+test('Should send message and close', (t) => {
   t.plan(5)
   const fastify = Fastify()
 
@@ -481,6 +490,9 @@ test('Should send message and close', (t, end) => {
 
   fastify.register(fastifyWebsocket)
 
+  const { promise: clientPromise, resolve: clientResolve } = withResolvers()
+  const { promise: serverPromise, resolve: serverResolve } = withResolvers()
+
   fastify.register(async function (fastify) {
     fastify.get('/', { websocket: true }, (socket) => {
       socket.on('message', message => {
@@ -490,7 +502,7 @@ test('Should send message and close', (t, end) => {
 
       socket.on('close', () => {
         t.assert.ok(true)
-        end()
+        serverResolve()
       })
 
       t.after(() => socket.terminate())
@@ -514,8 +526,11 @@ test('Should send message and close', (t, end) => {
 
     ws.on('close', () => {
       t.assert.ok(true)
+      clientResolve()
     })
   })
+
+  return Promise.all([clientPromise, serverPromise])
 })
 
 test('Should return 404 on http request', (t, end) => {

From 441e8e5f6d0b555fb0e8231fd208fabe142cefdb Mon Sep 17 00:00:00 2001
From: Matteo Pietro Dazzi <matteopietro.dazzi@gmail.com>
Date: Sat, 1 Mar 2025 10:17:27 +0100
Subject: [PATCH 9/9] fix: use promises

---
 test/router.test.js | 10 ++++++++--
 1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/test/router.test.js b/test/router.test.js
index 2b51d1f..0d15c31 100644
--- a/test/router.test.js
+++ b/test/router.test.js
@@ -95,12 +95,15 @@ test('Should expose a websocket on prefixed route with /', (t, end) => {
   })
 })
 
-test('Should expose websocket and http route', (t, end) => {
+test('Should expose websocket and http route', (t) => {
   t.plan(4)
   const fastify = Fastify()
 
   t.after(() => fastify.close())
 
+  const { promise: clientPromise, resolve: clientResolve } = withResolvers()
+  const { promise: serverPromise, resolve: serverResolve } = withResolvers()
+
   fastify.register(fastifyWebsocket)
   fastify.register(
     function (instance, _opts, next) {
@@ -116,6 +119,7 @@ test('Should expose websocket and http route', (t, end) => {
 
           socket.once('message', (chunk) => {
             t.assert.deepStrictEqual(chunk.toString(), 'hello server')
+            clientResolve()
           })
         }
       })
@@ -149,10 +153,12 @@ test('Should expose websocket and http route', (t, end) => {
       // The whole response has been received. Print out the result.
       response.on('end', () => {
         t.assert.deepStrictEqual(data, '{"hello":"world"}')
-        end()
+        serverResolve()
       })
     })
   })
+
+  return Promise.all([clientPromise, serverPromise])
 })
 
 test('Should close on unregistered path (with no wildcard route websocket handler defined)', (t, end) => {