From 594841617d116c830609cd8f61eabcdab9d59cb1 Mon Sep 17 00:00:00 2001 From: Damien Arrachequesne Date: Mon, 22 Dec 2025 14:16:19 +0100 Subject: [PATCH] test(redis-streams-emitter): migrate to Node.js test runner We should eventually be able to replace: - mocha and nyc with Node.js built-in test runner (`node:test`) - expect.js with Node.js built-in assertion library (`node:assert`) --- .../package.json | 10 +- .../test/index.ts | 211 ++++++++++-------- .../test/util.ts | 14 +- 3 files changed, 128 insertions(+), 107 deletions(-) diff --git a/packages/socket.io-redis-streams-emitter/package.json b/packages/socket.io-redis-streams-emitter/package.json index 20b0d5d0..ebc5d6fc 100644 --- a/packages/socket.io-redis-streams-emitter/package.json +++ b/packages/socket.io-redis-streams-emitter/package.json @@ -19,11 +19,11 @@ "format:fix": "prettier --parser typescript --write 'lib/**/*.ts' 'test/**/*.ts'", "prepack": "npm run compile", "test": "npm run format:check && npm run compile && npm run test:redis-standalone && npm run test:ioredis-standalone", - "test:redis-standalone": "nyc mocha --import=tsx test/**/*.ts", - "test:redis-cluster": "REDIS_CLUSTER=1 mocha --import=tsx test/**/*.ts", - "test:ioredis-standalone": "REDIS_LIB=ioredis mocha --import=tsx test/**/*.ts", - "test:ioredis-cluster": "REDIS_LIB=ioredis REDIS_CLUSTER=1 mocha --import=tsx test/**/*.ts", - "test:valkey-standalone": "VALKEY=1 mocha --import=tsx test/**/*.ts" + "test:redis-standalone": "tsx --test", + "test:redis-cluster": "REDIS_CLUSTER=1 npm run test:redis-standalone", + "test:ioredis-standalone": "REDIS_LIB=ioredis npm run test:redis-standalone", + "test:ioredis-cluster": "REDIS_LIB=ioredis REDIS_CLUSTER=1 npm run test:redis-standalone", + "test:valkey-standalone": "VALKEY=1 npm run test:redis-standalone" }, "dependencies": { "@msgpack/msgpack": "~2.8.0", diff --git a/packages/socket.io-redis-streams-emitter/test/index.ts b/packages/socket.io-redis-streams-emitter/test/index.ts index c2f30271..3d01ee7c 100644 --- a/packages/socket.io-redis-streams-emitter/test/index.ts +++ b/packages/socket.io-redis-streams-emitter/test/index.ts @@ -1,15 +1,16 @@ +import { describe, it, beforeEach, afterEach } from "node:test"; +import * as assert from "node:assert"; import { type Server, type Socket as ServerSocket } from "socket.io"; import { type Socket as ClientSocket } from "socket.io-client"; -import expect = require("expect.js"); import { times, sleep, setup, initRedisClient } from "./util"; import { Emitter } from "../lib"; const PROPAGATION_DELAY_IN_MS = 100; describe("@socket.io/redis-streams-emitter", () => { - let servers: Server[], - serverSockets: ServerSocket[], - clientSockets: ClientSocket[], + let servers: [Server, Server, Server], + serverSockets: [ServerSocket, ServerSocket, ServerSocket], + clientSockets: [ClientSocket, ClientSocket, ClientSocket], cleanup: () => void, emitter: Emitter; @@ -30,80 +31,88 @@ describe("@socket.io/redis-streams-emitter", () => { afterEach(() => cleanup()); describe("broadcast", function () { - it("broadcasts to all clients", (done) => { - const partialDone = times(3, done); + it("broadcasts to all clients", () => { + return new Promise((resolve) => { + const partialResolve = times(3, resolve); - clientSockets.forEach((clientSocket) => { - clientSocket.on("test", (arg1, arg2, arg3) => { - expect(arg1).to.eql(1); - expect(arg2).to.eql("2"); - expect(Buffer.isBuffer(arg3)).to.be(true); - partialDone(); + clientSockets.forEach((clientSocket) => { + clientSocket.on("test", (arg1, arg2, arg3) => { + assert.equal(arg1, 1); + assert.equal(arg2, "2"); + assert.ok(Buffer.isBuffer(arg3)); + partialResolve(); + }); }); - }); - emitter.emit("test", 1, "2", Buffer.from([3, 4])); + emitter.emit("test", 1, "2", Buffer.from([3, 4])); + }); }); - it("broadcasts to all clients in a namespace", (done) => { - const partialDone = times(3, () => { - servers.forEach((server) => server.of("/custom").adapter.close()); - done(); - }); + it("broadcasts to all clients in a namespace", () => { + return new Promise((resolve) => { + const partialResolve = times(3, () => { + servers.forEach((server) => server.of("/custom").adapter.close()); + resolve(); + }); - servers.forEach((server) => server.of("/custom")); + servers.forEach((server) => server.of("/custom")); - const onConnect = times(3, async () => { - await sleep(PROPAGATION_DELAY_IN_MS); + const onConnect = times(3, async () => { + await sleep(PROPAGATION_DELAY_IN_MS); - emitter.of("/custom").emit("test"); - }); + emitter.of("/custom").emit("test"); + }); - clientSockets.forEach((clientSocket) => { - const socket = clientSocket.io.socket("/custom"); - socket.on("connect", onConnect); - socket.on("test", () => { - socket.disconnect(); - partialDone(); + clientSockets.forEach((clientSocket) => { + const socket = clientSocket.io.socket("/custom"); + socket.on("connect", onConnect); + socket.on("test", () => { + socket.disconnect(); + partialResolve(); + }); }); }); }); - it("broadcasts to all clients in a room", (done) => { - serverSockets[1].join("room1"); + it("broadcasts to all clients in a room", () => { + return new Promise((resolve, reject) => { + serverSockets[1].join("room1"); - clientSockets[0].on("test", () => { - done(new Error("should not happen")); + clientSockets[0].on("test", () => { + reject("should not happen"); + }); + + clientSockets[1].on("test", () => { + resolve(); + }); + + clientSockets[2].on("test", () => { + reject("should not happen"); + }); + + emitter.to("room1").emit("test"); }); - - clientSockets[1].on("test", () => { - done(); - }); - - clientSockets[2].on("test", () => { - done(new Error("should not happen")); - }); - - emitter.to("room1").emit("test"); }); - it("broadcasts to all clients except in room", (done) => { - const partialDone = times(2, done); - serverSockets[1].join("room1"); + it("broadcasts to all clients except in room", () => { + return new Promise((resolve, reject) => { + const partialResolve = times(2, resolve); + serverSockets[1].join("room1"); - clientSockets[0].on("test", () => { - partialDone(); + clientSockets[0].on("test", () => { + partialResolve(); + }); + + clientSockets[1].on("test", () => { + reject("should not happen"); + }); + + clientSockets[2].on("test", () => { + partialResolve(); + }); + + emitter.of("/").except("room1").emit("test"); }); - - clientSockets[1].on("test", () => { - done(new Error("should not happen")); - }); - - clientSockets[2].on("test", () => { - partialDone(); - }); - - emitter.of("/").except("room1").emit("test"); }); }); @@ -113,9 +122,9 @@ describe("@socket.io/redis-streams-emitter", () => { await sleep(PROPAGATION_DELAY_IN_MS); - expect(serverSockets[0].rooms.has("room1")).to.be(true); - expect(serverSockets[1].rooms.has("room1")).to.be(true); - expect(serverSockets[2].rooms.has("room1")).to.be(true); + assert.ok(serverSockets[0].rooms.has("room1")); + assert.ok(serverSockets[1].rooms.has("room1")); + assert.ok(serverSockets[2].rooms.has("room1")); }); it("makes the matching socket instances join the specified room", async () => { @@ -126,9 +135,9 @@ describe("@socket.io/redis-streams-emitter", () => { await sleep(PROPAGATION_DELAY_IN_MS); - expect(serverSockets[0].rooms.has("room2")).to.be(true); - expect(serverSockets[1].rooms.has("room2")).to.be(false); - expect(serverSockets[2].rooms.has("room2")).to.be(true); + assert.ok(serverSockets[0].rooms.has("room2")); + assert.ok(serverSockets[1].rooms.has("room2") === false); + assert.ok(serverSockets[2].rooms.has("room2")); }); it("makes the given socket instance join the specified room", async () => { @@ -136,9 +145,9 @@ describe("@socket.io/redis-streams-emitter", () => { await sleep(PROPAGATION_DELAY_IN_MS); - expect(serverSockets[0].rooms.has("room3")).to.be(false); - expect(serverSockets[1].rooms.has("room3")).to.be(true); - expect(serverSockets[2].rooms.has("room3")).to.be(false); + assert.ok(serverSockets[0].rooms.has("room3") === false); + assert.ok(serverSockets[1].rooms.has("room3")); + assert.ok(serverSockets[2].rooms.has("room3") === false); }); }); @@ -151,9 +160,9 @@ describe("@socket.io/redis-streams-emitter", () => { await sleep(PROPAGATION_DELAY_IN_MS); - expect(serverSockets[0].rooms.has("room1")).to.be(false); - expect(serverSockets[1].rooms.has("room1")).to.be(false); - expect(serverSockets[2].rooms.has("room1")).to.be(false); + assert.ok(serverSockets[0].rooms.has("room1") === false); + assert.ok(serverSockets[1].rooms.has("room1") === false); + assert.ok(serverSockets[2].rooms.has("room1") === false); }); it("makes the matching socket instances leave the specified room", async () => { @@ -165,9 +174,9 @@ describe("@socket.io/redis-streams-emitter", () => { await sleep(PROPAGATION_DELAY_IN_MS); - expect(serverSockets[0].rooms.has("room2")).to.be(false); - expect(serverSockets[1].rooms.has("room2")).to.be(false); - expect(serverSockets[2].rooms.has("room2")).to.be(true); + assert.ok(serverSockets[0].rooms.has("room2") === false); + assert.ok(serverSockets[1].rooms.has("room2") === false); + assert.ok(serverSockets[2].rooms.has("room2")); }); it("makes the given socket instance leave the specified room", async () => { @@ -179,46 +188,50 @@ describe("@socket.io/redis-streams-emitter", () => { await sleep(PROPAGATION_DELAY_IN_MS); - expect(serverSockets[0].rooms.has("room3")).to.be(true); - expect(serverSockets[1].rooms.has("room3")).to.be(false); - expect(serverSockets[2].rooms.has("room3")).to.be(true); + assert.ok(serverSockets[0].rooms.has("room3")); + assert.ok(serverSockets[1].rooms.has("room1") === false); + assert.ok(serverSockets[2].rooms.has("room3")); }); }); describe("disconnectSockets", () => { - it("makes all socket instances disconnect", (done) => { - const partialDone = times(3, done); + it("makes all socket instances disconnect", () => { + return new Promise((resolve) => { + const partialResolve = times(3, resolve); - clientSockets.forEach((clientSocket) => { - clientSocket.on("disconnect", (reason) => { - expect(reason).to.eql("io server disconnect"); - partialDone(); + clientSockets.forEach((clientSocket) => { + clientSocket.on("disconnect", (reason) => { + assert.equal(reason, "io server disconnect"); + partialResolve(); + }); }); - }); - emitter.disconnectSockets(); + emitter.disconnectSockets(); + }); }); }); describe("serverSideEmit", () => { - it("sends an event to other server instances", (done) => { - const partialDone = times(3, done); + it("sends an event to other server instances", () => { + return new Promise((resolve) => { + const partialResolve = times(3, resolve); - emitter.serverSideEmit("hello", "world", 1, "2"); + emitter.serverSideEmit("hello", "world", 1, "2"); - servers[0].on("hello", (arg1, arg2, arg3) => { - expect(arg1).to.eql("world"); - expect(arg2).to.eql(1); - expect(arg3).to.eql("2"); - partialDone(); - }); + servers[0].on("hello", (arg1, arg2, arg3) => { + assert.equal(arg1, "world"); + assert.equal(arg2, 1); + assert.equal(arg3, "2"); + partialResolve(); + }); - servers[1].on("hello", (arg1, arg2, arg3) => { - partialDone(); - }); + servers[1].on("hello", (arg1, arg2, arg3) => { + partialResolve(); + }); - servers[2].of("/").on("hello", () => { - partialDone(); + servers[2].of("/").on("hello", () => { + partialResolve(); + }); }); }); }); diff --git a/packages/socket.io-redis-streams-emitter/test/util.ts b/packages/socket.io-redis-streams-emitter/test/util.ts index ea5d4a2b..0ba14cf3 100644 --- a/packages/socket.io-redis-streams-emitter/test/util.ts +++ b/packages/socket.io-redis-streams-emitter/test/util.ts @@ -138,9 +138,17 @@ async function init() { export async function setup() { const results = await Promise.all([init(), init(), init()]); - const servers = results.map(({ io }) => io); - const serverSockets = results.map(({ socket }) => socket); - const clientSockets = results.map(({ clientSocket }) => clientSocket); + const servers = results.map(({ io }) => io) as [Server, Server, Server]; + const serverSockets = results.map(({ socket }) => socket) as [ + ServerSocket, + ServerSocket, + ServerSocket, + ]; + const clientSockets = results.map(({ clientSocket }) => clientSocket) as [ + ClientSocket, + ClientSocket, + ClientSocket, + ]; const cleanupMethods = results.map(({ cleanup }) => cleanup); return {