mirror of
https://github.com/socketio/socket.io.git
synced 2026-04-30 03:00:39 -04:00
588 lines
15 KiB
TypeScript
588 lines
15 KiB
TypeScript
import { Server } from "..";
|
|
import expect from "expect.js";
|
|
import {
|
|
createClient,
|
|
createPartialDone,
|
|
success,
|
|
successFn,
|
|
waitFor,
|
|
} from "./support/util";
|
|
|
|
describe("messaging many", () => {
|
|
it("emits to a namespace", (done) => {
|
|
const io = new Server(0);
|
|
const socket1 = createClient(io, "/", { multiplex: false });
|
|
const socket2 = createClient(io, "/", { multiplex: false });
|
|
const socket3 = createClient(io, "/test");
|
|
|
|
const partialDone = createPartialDone(
|
|
2,
|
|
successFn(done, io, socket1, socket2, socket3)
|
|
);
|
|
|
|
socket1.on("a", (a) => {
|
|
expect(a).to.be("b");
|
|
partialDone();
|
|
});
|
|
socket2.on("a", (a) => {
|
|
expect(a).to.be("b");
|
|
partialDone();
|
|
});
|
|
socket3.on("a", () => {
|
|
done(new Error("not"));
|
|
});
|
|
|
|
let sockets = 3;
|
|
io.on("connection", () => {
|
|
--sockets || emit();
|
|
});
|
|
io.of("/test", () => {
|
|
--sockets || emit();
|
|
});
|
|
|
|
function emit() {
|
|
io.emit("a", "b");
|
|
}
|
|
});
|
|
|
|
it("emits binary data to a namespace", (done) => {
|
|
const io = new Server(0);
|
|
const socket1 = createClient(io, "/", { multiplex: false });
|
|
const socket2 = createClient(io, "/", { multiplex: false });
|
|
const socket3 = createClient(io, "/test");
|
|
|
|
const partialDone = createPartialDone(
|
|
2,
|
|
successFn(done, io, socket1, socket2, socket3)
|
|
);
|
|
|
|
socket1.on("bin", (a) => {
|
|
expect(Buffer.isBuffer(a)).to.be(true);
|
|
partialDone();
|
|
});
|
|
socket2.on("bin", (a) => {
|
|
expect(Buffer.isBuffer(a)).to.be(true);
|
|
partialDone();
|
|
});
|
|
socket3.on("bin", () => {
|
|
done(new Error("not"));
|
|
});
|
|
|
|
let sockets = 3;
|
|
io.on("connection", () => {
|
|
--sockets || emit();
|
|
});
|
|
io.of("/test", () => {
|
|
--sockets || emit();
|
|
});
|
|
|
|
function emit() {
|
|
io.emit("bin", Buffer.alloc(10));
|
|
}
|
|
});
|
|
|
|
it("emits to the rest", (done) => {
|
|
const io = new Server(0);
|
|
const socket1 = createClient(io, "/", { multiplex: false });
|
|
const socket2 = createClient(io, "/", { multiplex: false });
|
|
const socket3 = createClient(io, "/test");
|
|
|
|
socket1.on("a", (a) => {
|
|
expect(a).to.be("b");
|
|
socket1.emit("finish");
|
|
});
|
|
socket2.emit("broadcast");
|
|
socket2.on("a", () => {
|
|
done(new Error("done"));
|
|
});
|
|
socket3.on("a", () => {
|
|
done(new Error("not"));
|
|
});
|
|
|
|
io.on("connection", (socket) => {
|
|
socket.on("broadcast", () => {
|
|
socket.broadcast.emit("a", "b");
|
|
});
|
|
socket.on("finish", () => {
|
|
success(done, io, socket1, socket2, socket3);
|
|
});
|
|
});
|
|
});
|
|
|
|
it("emits to rooms", (done) => {
|
|
const io = new Server(0);
|
|
const socket1 = createClient(io, "/", { multiplex: false });
|
|
const socket2 = createClient(io, "/", { multiplex: false });
|
|
|
|
socket2.on("a", () => {
|
|
done(new Error("not"));
|
|
});
|
|
socket1.on("a", () => {
|
|
success(done, io, socket1, socket2);
|
|
});
|
|
socket1.emit("join", "woot");
|
|
socket1.emit("emit", "woot");
|
|
|
|
io.on("connection", (socket) => {
|
|
socket.on("join", (room, fn) => {
|
|
socket.join(room);
|
|
fn && fn();
|
|
});
|
|
|
|
socket.on("emit", (room) => {
|
|
io.in(room).emit("a");
|
|
});
|
|
});
|
|
});
|
|
|
|
it("emits to rooms avoiding dupes", (done) => {
|
|
const io = new Server(0);
|
|
const socket1 = createClient(io, "/", { multiplex: false });
|
|
const socket2 = createClient(io, "/", { multiplex: false });
|
|
|
|
const partialDone = createPartialDone(
|
|
2,
|
|
successFn(done, io, socket1, socket2)
|
|
);
|
|
|
|
socket2.on("a", () => {
|
|
done(new Error("not"));
|
|
});
|
|
socket1.on("a", partialDone);
|
|
socket2.on("b", partialDone);
|
|
|
|
socket1.emit("join", "woot");
|
|
socket1.emit("join", "test");
|
|
socket2.emit("join", "third", () => {
|
|
socket2.emit("emit");
|
|
});
|
|
|
|
io.on("connection", (socket) => {
|
|
socket.on("join", (room, fn) => {
|
|
socket.join(room);
|
|
fn && fn();
|
|
});
|
|
|
|
socket.on("emit", () => {
|
|
io.in("woot").in("test").emit("a");
|
|
io.in("third").emit("b");
|
|
});
|
|
});
|
|
});
|
|
|
|
it("broadcasts to rooms", (done) => {
|
|
const io = new Server(0);
|
|
const socket1 = createClient(io, "/", { multiplex: false });
|
|
const socket2 = createClient(io, "/", { multiplex: false });
|
|
const socket3 = createClient(io, "/", { multiplex: false });
|
|
|
|
const partialDone = createPartialDone(
|
|
2,
|
|
successFn(done, io, socket1, socket2, socket3)
|
|
);
|
|
|
|
socket1.emit("join", "woot");
|
|
socket2.emit("join", "test");
|
|
socket3.emit("join", "test", () => {
|
|
socket3.emit("broadcast");
|
|
});
|
|
|
|
socket1.on("a", () => {
|
|
done(new Error("not"));
|
|
});
|
|
socket2.on("a", () => {
|
|
partialDone();
|
|
});
|
|
socket3.on("a", () => {
|
|
done(new Error("not"));
|
|
});
|
|
socket3.on("b", () => {
|
|
partialDone();
|
|
});
|
|
|
|
io.on("connection", (socket) => {
|
|
socket.on("join", (room, fn) => {
|
|
socket.join(room);
|
|
fn && fn();
|
|
});
|
|
|
|
socket.on("broadcast", () => {
|
|
socket.broadcast.to("test").emit("a");
|
|
socket.emit("b");
|
|
});
|
|
});
|
|
});
|
|
|
|
it("broadcasts binary data to rooms", (done) => {
|
|
const io = new Server(0);
|
|
const socket1 = createClient(io, "/", { multiplex: false });
|
|
const socket2 = createClient(io, "/", { multiplex: false });
|
|
const socket3 = createClient(io, "/", { multiplex: false });
|
|
|
|
const partialDone = createPartialDone(
|
|
2,
|
|
successFn(done, io, socket1, socket2, socket3)
|
|
);
|
|
|
|
socket1.emit("join", "woot");
|
|
socket2.emit("join", "test");
|
|
socket3.emit("join", "test", () => {
|
|
socket3.emit("broadcast");
|
|
});
|
|
|
|
socket1.on("bin", (data) => {
|
|
throw new Error("got bin in socket1");
|
|
});
|
|
socket2.on("bin", (data) => {
|
|
expect(Buffer.isBuffer(data)).to.be(true);
|
|
partialDone();
|
|
});
|
|
socket2.on("bin2", (data) => {
|
|
throw new Error("socket2 got bin2");
|
|
});
|
|
socket3.on("bin", (data) => {
|
|
throw new Error("socket3 got bin");
|
|
});
|
|
socket3.on("bin2", (data) => {
|
|
expect(Buffer.isBuffer(data)).to.be(true);
|
|
partialDone();
|
|
});
|
|
|
|
io.on("connection", (socket) => {
|
|
socket.on("join", (room, fn) => {
|
|
socket.join(room);
|
|
fn && fn();
|
|
});
|
|
socket.on("broadcast", () => {
|
|
socket.broadcast.to("test").emit("bin", Buffer.alloc(5));
|
|
socket.emit("bin2", Buffer.alloc(5));
|
|
});
|
|
});
|
|
});
|
|
|
|
it("keeps track of rooms", (done) => {
|
|
const io = new Server(0);
|
|
const socket = createClient(io);
|
|
|
|
io.on("connection", (s) => {
|
|
s.join("a");
|
|
expect(s.rooms).to.contain(s.id, "a");
|
|
s.join("b");
|
|
expect(s.rooms).to.contain(s.id, "a", "b");
|
|
s.join("c");
|
|
expect(s.rooms).to.contain(s.id, "a", "b", "c");
|
|
s.leave("b");
|
|
expect(s.rooms).to.contain(s.id, "a", "c");
|
|
(s as any).leaveAll();
|
|
expect(s.rooms.size).to.eql(0);
|
|
|
|
success(done, io, socket);
|
|
});
|
|
});
|
|
|
|
it("deletes empty rooms", (done) => {
|
|
const io = new Server(0);
|
|
const socket = createClient(io);
|
|
|
|
io.on("connection", (s) => {
|
|
s.join("a");
|
|
expect(s.nsp.adapter.rooms).to.contain("a");
|
|
s.leave("a");
|
|
expect(s.nsp.adapter.rooms).to.not.contain("a");
|
|
|
|
success(done, io, socket);
|
|
});
|
|
});
|
|
|
|
it("should properly cleanup left rooms", (done) => {
|
|
const io = new Server(0);
|
|
const socket = createClient(io);
|
|
|
|
io.on("connection", (s) => {
|
|
s.join("a");
|
|
expect(s.rooms).to.contain(s.id, "a");
|
|
s.join("b");
|
|
expect(s.rooms).to.contain(s.id, "a", "b");
|
|
s.leave("unknown");
|
|
expect(s.rooms).to.contain(s.id, "a", "b");
|
|
(s as any).leaveAll();
|
|
expect(s.rooms.size).to.eql(0);
|
|
|
|
success(done, io, socket);
|
|
});
|
|
});
|
|
|
|
it("allows to join several rooms at once", (done) => {
|
|
const io = new Server(0);
|
|
const socket = createClient(io);
|
|
|
|
io.on("connection", (s) => {
|
|
s.join(["a", "b", "c"]);
|
|
expect(s.rooms).to.contain(s.id, "a", "b", "c");
|
|
success(done, io, socket);
|
|
});
|
|
});
|
|
|
|
it("should exclude specific sockets when broadcasting", (done) => {
|
|
const io = new Server(0);
|
|
const socket1 = createClient(io, "/", { multiplex: false });
|
|
const socket2 = createClient(io, "/", { multiplex: false });
|
|
const socket3 = createClient(io, "/", { multiplex: false });
|
|
|
|
socket2.on("a", () => {
|
|
done(new Error("not"));
|
|
});
|
|
socket3.on("a", () => {
|
|
done(new Error("not"));
|
|
});
|
|
socket1.on("a", successFn(done, io, socket1, socket2, socket3));
|
|
|
|
io.on("connection", (socket) => {
|
|
socket.on("exclude", (id) => {
|
|
socket.broadcast.except(id).emit("a");
|
|
});
|
|
});
|
|
|
|
socket2.on("connect", () => {
|
|
socket3.emit("exclude", socket2.id);
|
|
});
|
|
});
|
|
|
|
it("should exclude a specific room when broadcasting", (done) => {
|
|
const io = new Server(0);
|
|
const socket1 = createClient(io, "/", { multiplex: false });
|
|
const socket2 = createClient(io, "/", { multiplex: false });
|
|
const socket3 = createClient(io, "/", { multiplex: false });
|
|
|
|
socket2.on("a", () => {
|
|
done(new Error("not"));
|
|
});
|
|
socket3.on("a", () => {
|
|
done(new Error("not"));
|
|
});
|
|
socket1.on("a", successFn(done, io, socket1, socket2, socket3));
|
|
|
|
io.on("connection", (socket) => {
|
|
socket.on("join", (room, cb) => {
|
|
socket.join(room);
|
|
cb();
|
|
});
|
|
socket.on("broadcast", () => {
|
|
socket.broadcast.except("room1").emit("a");
|
|
});
|
|
});
|
|
|
|
socket2.emit("join", "room1", () => {
|
|
socket3.emit("broadcast");
|
|
});
|
|
});
|
|
|
|
it("should return an immutable broadcast operator", (done) => {
|
|
const io = new Server(0);
|
|
const clientSocket = createClient(io);
|
|
|
|
io.on("connection", (socket) => {
|
|
const operator = socket.local
|
|
.compress(false)
|
|
.to(["room1", "room2"])
|
|
.except("room3");
|
|
operator.compress(true).emit("hello");
|
|
operator.volatile.emit("hello");
|
|
operator.to("room4").emit("hello");
|
|
operator.except("room5").emit("hello");
|
|
socket.emit("hello");
|
|
socket.to("room6").emit("hello");
|
|
// @ts-ignore
|
|
expect(operator.rooms).to.contain("room1", "room2");
|
|
// @ts-ignore
|
|
expect(operator.rooms).to.not.contain("room4", "room5", "room6");
|
|
// @ts-ignore
|
|
expect(operator.exceptRooms).to.contain("room3");
|
|
// @ts-ignore
|
|
expect(operator.flags).to.eql({ local: true, compress: false });
|
|
|
|
success(done, io, clientSocket);
|
|
});
|
|
});
|
|
|
|
it("should broadcast and expect multiple acknowledgements", (done) => {
|
|
const io = new Server(0);
|
|
const socket1 = createClient(io, "/", { multiplex: false });
|
|
const socket2 = createClient(io, "/", { multiplex: false });
|
|
const socket3 = createClient(io, "/", { multiplex: false });
|
|
|
|
socket1.on("some event", (cb) => {
|
|
cb(1);
|
|
});
|
|
|
|
socket2.on("some event", (cb) => {
|
|
cb(2);
|
|
});
|
|
|
|
socket3.on("some event", (cb) => {
|
|
cb(3);
|
|
});
|
|
|
|
Promise.all([
|
|
waitFor(socket1, "connect"),
|
|
waitFor(socket2, "connect"),
|
|
waitFor(socket3, "connect"),
|
|
]).then(() => {
|
|
io.timeout(2000).emit("some event", (err, responses) => {
|
|
expect(err).to.be(null);
|
|
expect(responses).to.have.length(3);
|
|
expect(responses).to.contain(1, 2, 3);
|
|
|
|
success(done, io, socket1, socket2, socket3);
|
|
});
|
|
});
|
|
});
|
|
|
|
it("should fail when a client does not acknowledge the event in the given delay", (done) => {
|
|
const io = new Server(0);
|
|
const socket1 = createClient(io, "/", { multiplex: false });
|
|
const socket2 = createClient(io, "/", { multiplex: false });
|
|
const socket3 = createClient(io, "/", { multiplex: false });
|
|
|
|
socket1.on("some event", (cb) => {
|
|
cb(1);
|
|
});
|
|
|
|
socket2.on("some event", (cb) => {
|
|
cb(2);
|
|
});
|
|
|
|
socket3.on("some event", () => {
|
|
// timeout
|
|
});
|
|
|
|
Promise.all([
|
|
waitFor(socket1, "connect"),
|
|
waitFor(socket2, "connect"),
|
|
waitFor(socket3, "connect"),
|
|
]).then(() => {
|
|
io.timeout(200).emit("some event", (err, responses) => {
|
|
expect(err).to.be.an(Error);
|
|
expect(responses).to.have.length(2);
|
|
expect(responses).to.contain(1, 2);
|
|
|
|
success(done, io, socket1, socket2, socket3);
|
|
});
|
|
});
|
|
});
|
|
|
|
it("should broadcast and expect multiple acknowledgements (promise)", (done) => {
|
|
const io = new Server(0);
|
|
const socket1 = createClient(io, "/", { multiplex: false });
|
|
const socket2 = createClient(io, "/", { multiplex: false });
|
|
const socket3 = createClient(io, "/", { multiplex: false });
|
|
|
|
socket1.on("some event", (cb) => {
|
|
cb(1);
|
|
});
|
|
|
|
socket2.on("some event", (cb) => {
|
|
cb(2);
|
|
});
|
|
|
|
socket3.on("some event", (cb) => {
|
|
cb(3);
|
|
});
|
|
|
|
Promise.all([
|
|
waitFor(socket1, "connect"),
|
|
waitFor(socket2, "connect"),
|
|
waitFor(socket3, "connect"),
|
|
]).then(async () => {
|
|
const responses = await io.timeout(2000).emitWithAck("some event");
|
|
expect(responses).to.contain(1, 2, 3);
|
|
|
|
success(done, io, socket1, socket2, socket3);
|
|
});
|
|
});
|
|
|
|
it("should fail when a client does not acknowledge the event in the given delay (promise)", (done) => {
|
|
const io = new Server(0);
|
|
const socket1 = createClient(io, "/", { multiplex: false });
|
|
const socket2 = createClient(io, "/", { multiplex: false });
|
|
const socket3 = createClient(io, "/", { multiplex: false });
|
|
|
|
socket1.on("some event", (cb) => {
|
|
cb(1);
|
|
});
|
|
|
|
socket2.on("some event", (cb) => {
|
|
cb(2);
|
|
});
|
|
|
|
socket3.on("some event", () => {
|
|
// timeout
|
|
});
|
|
|
|
Promise.all([
|
|
waitFor(socket1, "connect"),
|
|
waitFor(socket2, "connect"),
|
|
waitFor(socket3, "connect"),
|
|
]).then(async () => {
|
|
try {
|
|
await io.timeout(200).emitWithAck("some event");
|
|
expect().fail();
|
|
} catch (err) {
|
|
expect(err).to.be.an(Error);
|
|
// @ts-ignore
|
|
expect(err.responses).to.have.length(2);
|
|
// @ts-ignore
|
|
expect(err.responses).to.contain(1, 2);
|
|
|
|
success(done, io, socket1, socket2, socket3);
|
|
}
|
|
});
|
|
});
|
|
|
|
it("should broadcast and return if the packet is sent to 0 client", (done) => {
|
|
const io = new Server(0);
|
|
const socket1 = createClient(io, "/", { multiplex: false });
|
|
const socket2 = createClient(io, "/", { multiplex: false });
|
|
const socket3 = createClient(io, "/", { multiplex: false });
|
|
|
|
socket1.on("some event", () => {
|
|
done(new Error("should not happen"));
|
|
});
|
|
|
|
socket2.on("some event", () => {
|
|
done(new Error("should not happen"));
|
|
});
|
|
|
|
socket3.on("some event", () => {
|
|
done(new Error("should not happen"));
|
|
});
|
|
|
|
io.to("room123")
|
|
.timeout(200)
|
|
.emit("some event", (err, responses) => {
|
|
expect(err).to.be(null);
|
|
expect(responses).to.have.length(0);
|
|
|
|
success(done, io, socket1, socket2, socket3);
|
|
});
|
|
});
|
|
|
|
it("should precompute the WebSocket frame when broadcasting", (done) => {
|
|
const io = new Server(0);
|
|
const socket = createClient(io, "/chat", {
|
|
transports: ["websocket"],
|
|
});
|
|
const partialDone = createPartialDone(2, successFn(done, io, socket));
|
|
|
|
io.of("/chat").on("connection", (s) => {
|
|
s.conn.once("packetCreate", (packet) => {
|
|
expect(packet.options.wsPreEncodedFrame).to.be.an(Array);
|
|
partialDone();
|
|
});
|
|
io.of("/chat").compress(false).emit("woot", "hi");
|
|
});
|
|
|
|
socket.on("woot", partialDone);
|
|
});
|
|
});
|