mirror of
https://github.com/socketio/socket.io.git
synced 2026-01-09 15:08:12 -05:00
279 lines
7.6 KiB
TypeScript
279 lines
7.6 KiB
TypeScript
import { createServer } from "http";
|
|
import { Server, Socket as ServerSocket } from "socket.io";
|
|
import { io as ioc, Socket as ClientSocket } from "socket.io-client";
|
|
import expect = require("expect.js");
|
|
import { createAdapter } from "@socket.io/postgres-adapter";
|
|
import type { AddressInfo } from "net";
|
|
import { Pool } from "pg";
|
|
import { times, sleep } from "./util";
|
|
import { Emitter } from "..";
|
|
|
|
const NODES_COUNT = 3;
|
|
|
|
describe("@socket.io/postgres-emitter", () => {
|
|
let servers: Server[],
|
|
serverSockets: ServerSocket[],
|
|
clientSockets: ClientSocket[],
|
|
pool: Pool,
|
|
emitter: Emitter;
|
|
|
|
beforeEach((done) => {
|
|
servers = [];
|
|
serverSockets = [];
|
|
clientSockets = [];
|
|
pool = new Pool({
|
|
user: "postgres",
|
|
host: "localhost",
|
|
database: "postgres",
|
|
password: "changeit",
|
|
port: 5432,
|
|
});
|
|
|
|
pool.query(
|
|
`
|
|
CREATE TABLE IF NOT EXISTS socket_io_attachments (
|
|
id bigserial UNIQUE,
|
|
created_at timestamptz DEFAULT NOW(),
|
|
payload bytea
|
|
);
|
|
`,
|
|
() => {},
|
|
);
|
|
|
|
emitter = new Emitter(pool);
|
|
|
|
for (let i = 1; i <= NODES_COUNT; i++) {
|
|
const httpServer = createServer();
|
|
const io = new Server(httpServer);
|
|
// @ts-ignore
|
|
io.adapter(createAdapter(pool));
|
|
httpServer.listen(() => {
|
|
const port = (httpServer.address() as AddressInfo).port;
|
|
const clientSocket = ioc(`http://localhost:${port}`);
|
|
|
|
io.on("connection", async (socket) => {
|
|
clientSockets.push(clientSocket);
|
|
serverSockets.push(socket);
|
|
servers.push(io);
|
|
if (servers.length === NODES_COUNT) {
|
|
// ensure all nodes know each other
|
|
servers[0].emit("ping");
|
|
servers[1].emit("ping");
|
|
servers[2].emit("ping");
|
|
|
|
await sleep(200);
|
|
|
|
done();
|
|
}
|
|
});
|
|
});
|
|
}
|
|
});
|
|
|
|
afterEach((done) => {
|
|
servers.forEach((server) => {
|
|
// @ts-ignore
|
|
server.httpServer.close();
|
|
server.of("/").adapter.close();
|
|
});
|
|
clientSockets.forEach((socket) => {
|
|
socket.disconnect();
|
|
});
|
|
pool.end(done);
|
|
});
|
|
|
|
describe("broadcast", function () {
|
|
it("broadcasts to all clients", (done) => {
|
|
const partialDone = times(3, done);
|
|
|
|
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();
|
|
});
|
|
});
|
|
|
|
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();
|
|
});
|
|
|
|
servers.forEach((server) => server.of("/custom"));
|
|
|
|
const onConnect = times(3, async () => {
|
|
await sleep(200);
|
|
|
|
emitter.of("/custom").emit("test");
|
|
});
|
|
|
|
clientSockets.forEach((clientSocket) => {
|
|
const socket = clientSocket.io.socket("/custom");
|
|
socket.on("connect", onConnect);
|
|
socket.on("test", () => {
|
|
socket.disconnect();
|
|
partialDone();
|
|
});
|
|
});
|
|
});
|
|
|
|
it("broadcasts to all clients in a room", (done) => {
|
|
serverSockets[1].join("room1");
|
|
|
|
clientSockets[0].on("test", () => {
|
|
done(new Error("should not happen"));
|
|
});
|
|
|
|
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");
|
|
|
|
clientSockets[0].on("test", () => {
|
|
partialDone();
|
|
});
|
|
|
|
clientSockets[1].on("test", () => {
|
|
done(new Error("should not happen"));
|
|
});
|
|
|
|
clientSockets[2].on("test", () => {
|
|
partialDone();
|
|
});
|
|
|
|
emitter.of("/").except("room1").emit("test");
|
|
});
|
|
});
|
|
|
|
describe("socketsJoin", () => {
|
|
it("makes all socket instances join the specified room", async () => {
|
|
emitter.socketsJoin("room1");
|
|
|
|
await sleep(200);
|
|
|
|
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);
|
|
});
|
|
|
|
it("makes the matching socket instances join the specified room", async () => {
|
|
serverSockets[0].join("room1");
|
|
serverSockets[2].join("room1");
|
|
|
|
emitter.in("room1").socketsJoin("room2");
|
|
|
|
await sleep(200);
|
|
|
|
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);
|
|
});
|
|
|
|
it("makes the given socket instance join the specified room", async () => {
|
|
emitter.in(serverSockets[1].id).socketsJoin("room3");
|
|
|
|
await sleep(200);
|
|
|
|
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);
|
|
});
|
|
});
|
|
|
|
describe("socketsLeave", () => {
|
|
it("makes all socket instances leave the specified room", async () => {
|
|
serverSockets[0].join("room1");
|
|
serverSockets[2].join("room1");
|
|
|
|
emitter.socketsLeave("room1");
|
|
|
|
await sleep(200);
|
|
|
|
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);
|
|
});
|
|
|
|
it("makes the matching socket instances leave the specified room", async () => {
|
|
serverSockets[0].join(["room1", "room2"]);
|
|
serverSockets[1].join(["room1", "room2"]);
|
|
serverSockets[2].join(["room2"]);
|
|
|
|
emitter.in("room1").socketsLeave("room2");
|
|
|
|
await sleep(200);
|
|
|
|
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);
|
|
});
|
|
|
|
it("makes the given socket instance leave the specified room", async () => {
|
|
serverSockets[0].join("room3");
|
|
serverSockets[1].join("room3");
|
|
serverSockets[2].join("room3");
|
|
|
|
emitter.in(serverSockets[1].id).socketsLeave("room3");
|
|
|
|
await sleep(200);
|
|
|
|
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);
|
|
});
|
|
});
|
|
|
|
describe("disconnectSockets", () => {
|
|
it("makes all socket instances disconnect", (done) => {
|
|
const partialDone = times(3, done);
|
|
|
|
clientSockets.forEach((clientSocket) => {
|
|
clientSocket.on("disconnect", (reason) => {
|
|
expect(reason).to.eql("io server disconnect");
|
|
partialDone();
|
|
});
|
|
});
|
|
|
|
emitter.disconnectSockets();
|
|
});
|
|
});
|
|
|
|
describe("serverSideEmit", () => {
|
|
it("sends an event to other server instances", (done) => {
|
|
const partialDone = times(3, done);
|
|
|
|
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[1].on("hello", (arg1, arg2, arg3) => {
|
|
partialDone();
|
|
});
|
|
|
|
servers[2].of("/").on("hello", () => {
|
|
partialDone();
|
|
});
|
|
});
|
|
});
|
|
});
|