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) => {