mirror of
https://github.com/socketio/socket.io.git
synced 2026-01-13 08:57:59 -05:00
2596 lines
74 KiB
JavaScript
2596 lines
74 KiB
JavaScript
'use strict';
|
|
|
|
var http = require('http').Server;
|
|
var io = require('../lib');
|
|
var fs = require('fs');
|
|
var join = require('path').join;
|
|
var exec = require('child_process').exec;
|
|
var ioc = require('socket.io-client');
|
|
var request = require('supertest');
|
|
var expect = require('expect.js');
|
|
|
|
// Creates a socket.io client for the given server
|
|
function client(srv, nsp, opts){
|
|
if ('object' == typeof nsp) {
|
|
opts = nsp;
|
|
nsp = null;
|
|
}
|
|
var addr = srv.address();
|
|
if (!addr) addr = srv.listen().address();
|
|
var url = 'ws://localhost:' + addr.port + (nsp || '');
|
|
return ioc(url, opts);
|
|
}
|
|
|
|
describe('socket.io', function(){
|
|
|
|
it.skip('should be the same version as client', function(){
|
|
var version = require('../package').version;
|
|
expect(version).to.be(require('socket.io-client/package').version);
|
|
});
|
|
|
|
describe('set', function() {
|
|
it('should be able to set ping timeout to engine.io', function() {
|
|
var srv = io(http());
|
|
srv.set('heartbeat timeout', 10);
|
|
expect(srv.eio.pingTimeout).to.be(10);
|
|
});
|
|
|
|
it('should be able to set ping interval to engine.io', function() {
|
|
var srv = io(http());
|
|
srv.set('heartbeat interval', 10);
|
|
expect(srv.eio.pingInterval).to.be(10);
|
|
});
|
|
|
|
it('should be able to set transports to engine.io', function() {
|
|
var srv = io(http());
|
|
srv.set('transports', ['polling']);
|
|
expect(srv.eio.transports).to.eql(['polling']);
|
|
});
|
|
|
|
it('should be able to set maxHttpBufferSize to engine.io', function() {
|
|
var srv = io(http());
|
|
srv.set('destroy buffer size', 10);
|
|
expect(srv.eio.maxHttpBufferSize).to.eql(10);
|
|
});
|
|
|
|
it('should be able to set path with setting resource', function(done) {
|
|
var eio = io();
|
|
var srv = http();
|
|
|
|
eio.set('resource', '/random');
|
|
eio.attach(srv);
|
|
|
|
// Check that the server is accessible through the specified path
|
|
request(srv)
|
|
.get('/random/socket.io.js')
|
|
.buffer(true)
|
|
.end(function(err, res){
|
|
if (err) return done(err);
|
|
done();
|
|
});
|
|
});
|
|
|
|
it('should be able to set origins to engine.io', function() {
|
|
var srv = io(http());
|
|
srv.set('origins', 'http://hostname.com:*');
|
|
expect(srv.origins()).to.be('http://hostname.com:*');
|
|
});
|
|
|
|
it('should be able to set authorization and send error packet', function(done) {
|
|
var httpSrv = http();
|
|
var srv = io(httpSrv);
|
|
srv.set('authorization', function(o, f) { f(null, false); });
|
|
|
|
var socket = client(httpSrv);
|
|
socket.on('connect', function(){
|
|
expect().fail();
|
|
});
|
|
socket.on('error', function(err) {
|
|
expect(err).to.be('Not authorized');
|
|
done();
|
|
});
|
|
});
|
|
|
|
it('should be able to set authorization and succeed', function(done) {
|
|
var httpSrv = http();
|
|
var srv = io(httpSrv);
|
|
srv.set('authorization', function(o, f) { f(null, true); });
|
|
|
|
srv.on('connection', function(s) {
|
|
s.on('yoyo', function(data) {
|
|
expect(data).to.be('data');
|
|
done();
|
|
});
|
|
});
|
|
|
|
var socket = client(httpSrv);
|
|
socket.on('connect', function(){
|
|
socket.emit('yoyo', 'data');
|
|
});
|
|
|
|
socket.on('error', function(err) {
|
|
expect().fail();
|
|
});
|
|
});
|
|
|
|
it('should set the handshake BC object', function(done){
|
|
var httpSrv = http();
|
|
var srv = io(httpSrv);
|
|
|
|
srv.on('connection', function(s) {
|
|
expect(s.handshake).to.not.be(undefined);
|
|
|
|
// Headers set and has some valid properties
|
|
expect(s.handshake.headers).to.be.an('object');
|
|
expect(s.handshake.headers['user-agent']).to.be('node-XMLHttpRequest');
|
|
|
|
// Time set and is valid looking string
|
|
expect(s.handshake.time).to.be.a('string');
|
|
expect(s.handshake.time.split(' ').length > 0); // Is "multipart" string representation
|
|
|
|
// Address, xdomain, secure, issued and url set
|
|
expect(s.handshake.address).to.contain('127.0.0.1');
|
|
expect(s.handshake.xdomain).to.be.a('boolean');
|
|
expect(s.handshake.secure).to.be.a('boolean');
|
|
expect(s.handshake.issued).to.be.a('number');
|
|
expect(s.handshake.url).to.be.a('string');
|
|
|
|
// Query set and has some right properties
|
|
expect(s.handshake.query).to.be.an('object');
|
|
expect(s.handshake.query.EIO).to.not.be(undefined);
|
|
expect(s.handshake.query.transport).to.not.be(undefined);
|
|
expect(s.handshake.query.t).to.not.be(undefined);
|
|
|
|
done();
|
|
});
|
|
|
|
var socket = client(httpSrv);
|
|
});
|
|
});
|
|
|
|
describe('server attachment', function(){
|
|
describe('http.Server', function(){
|
|
var clientVersion = require('socket.io-client/package').version;
|
|
|
|
it('should serve static files', function(done){
|
|
var srv = http();
|
|
io(srv);
|
|
request(srv)
|
|
.get('/socket.io/socket.io.js')
|
|
.buffer(true)
|
|
.end(function(err, res){
|
|
if (err) return done(err);
|
|
var ctype = res.headers['content-type'];
|
|
expect(ctype).to.be('application/javascript');
|
|
expect(res.headers.etag).to.be('"' + clientVersion + '"');
|
|
expect(res.text).to.match(/engine\.io/);
|
|
expect(res.status).to.be(200);
|
|
done();
|
|
});
|
|
});
|
|
|
|
it('should handle 304', function(done){
|
|
var srv = http();
|
|
io(srv);
|
|
request(srv)
|
|
.get('/socket.io/socket.io.js')
|
|
.set('If-None-Match', '"' + clientVersion + '"')
|
|
.end(function(err, res){
|
|
if (err) return done(err);
|
|
expect(res.statusCode).to.be(304);
|
|
done();
|
|
});
|
|
});
|
|
|
|
it('should not serve static files', function(done){
|
|
var srv = http();
|
|
io(srv, { serveClient: false });
|
|
request(srv)
|
|
.get('/socket.io/socket.io.js')
|
|
.expect(400, done);
|
|
});
|
|
|
|
it('should work with #attach', function(done){
|
|
var srv = http(function(req, res){
|
|
res.writeHead(404);
|
|
res.end();
|
|
});
|
|
var sockets = io();
|
|
sockets.attach(srv);
|
|
request(srv)
|
|
.get('/socket.io/socket.io.js')
|
|
.end(function(err, res){
|
|
if (err) return done(err);
|
|
expect(res.status).to.be(200);
|
|
done();
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('port', function(done){
|
|
it('should be bound', function(done){
|
|
var sockets = io(54010);
|
|
request('http://localhost:54010')
|
|
.get('/socket.io/socket.io.js')
|
|
.expect(200, done);
|
|
});
|
|
|
|
it('should be bound as a string', function(done) {
|
|
var sockets = io('54020');
|
|
request('http://localhost:54020')
|
|
.get('/socket.io/socket.io.js')
|
|
.expect(200, done);
|
|
});
|
|
|
|
it('with listen', function(done){
|
|
var sockets = io().listen(54011);
|
|
request('http://localhost:54011')
|
|
.get('/socket.io/socket.io.js')
|
|
.expect(200, done);
|
|
});
|
|
|
|
it('as a string', function(done){
|
|
var sockets = io().listen('54012');
|
|
request('http://localhost:54012')
|
|
.get('/socket.io/socket.io.js')
|
|
.expect(200, done);
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('handshake', function(){
|
|
var request = require('superagent');
|
|
|
|
it('should disallow request when origin defined and none specified', function(done) {
|
|
var sockets = io({ origins: 'http://foo.example:*' }).listen('54013');
|
|
request.get('http://localhost:54013/socket.io/default/')
|
|
.query({ transport: 'polling' })
|
|
.end(function (err, res) {
|
|
expect(res.status).to.be(403);
|
|
done();
|
|
});
|
|
});
|
|
|
|
it('should disallow request when origin defined and a different one specified', function(done) {
|
|
var sockets = io({ origins: 'http://foo.example:*' }).listen('54014');
|
|
request.get('http://localhost:54014/socket.io/default/')
|
|
.query({ transport: 'polling' })
|
|
.set('origin', 'http://herp.derp')
|
|
.end(function (err, res) {
|
|
expect(res.status).to.be(403);
|
|
done();
|
|
});
|
|
});
|
|
|
|
it('should allow request when origin defined an the same is specified', function(done) {
|
|
var sockets = io({ origins: 'http://foo.example:*' }).listen('54015');
|
|
request.get('http://localhost:54015/socket.io/default/')
|
|
.set('origin', 'http://foo.example')
|
|
.query({ transport: 'polling' })
|
|
.end(function (err, res) {
|
|
expect(res.status).to.be(200);
|
|
done();
|
|
});
|
|
});
|
|
|
|
it('should allow request when origin defined as function and same is supplied', function(done) {
|
|
var sockets = io({ origins: function(origin,callback){
|
|
if (origin == 'http://foo.example') {
|
|
return callback(null, true);
|
|
}
|
|
return callback(null, false);
|
|
} }).listen('54016');
|
|
request.get('http://localhost:54016/socket.io/default/')
|
|
.set('origin', 'http://foo.example')
|
|
.query({ transport: 'polling' })
|
|
.end(function (err, res) {
|
|
expect(res.status).to.be(200);
|
|
done();
|
|
});
|
|
});
|
|
|
|
it('should allow request when origin defined as function and different is supplied', function(done) {
|
|
var sockets = io({ origins: function(origin,callback){
|
|
if (origin == 'http://foo.example') {
|
|
return callback(null, true);
|
|
}
|
|
return callback(null, false);
|
|
} }).listen('54017');
|
|
request.get('http://localhost:54017/socket.io/default/')
|
|
.set('origin', 'http://herp.derp')
|
|
.query({ transport: 'polling' })
|
|
.end(function (err, res) {
|
|
expect(res.status).to.be(403);
|
|
done();
|
|
});
|
|
});
|
|
|
|
it('should allow request when origin defined as function and no origin is supplied', function(done) {
|
|
var sockets = io({ origins: function(origin,callback){
|
|
if (origin == '*') {
|
|
return callback(null, true);
|
|
}
|
|
return callback(null, false);
|
|
} }).listen('54021');
|
|
request.get('http://localhost:54021/socket.io/default/')
|
|
.query({ transport: 'polling' })
|
|
.end(function (err, res) {
|
|
expect(res.status).to.be(200);
|
|
done();
|
|
});
|
|
});
|
|
|
|
it('should default to port 443 when protocol is https', function(done) {
|
|
var sockets = io({ origins: 'https://foo.example:443' }).listen('54036');
|
|
request.get('http://localhost:54036/socket.io/default/')
|
|
.set('origin', 'https://foo.example')
|
|
.query({ transport: 'polling' })
|
|
.end(function (err, res) {
|
|
expect(res.status).to.be(200);
|
|
done();
|
|
});
|
|
});
|
|
|
|
it('should allow request if custom function in opts.allowRequest returns true', function(done){
|
|
var sockets = io(http().listen(54022), { allowRequest: function (req, callback) {
|
|
return callback(null, true);
|
|
}, origins: 'http://foo.example:*' });
|
|
|
|
request.get('http://localhost:54022/socket.io/default/')
|
|
.query({ transport: 'polling' })
|
|
.end(function (err, res) {
|
|
expect(res.status).to.be(200);
|
|
done();
|
|
});
|
|
});
|
|
|
|
it('should disallow request if custom function in opts.allowRequest returns false', function(done){
|
|
var sockets = io(http().listen(54023), { allowRequest: function (req, callback) {
|
|
return callback(null, false);
|
|
} });
|
|
request.get('http://localhost:54023/socket.io/default/')
|
|
.set('origin', 'http://foo.example')
|
|
.query({ transport: 'polling' })
|
|
.end(function (err, res) {
|
|
expect(res.status).to.be(403);
|
|
done();
|
|
});
|
|
});
|
|
|
|
it('should allow request when using an array of origins', function(done) {
|
|
io({ origins: [ 'http://foo.example:54024' ] }).listen('54024');
|
|
request.get('http://localhost:54024/socket.io/default/')
|
|
.set('origin', 'http://foo.example:54024')
|
|
.query({ transport: 'polling' })
|
|
.end(function (err, res) {
|
|
expect(res.status).to.be(200);
|
|
done();
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('close', function(){
|
|
|
|
it('should be able to close sio sending a srv', function(){
|
|
var PORT = 54018;
|
|
var srv = http().listen(PORT);
|
|
var sio = io(srv);
|
|
var net = require('net');
|
|
var server = net.createServer();
|
|
|
|
var clientSocket = client(srv, { reconnection: false });
|
|
|
|
clientSocket.on('disconnect', function init() {
|
|
expect(Object.keys(sio.nsps['/'].sockets).length).to.equal(0);
|
|
server.listen(PORT);
|
|
});
|
|
|
|
clientSocket.on('connect', function init() {
|
|
expect(Object.keys(sio.nsps['/'].sockets).length).to.equal(1);
|
|
sio.close();
|
|
});
|
|
|
|
server.once('listening', function() {
|
|
// PORT should be free
|
|
server.close(function(error){
|
|
expect(error).to.be(undefined);
|
|
});
|
|
});
|
|
|
|
});
|
|
|
|
it('should be able to close sio sending a port', function(){
|
|
var PORT = 54019;
|
|
var sio = io(PORT);
|
|
var net = require('net');
|
|
var server = net.createServer();
|
|
|
|
var clientSocket = ioc('ws://0.0.0.0:' + PORT, { reconnection: false });
|
|
|
|
clientSocket.on('disconnect', function init() {
|
|
expect(Object.keys(sio.nsps['/'].sockets).length).to.equal(0);
|
|
server.listen(PORT);
|
|
});
|
|
|
|
clientSocket.on('connect', function init() {
|
|
expect(Object.keys(sio.nsps['/'].sockets).length).to.equal(1);
|
|
sio.close();
|
|
});
|
|
|
|
server.once('listening', function() {
|
|
// PORT should be free
|
|
server.close(function(error){
|
|
expect(error).to.be(undefined);
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('graceful close', function(){
|
|
function fixture(filename) {
|
|
return '"' + process.execPath + '" "' +
|
|
join(__dirname, 'fixtures', filename) + '"';
|
|
}
|
|
|
|
it('should stop socket and timers', function(done){
|
|
exec(fixture('server-close.js'), done);
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('namespaces', function(){
|
|
var Socket = require('../lib/socket');
|
|
var Namespace = require('../lib/namespace');
|
|
|
|
it('should be accessible through .sockets', function(){
|
|
var sio = io();
|
|
expect(sio.sockets).to.be.a(Namespace);
|
|
});
|
|
|
|
it('should be aliased', function(){
|
|
var sio = io();
|
|
expect(sio.use).to.be.a('function');
|
|
expect(sio.to).to.be.a('function');
|
|
expect(sio['in']).to.be.a('function');
|
|
expect(sio.emit).to.be.a('function');
|
|
expect(sio.send).to.be.a('function');
|
|
expect(sio.write).to.be.a('function');
|
|
expect(sio.clients).to.be.a('function');
|
|
expect(sio.compress).to.be.a('function');
|
|
expect(sio.json).to.be(sio);
|
|
expect(sio.volatile).to.be(sio);
|
|
expect(sio.sockets.flags).to.eql({ json: true, volatile: true });
|
|
delete sio.sockets.flags;
|
|
});
|
|
|
|
it('should automatically connect', function(done){
|
|
var srv = http();
|
|
var sio = io(srv);
|
|
srv.listen(function(){
|
|
var socket = client(srv);
|
|
socket.on('connect', function(){
|
|
done();
|
|
});
|
|
});
|
|
});
|
|
|
|
it('should fire a `connection` event', function(done){
|
|
var srv = http();
|
|
var sio = io(srv);
|
|
srv.listen(function(){
|
|
var socket = client(srv);
|
|
sio.on('connection', function(socket){
|
|
expect(socket).to.be.a(Socket);
|
|
done();
|
|
});
|
|
});
|
|
});
|
|
|
|
it('should fire a `connect` event', function(done){
|
|
var srv = http();
|
|
var sio = io(srv);
|
|
srv.listen(function(){
|
|
var socket = client(srv);
|
|
sio.on('connect', function(socket){
|
|
expect(socket).to.be.a(Socket);
|
|
done();
|
|
});
|
|
});
|
|
});
|
|
|
|
it('should work with many sockets', function(done){
|
|
var srv = http();
|
|
var sio = io(srv);
|
|
srv.listen(function(){
|
|
sio.of('/chat');
|
|
sio.of('/news');
|
|
var chat = client(srv, '/chat');
|
|
var news = client(srv, '/news');
|
|
var total = 2;
|
|
chat.on('connect', function(){
|
|
--total || done();
|
|
});
|
|
news.on('connect', function(){
|
|
--total || done();
|
|
});
|
|
});
|
|
});
|
|
|
|
it('should be able to equivalently start with "" or "/" on server', function(done){
|
|
var srv = http();
|
|
var sio = io(srv);
|
|
var total = 2;
|
|
sio.of('').on('connection', function(){
|
|
--total || done();
|
|
});
|
|
sio.of('abc').on('connection', function(){
|
|
--total || done();
|
|
});
|
|
var c1 = client(srv, '/');
|
|
var c2 = client(srv, '/abc');
|
|
});
|
|
|
|
it('should be equivalent for "" and "/" on client', function(done){
|
|
var srv = http();
|
|
var sio = io(srv);
|
|
sio.of('/').on('connection', function(){
|
|
done();
|
|
});
|
|
var c1 = client(srv, '');
|
|
});
|
|
|
|
it('should work with `of` and many sockets', function(done){
|
|
var srv = http();
|
|
var sio = io(srv);
|
|
srv.listen(function(){
|
|
var chat = client(srv, '/chat');
|
|
var news = client(srv, '/news');
|
|
var total = 2;
|
|
sio.of('/news').on('connection', function(socket){
|
|
expect(socket).to.be.a(Socket);
|
|
--total || done();
|
|
});
|
|
sio.of('/news').on('connection', function(socket){
|
|
expect(socket).to.be.a(Socket);
|
|
--total || done();
|
|
});
|
|
});
|
|
});
|
|
|
|
it('should work with `of` second param', function(done){
|
|
var srv = http();
|
|
var sio = io(srv);
|
|
srv.listen(function(){
|
|
var chat = client(srv, '/chat');
|
|
var news = client(srv, '/news');
|
|
var total = 2;
|
|
sio.of('/news', function(socket){
|
|
expect(socket).to.be.a(Socket);
|
|
--total || done();
|
|
});
|
|
sio.of('/news', function(socket){
|
|
expect(socket).to.be.a(Socket);
|
|
--total || done();
|
|
});
|
|
});
|
|
});
|
|
|
|
it('should disconnect upon transport disconnection', function(done){
|
|
var srv = http();
|
|
var sio = io(srv);
|
|
srv.listen(function(){
|
|
var chat = client(srv, '/chat');
|
|
var news = client(srv, '/news');
|
|
var total = 2;
|
|
var totald = 2;
|
|
var s;
|
|
sio.of('/news', function(socket){
|
|
socket.on('disconnect', function(reason){
|
|
--totald || done();
|
|
});
|
|
--total || close();
|
|
});
|
|
sio.of('/chat', function(socket){
|
|
s = socket;
|
|
socket.on('disconnect', function(reason){
|
|
--totald || done();
|
|
});
|
|
--total || close();
|
|
});
|
|
function close(){
|
|
s.disconnect(true);
|
|
}
|
|
});
|
|
});
|
|
|
|
it('should disconnect both default and custom namespace upon disconnect', function(done){
|
|
var srv = http();
|
|
var sio = io(srv);
|
|
srv.listen(function(){
|
|
var lolcats = client(srv, '/lolcats');
|
|
var total = 2;
|
|
var totald = 2;
|
|
var s;
|
|
sio.of('/', function(socket){
|
|
socket.on('disconnect', function(reason){
|
|
--totald || done();
|
|
});
|
|
--total || close();
|
|
});
|
|
sio.of('/lolcats', function(socket){
|
|
s = socket;
|
|
socket.on('disconnect', function(reason){
|
|
--totald || done();
|
|
});
|
|
--total || close();
|
|
});
|
|
function close(){
|
|
s.disconnect(true);
|
|
}
|
|
});
|
|
});
|
|
|
|
it('should not crash while disconnecting socket', function(done){
|
|
var srv = http();
|
|
var sio = io(srv);
|
|
srv.listen(function(){
|
|
var socket = client(srv,'/ns');
|
|
sio.on('connection', function(socket){
|
|
socket.disconnect();
|
|
done();
|
|
});
|
|
});
|
|
});
|
|
|
|
it('should fire a `disconnecting` event just before leaving all rooms', function(done){
|
|
var srv = http();
|
|
var sio = io(srv);
|
|
srv.listen(function(){
|
|
var socket = client(srv);
|
|
|
|
sio.on('connection', function(s){
|
|
s.join('a', function(){
|
|
s.disconnect();
|
|
});
|
|
|
|
var total = 2;
|
|
s.on('disconnecting', function(reason){
|
|
expect(Object.keys(s.rooms)).to.eql([s.id, 'a']);
|
|
total--;
|
|
});
|
|
|
|
s.on('disconnect', function(reason){
|
|
expect(Object.keys(s.rooms)).to.eql([]);
|
|
--total || done();
|
|
});
|
|
});
|
|
});
|
|
});
|
|
|
|
it('should return error connecting to non-existent namespace', function(done){
|
|
var srv = http();
|
|
var sio = io(srv);
|
|
srv.listen(function(){
|
|
var socket = client(srv,'/doesnotexist');
|
|
socket.on('error', function(err) {
|
|
expect(err).to.be('Invalid namespace');
|
|
done();
|
|
});
|
|
});
|
|
});
|
|
|
|
it('should not reuse same-namespace connections', function(done){
|
|
var srv = http();
|
|
var sio = io(srv);
|
|
var connections = 0;
|
|
|
|
srv.listen(function() {
|
|
var clientSocket1 = client(srv);
|
|
var clientSocket2 = client(srv);
|
|
sio.on('connection', function() {
|
|
connections++;
|
|
if (connections === 2) {
|
|
done();
|
|
}
|
|
});
|
|
});
|
|
});
|
|
|
|
it('should find all clients in a namespace', function(done){
|
|
var srv = http();
|
|
var sio = io(srv);
|
|
var chatSids = [];
|
|
var otherSid = null;
|
|
srv.listen(function(){
|
|
var c1 = client(srv, '/chat');
|
|
var c2 = client(srv, '/chat', {forceNew: true});
|
|
var c3 = client(srv, '/other', {forceNew: true});
|
|
var total = 3;
|
|
sio.of('/chat').on('connection', function(socket){
|
|
chatSids.push(socket.id);
|
|
--total || getClients();
|
|
});
|
|
sio.of('/other').on('connection', function(socket){
|
|
otherSid = socket.id;
|
|
--total || getClients();
|
|
});
|
|
});
|
|
function getClients() {
|
|
sio.of('/chat').clients(function(error, sids) {
|
|
expect(error).to.not.be.ok();
|
|
expect(sids).to.contain(chatSids[0]);
|
|
expect(sids).to.contain(chatSids[1]);
|
|
expect(sids).to.not.contain(otherSid);
|
|
done();
|
|
});
|
|
}
|
|
});
|
|
|
|
it('should find all clients in a namespace room', function(done){
|
|
var srv = http();
|
|
var sio = io(srv);
|
|
var chatFooSid = null;
|
|
var chatBarSid = null;
|
|
var otherSid = null;
|
|
srv.listen(function(){
|
|
var c1 = client(srv, '/chat');
|
|
var c2 = client(srv, '/chat', {forceNew: true});
|
|
var c3 = client(srv, '/other', {forceNew: true});
|
|
var chatIndex = 0;
|
|
var total = 3;
|
|
sio.of('/chat').on('connection', function(socket){
|
|
if (chatIndex++) {
|
|
socket.join('foo', function() {
|
|
chatFooSid = socket.id;
|
|
--total || getClients();
|
|
});
|
|
} else {
|
|
socket.join('bar', function() {
|
|
chatBarSid = socket.id;
|
|
--total || getClients();
|
|
});
|
|
}
|
|
});
|
|
sio.of('/other').on('connection', function(socket){
|
|
socket.join('foo', function() {
|
|
otherSid = socket.id;
|
|
--total || getClients();
|
|
});
|
|
});
|
|
});
|
|
function getClients() {
|
|
sio.of('/chat').in('foo').clients(function(error, sids) {
|
|
expect(error).to.not.be.ok();
|
|
expect(sids).to.contain(chatFooSid);
|
|
expect(sids).to.not.contain(chatBarSid);
|
|
expect(sids).to.not.contain(otherSid);
|
|
done();
|
|
});
|
|
}
|
|
});
|
|
|
|
it('should find all clients across namespace rooms', function(done){
|
|
var srv = http();
|
|
var sio = io(srv);
|
|
var chatFooSid = null;
|
|
var chatBarSid = null;
|
|
var otherSid = null;
|
|
srv.listen(function(){
|
|
var c1 = client(srv, '/chat');
|
|
var c2 = client(srv, '/chat', {forceNew: true});
|
|
var c3 = client(srv, '/other', {forceNew: true});
|
|
var chatIndex = 0;
|
|
var total = 3;
|
|
sio.of('/chat').on('connection', function(socket){
|
|
if (chatIndex++) {
|
|
socket.join('foo', function() {
|
|
chatFooSid = socket.id;
|
|
--total || getClients();
|
|
});
|
|
} else {
|
|
socket.join('bar', function() {
|
|
chatBarSid = socket.id;
|
|
--total || getClients();
|
|
});
|
|
}
|
|
});
|
|
sio.of('/other').on('connection', function(socket){
|
|
socket.join('foo', function() {
|
|
otherSid = socket.id;
|
|
--total || getClients();
|
|
});
|
|
});
|
|
});
|
|
function getClients() {
|
|
sio.of('/chat').clients(function(error, sids) {
|
|
expect(error).to.not.be.ok();
|
|
expect(sids).to.contain(chatFooSid);
|
|
expect(sids).to.contain(chatBarSid);
|
|
expect(sids).to.not.contain(otherSid);
|
|
done();
|
|
});
|
|
}
|
|
});
|
|
|
|
it('should not emit volatile event after regular event', function(done) {
|
|
var srv = http();
|
|
var sio = io(srv);
|
|
|
|
var counter = 0;
|
|
srv.listen(function(){
|
|
sio.of('/chat').on('connection', function(s){
|
|
// Wait to make sure there are no packets being sent for opening the connection
|
|
setTimeout(function() {
|
|
sio.of('/chat').emit('ev', 'data');
|
|
sio.of('/chat').volatile.emit('ev', 'data');
|
|
}, 50);
|
|
});
|
|
|
|
var socket = client(srv, '/chat');
|
|
socket.on('ev', function() {
|
|
counter++;
|
|
});
|
|
});
|
|
|
|
setTimeout(function() {
|
|
expect(counter).to.be(1);
|
|
done();
|
|
}, 500);
|
|
});
|
|
|
|
it('should emit volatile event', function(done) {
|
|
var srv = http();
|
|
var sio = io(srv);
|
|
|
|
var counter = 0;
|
|
srv.listen(function(){
|
|
sio.of('/chat').on('connection', function(s){
|
|
// Wait to make sure there are no packets being sent for opening the connection
|
|
setTimeout(function() {
|
|
sio.of('/chat').volatile.emit('ev', 'data');
|
|
}, 100);
|
|
});
|
|
|
|
var socket = client(srv, '/chat');
|
|
socket.on('ev', function() {
|
|
counter++;
|
|
});
|
|
});
|
|
|
|
setTimeout(function() {
|
|
expect(counter).to.be(1);
|
|
done();
|
|
}, 500);
|
|
});
|
|
|
|
it('should enable compression by default', function(done){
|
|
var srv = http();
|
|
var sio = io(srv);
|
|
srv.listen(function(){
|
|
var socket = client(srv, '/chat');
|
|
sio.of('/chat').on('connection', function(s){
|
|
s.conn.once('packetCreate', function(packet) {
|
|
expect(packet.options.compress).to.be(true);
|
|
done();
|
|
});
|
|
sio.of('/chat').emit('woot', 'hi');
|
|
});
|
|
});
|
|
});
|
|
|
|
it('should disable compression', function(done){
|
|
var srv = http();
|
|
var sio = io(srv);
|
|
srv.listen(function(){
|
|
var socket = client(srv, '/chat');
|
|
sio.of('/chat').on('connection', function(s){
|
|
s.conn.once('packetCreate', function(packet) {
|
|
expect(packet.options.compress).to.be(false);
|
|
done();
|
|
});
|
|
sio.of('/chat').compress(false).emit('woot', 'hi');
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('dynamic namespaces', function () {
|
|
it('should allow connections to dynamic namespaces with a regex', function(done){
|
|
const srv = http();
|
|
const sio = io(srv);
|
|
let count = 0;
|
|
srv.listen(function(){
|
|
const socket = client(srv, '/dynamic-101');
|
|
let dynamicNsp = sio.of(/^\/dynamic-\d+$/).on('connect', (socket) => {
|
|
expect(socket.nsp.name).to.be('/dynamic-101');
|
|
dynamicNsp.emit('hello', 1, '2', { 3: '4'});
|
|
if (++count === 4) done();
|
|
}).use((socket, next) => {
|
|
next();
|
|
if (++count === 4) done();
|
|
});
|
|
socket.on('error', function(err) {
|
|
expect().fail();
|
|
});
|
|
socket.on('connect', () => {
|
|
if (++count === 4) done();
|
|
});
|
|
socket.on('hello', (a, b, c) => {
|
|
expect(a).to.eql(1);
|
|
expect(b).to.eql('2');
|
|
expect(c).to.eql({ 3: '4' });
|
|
if (++count === 4) done();
|
|
});
|
|
});
|
|
});
|
|
|
|
it('should allow connections to dynamic namespaces with a function', function(done){
|
|
const srv = http();
|
|
const sio = io(srv);
|
|
srv.listen(function(){
|
|
const socket = client(srv, '/dynamic-101');
|
|
sio.of((name, query, next) => next(null, '/dynamic-101' === name));
|
|
socket.on('connect', done);
|
|
});
|
|
});
|
|
|
|
it('should disallow connections when no dynamic namespace matches', function(done){
|
|
const srv = http();
|
|
const sio = io(srv);
|
|
srv.listen(function(){
|
|
const socket = client(srv, '/abc');
|
|
sio.of(/^\/dynamic-\d+$/);
|
|
sio.of((name, query, next) => next(null, '/dynamic-101' === name));
|
|
socket.on('error', (err) => {
|
|
expect(err).to.be('Invalid namespace');
|
|
done();
|
|
});
|
|
});
|
|
});
|
|
|
|
it("should handle race conditions with dynamic namespaces (#4136)", (done) => {
|
|
const srv = http();
|
|
const sio = io(srv);
|
|
const counters = {
|
|
connected: 0,
|
|
created: 0,
|
|
events: 0,
|
|
};
|
|
const buffer = [];
|
|
srv.listen(() => {
|
|
const handler = () => {
|
|
if (++counters.events === 2) {
|
|
done();
|
|
}
|
|
};
|
|
|
|
sio
|
|
.of((name, query, next) => {
|
|
buffer.push(next);
|
|
if (buffer.length === 2) {
|
|
buffer.forEach((next) => next(null, true));
|
|
}
|
|
})
|
|
.on("connection", (socket) => {
|
|
if (++counters.connected === 2) {
|
|
sio.of("/dynamic-101").emit("message");
|
|
}
|
|
});
|
|
|
|
let one = client(srv, "/dynamic-101");
|
|
let two = client(srv, "/dynamic-101");
|
|
one.on("message", handler);
|
|
two.on("message", handler);
|
|
});
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('socket', function(){
|
|
|
|
it('should not fire events more than once after manually reconnecting', function(done) {
|
|
var srv = http();
|
|
var sio = io(srv);
|
|
srv.listen(function(){
|
|
var clientSocket = client(srv, { reconnection: false });
|
|
clientSocket.on('connect', function init() {
|
|
clientSocket.removeListener('connect', init);
|
|
clientSocket.io.engine.close();
|
|
|
|
clientSocket.connect();
|
|
clientSocket.on('connect', function() {
|
|
done();
|
|
});
|
|
});
|
|
});
|
|
});
|
|
|
|
it('should not fire reconnect_failed event more than once when server closed', function(done) {
|
|
var srv = http();
|
|
var sio = io(srv);
|
|
srv.listen(function(){
|
|
var clientSocket = client(srv, { reconnectionAttempts: 3, reconnectionDelay: 10 });
|
|
clientSocket.on('connect', function() {
|
|
srv.close();
|
|
});
|
|
|
|
clientSocket.on('reconnect_failed', function() {
|
|
done();
|
|
});
|
|
});
|
|
});
|
|
|
|
it('should receive events', function(done){
|
|
var srv = http();
|
|
var sio = io(srv);
|
|
srv.listen(function(){
|
|
var socket = client(srv);
|
|
sio.on('connection', function(s){
|
|
s.on('random', function(a, b, c){
|
|
expect(a).to.be(1);
|
|
expect(b).to.be('2');
|
|
expect(c).to.eql([3]);
|
|
done();
|
|
});
|
|
socket.emit('random', 1, '2', [3]);
|
|
});
|
|
});
|
|
});
|
|
|
|
it('should receive message events through `send`', function(done){
|
|
var srv = http();
|
|
var sio = io(srv);
|
|
srv.listen(function(){
|
|
var socket = client(srv);
|
|
sio.on('connection', function(s){
|
|
s.on('message', function(a){
|
|
expect(a).to.be(1337);
|
|
done();
|
|
});
|
|
socket.send(1337);
|
|
});
|
|
});
|
|
});
|
|
|
|
it('should error with null messages', function(done){
|
|
var srv = http();
|
|
var sio = io(srv);
|
|
srv.listen(function(){
|
|
var socket = client(srv);
|
|
sio.on('connection', function(s){
|
|
s.on('message', function(a){
|
|
expect(a).to.be(null);
|
|
done();
|
|
});
|
|
socket.send(null);
|
|
});
|
|
});
|
|
});
|
|
|
|
it('should handle transport null messages', function(done){
|
|
var srv = http();
|
|
var sio = io(srv);
|
|
srv.listen(function(){
|
|
var socket = client(srv, { reconnection: false });
|
|
sio.on('connection', function(s){
|
|
s.on('error', function(err){
|
|
expect(err).to.be.an(Error);
|
|
s.on('disconnect', function(reason){
|
|
expect(reason).to.be('forced close');
|
|
done();
|
|
});
|
|
});
|
|
s.client.ondata(null);
|
|
});
|
|
});
|
|
});
|
|
|
|
it('should emit events', function(done){
|
|
var srv = http();
|
|
var sio = io(srv);
|
|
srv.listen(function(){
|
|
var socket = client(srv);
|
|
socket.on('woot', function(a){
|
|
expect(a).to.be('tobi');
|
|
done();
|
|
});
|
|
sio.on('connection', function(s){
|
|
s.emit('woot', 'tobi');
|
|
});
|
|
});
|
|
});
|
|
|
|
it('should emit events with utf8 multibyte character', function(done) {
|
|
var srv = http();
|
|
var sio = io(srv);
|
|
srv.listen(function(){
|
|
var socket = client(srv);
|
|
var i = 0;
|
|
socket.on('hoot', function(a){
|
|
expect(a).to.be('utf8 — string');
|
|
i++;
|
|
|
|
if (3 == i) {
|
|
done();
|
|
}
|
|
});
|
|
sio.on('connection', function(s){
|
|
s.emit('hoot', 'utf8 — string');
|
|
s.emit('hoot', 'utf8 — string');
|
|
s.emit('hoot', 'utf8 — string');
|
|
});
|
|
});
|
|
});
|
|
|
|
it('should emit events with binary data', function(done){
|
|
var srv = http();
|
|
var sio = io(srv);
|
|
srv.listen(function(){
|
|
var socket = client(srv);
|
|
var imageData;
|
|
socket.on('doge', function(a){
|
|
expect(Buffer.isBuffer(a)).to.be(true);
|
|
expect(imageData.length).to.equal(a.length);
|
|
expect(imageData[0]).to.equal(a[0]);
|
|
expect(imageData[imageData.length - 1]).to.equal(a[a.length - 1]);
|
|
done();
|
|
});
|
|
sio.on('connection', function(s){
|
|
fs.readFile(join(__dirname, 'support', 'doge.jpg'), function(err, data){
|
|
if (err) return done(err);
|
|
imageData = data;
|
|
s.emit('doge', data);
|
|
});
|
|
});
|
|
});
|
|
});
|
|
|
|
it('should emit events with several types of data (including binary)', function(done){
|
|
var srv = http();
|
|
var sio = io(srv);
|
|
srv.listen(function(){
|
|
var socket = client(srv);
|
|
socket.on('multiple', function(a, b, c, d, e, f){
|
|
expect(a).to.be(1);
|
|
expect(Buffer.isBuffer(b)).to.be(true);
|
|
expect(c).to.be('3');
|
|
expect(d).to.eql([4]);
|
|
expect(Buffer.isBuffer(e)).to.be(true);
|
|
expect(Buffer.isBuffer(f[0])).to.be(true);
|
|
expect(f[1]).to.be('swag');
|
|
expect(Buffer.isBuffer(f[2])).to.be(true);
|
|
done();
|
|
});
|
|
sio.on('connection', function(s){
|
|
fs.readFile(join(__dirname, 'support', 'doge.jpg'), function(err, data){
|
|
if (err) return done(err);
|
|
var buf = Buffer.from('asdfasdf', 'utf8');
|
|
s.emit('multiple', 1, data, '3', [4], buf, [data, 'swag', buf]);
|
|
});
|
|
});
|
|
});
|
|
});
|
|
|
|
it('should receive events with binary data', function(done){
|
|
var srv = http();
|
|
var sio = io(srv);
|
|
srv.listen(function(){
|
|
var socket = client(srv);
|
|
sio.on('connection', function(s){
|
|
s.on('buff', function(a){
|
|
expect(Buffer.isBuffer(a)).to.be(true);
|
|
done();
|
|
});
|
|
var buf = Buffer.from('abcdefg', 'utf8');
|
|
socket.emit('buff', buf);
|
|
});
|
|
});
|
|
});
|
|
|
|
it('should receive events with several types of data (including binary)', function(done){
|
|
var srv = http();
|
|
var sio = io(srv);
|
|
srv.listen(function(){
|
|
var socket = client(srv);
|
|
sio.on('connection', function(s){
|
|
s.on('multiple', function(a, b, c, d, e, f){
|
|
expect(a).to.be(1);
|
|
expect(Buffer.isBuffer(b)).to.be(true);
|
|
expect(c).to.be('3');
|
|
expect(d).to.eql([4]);
|
|
expect(Buffer.isBuffer(e)).to.be(true);
|
|
expect(Buffer.isBuffer(f[0])).to.be(true);
|
|
expect(f[1]).to.be('swag');
|
|
expect(Buffer.isBuffer(f[2])).to.be(true);
|
|
done();
|
|
});
|
|
fs.readFile(join(__dirname, 'support', 'doge.jpg'), function(err, data){
|
|
if (err) return done(err);
|
|
var buf = Buffer.from('asdfasdf', 'utf8');
|
|
socket.emit('multiple', 1, data, '3', [4], buf, [data, 'swag', buf]);
|
|
});
|
|
});
|
|
});
|
|
});
|
|
|
|
it('should not emit volatile event after regular event (polling)', function(done) {
|
|
var srv = http();
|
|
var sio = io(srv, { transports: ['polling'] });
|
|
|
|
var counter = 0;
|
|
srv.listen(function(){
|
|
sio.on('connection', function(s){
|
|
s.emit('ev', 'data');
|
|
s.volatile.emit('ev', 'data');
|
|
});
|
|
|
|
var socket = client(srv, { transports: ['polling'] });
|
|
socket.on('ev', function() {
|
|
counter++;
|
|
});
|
|
});
|
|
|
|
setTimeout(function() {
|
|
expect(counter).to.be(1);
|
|
done();
|
|
}, 200);
|
|
});
|
|
|
|
it('should not emit volatile event after regular event (ws)', function(done) {
|
|
var srv = http();
|
|
var sio = io(srv, { transports: ['websocket'] });
|
|
|
|
var counter = 0;
|
|
srv.listen(function(){
|
|
sio.on('connection', function(s){
|
|
s.emit('ev', 'data');
|
|
s.volatile.emit('ev', 'data');
|
|
});
|
|
|
|
var socket = client(srv, { transports: ['websocket'] });
|
|
socket.on('ev', function() {
|
|
counter++;
|
|
});
|
|
});
|
|
|
|
setTimeout(function() {
|
|
expect(counter).to.be(1);
|
|
done();
|
|
}, 200);
|
|
});
|
|
|
|
it('should emit volatile event (polling)', function(done) {
|
|
var srv = http();
|
|
var sio = io(srv, { transports: ['polling'] });
|
|
|
|
var counter = 0;
|
|
srv.listen(function(){
|
|
sio.on('connection', function(s){
|
|
// Wait to make sure there are no packets being sent for opening the connection
|
|
setTimeout(function() {
|
|
s.volatile.emit('ev', 'data');
|
|
}, 100);
|
|
});
|
|
|
|
var socket = client(srv, { transports: ['polling'] });
|
|
socket.on('ev', function() {
|
|
counter++;
|
|
});
|
|
});
|
|
|
|
setTimeout(function() {
|
|
expect(counter).to.be(1);
|
|
done();
|
|
}, 500);
|
|
});
|
|
|
|
it('should emit volatile event (ws)', function(done) {
|
|
var srv = http();
|
|
var sio = io(srv, { transports: ['websocket'] });
|
|
|
|
var counter = 0;
|
|
srv.listen(function(){
|
|
sio.on('connection', function(s){
|
|
// Wait to make sure there are no packets being sent for opening the connection
|
|
setTimeout(function() {
|
|
s.volatile.emit('ev', 'data');
|
|
}, 20);
|
|
});
|
|
|
|
var socket = client(srv, { transports: ['websocket'] });
|
|
socket.on('ev', function() {
|
|
counter++;
|
|
});
|
|
});
|
|
|
|
setTimeout(function() {
|
|
expect(counter).to.be(1);
|
|
done();
|
|
}, 200);
|
|
});
|
|
|
|
it('should emit only one consecutive volatile event (polling)', function(done) {
|
|
var srv = http();
|
|
var sio = io(srv, { transports: ['polling'] });
|
|
|
|
var counter = 0;
|
|
srv.listen(function(){
|
|
sio.on('connection', function(s){
|
|
// Wait to make sure there are no packets being sent for opening the connection
|
|
setTimeout(function() {
|
|
s.volatile.emit('ev', 'data');
|
|
s.volatile.emit('ev', 'data');
|
|
}, 100);
|
|
});
|
|
|
|
var socket = client(srv, { transports: ['polling'] });
|
|
socket.on('ev', function() {
|
|
counter++;
|
|
});
|
|
});
|
|
|
|
setTimeout(function() {
|
|
expect(counter).to.be(1);
|
|
done();
|
|
}, 500);
|
|
});
|
|
|
|
it('should emit only one consecutive volatile event (ws)', function(done) {
|
|
var srv = http();
|
|
var sio = io(srv, { transports: ['websocket'] });
|
|
|
|
var counter = 0;
|
|
srv.listen(function(){
|
|
sio.on('connection', function(s){
|
|
// Wait to make sure there are no packets being sent for opening the connection
|
|
setTimeout(function() {
|
|
s.volatile.emit('ev', 'data');
|
|
s.volatile.emit('ev', 'data');
|
|
}, 20);
|
|
});
|
|
|
|
var socket = client(srv, { transports: ['websocket'] });
|
|
socket.on('ev', function() {
|
|
counter++;
|
|
});
|
|
});
|
|
|
|
setTimeout(function() {
|
|
expect(counter).to.be(1);
|
|
done();
|
|
}, 200);
|
|
});
|
|
|
|
it('should emit regular events after trying a failed volatile event (polling)', function(done) {
|
|
var srv = http();
|
|
var sio = io(srv, { transports: ['polling'] });
|
|
|
|
var counter = 0;
|
|
srv.listen(function(){
|
|
sio.on('connection', function(s){
|
|
// Wait to make sure there are no packets being sent for opening the connection
|
|
setTimeout(function() {
|
|
s.emit('ev', 'data');
|
|
s.volatile.emit('ev', 'data');
|
|
s.emit('ev', 'data');
|
|
}, 20);
|
|
});
|
|
|
|
var socket = client(srv, { transports: ['polling'] });
|
|
socket.on('ev', function() {
|
|
counter++;
|
|
});
|
|
});
|
|
|
|
setTimeout(function() {
|
|
expect(counter).to.be(2);
|
|
done();
|
|
}, 200);
|
|
});
|
|
|
|
it('should emit regular events after trying a failed volatile event (ws)', function(done) {
|
|
var srv = http();
|
|
var sio = io(srv, { transports: ['websocket'] });
|
|
|
|
var counter = 0;
|
|
srv.listen(function(){
|
|
sio.on('connection', function(s){
|
|
// Wait to make sure there are no packets being sent for opening the connection
|
|
setTimeout(function() {
|
|
s.emit('ev', 'data');
|
|
s.volatile.emit('ev', 'data');
|
|
s.emit('ev', 'data');
|
|
}, 20);
|
|
});
|
|
|
|
var socket = client(srv, { transports: ['websocket'] });
|
|
socket.on('ev', function() {
|
|
counter++;
|
|
});
|
|
});
|
|
|
|
setTimeout(function() {
|
|
expect(counter).to.be(2);
|
|
done();
|
|
}, 200);
|
|
});
|
|
|
|
it('should emit message events through `send`', function(done){
|
|
var srv = http();
|
|
var sio = io(srv);
|
|
srv.listen(function(){
|
|
var socket = client(srv);
|
|
socket.on('message', function(a){
|
|
expect(a).to.be('a');
|
|
done();
|
|
});
|
|
sio.on('connection', function(s){
|
|
s.send('a');
|
|
});
|
|
});
|
|
});
|
|
|
|
it('should receive event with callbacks', function(done){
|
|
var srv = http();
|
|
var sio = io(srv);
|
|
srv.listen(function(){
|
|
var socket = client(srv);
|
|
sio.on('connection', function(s){
|
|
s.on('woot', function(fn){
|
|
fn(1, 2);
|
|
});
|
|
socket.emit('woot', function(a, b){
|
|
expect(a).to.be(1);
|
|
expect(b).to.be(2);
|
|
done();
|
|
});
|
|
});
|
|
});
|
|
});
|
|
|
|
it('should receive all events emitted from namespaced client immediately and in order', function(done) {
|
|
var srv = http();
|
|
var sio = io(srv);
|
|
var total = 0;
|
|
srv.listen(function(){
|
|
sio.of('/chat', function(s){
|
|
s.on('hi', function(letter){
|
|
total++;
|
|
if (total == 2 && letter == 'b') {
|
|
done();
|
|
} else if (total == 1 && letter != 'a') {
|
|
throw new Error('events out of order');
|
|
}
|
|
});
|
|
});
|
|
|
|
var chat = client(srv, '/chat');
|
|
chat.emit('hi', 'a');
|
|
setTimeout(function() {
|
|
chat.emit('hi', 'b');
|
|
}, 50);
|
|
});
|
|
});
|
|
|
|
it('should emit events with callbacks', function(done){
|
|
var srv = http();
|
|
var sio = io(srv);
|
|
srv.listen(function(){
|
|
var socket = client(srv);
|
|
sio.on('connection', function(s){
|
|
socket.on('hi', function(fn){
|
|
fn();
|
|
});
|
|
s.emit('hi', function(){
|
|
done();
|
|
});
|
|
});
|
|
});
|
|
});
|
|
|
|
it('should receive events with args and callback', function(done){
|
|
var srv = http();
|
|
var sio = io(srv);
|
|
srv.listen(function(){
|
|
var socket = client(srv);
|
|
sio.on('connection', function(s){
|
|
s.on('woot', function(a, b, fn){
|
|
expect(a).to.be(1);
|
|
expect(b).to.be(2);
|
|
fn();
|
|
});
|
|
socket.emit('woot', 1, 2, function(){
|
|
done();
|
|
});
|
|
});
|
|
});
|
|
});
|
|
|
|
it('should emit events with args and callback', function(done){
|
|
var srv = http();
|
|
var sio = io(srv);
|
|
srv.listen(function(){
|
|
var socket = client(srv);
|
|
sio.on('connection', function(s){
|
|
socket.on('hi', function(a, b, fn){
|
|
expect(a).to.be(1);
|
|
expect(b).to.be(2);
|
|
fn();
|
|
});
|
|
s.emit('hi', 1, 2, function(){
|
|
done();
|
|
});
|
|
});
|
|
});
|
|
});
|
|
|
|
it('should receive events with binary args and callbacks', function(done) {
|
|
var srv = http();
|
|
var sio = io(srv);
|
|
srv.listen(function(){
|
|
var socket = client(srv);
|
|
sio.on('connection', function(s){
|
|
s.on('woot', function(buf, fn){
|
|
expect(Buffer.isBuffer(buf)).to.be(true);
|
|
fn(1, 2);
|
|
});
|
|
socket.emit('woot', Buffer.alloc(3), function(a, b){
|
|
expect(a).to.be(1);
|
|
expect(b).to.be(2);
|
|
done();
|
|
});
|
|
});
|
|
});
|
|
});
|
|
|
|
it('should emit events with binary args and callback', function(done){
|
|
var srv = http();
|
|
var sio = io(srv);
|
|
srv.listen(function(){
|
|
var socket = client(srv);
|
|
sio.on('connection', function(s){
|
|
socket.on('hi', function(a, fn){
|
|
expect(Buffer.isBuffer(a)).to.be(true);
|
|
fn();
|
|
});
|
|
s.emit('hi', Buffer.alloc(4), function(){
|
|
done();
|
|
});
|
|
});
|
|
});
|
|
});
|
|
|
|
it('should emit events and receive binary data in a callback', function(done) {
|
|
var srv = http();
|
|
var sio = io(srv);
|
|
srv.listen(function(){
|
|
var socket = client(srv);
|
|
sio.on('connection', function(s){
|
|
socket.on('hi', function(fn){
|
|
fn(Buffer.alloc(1));
|
|
});
|
|
s.emit('hi', function(a){
|
|
expect(Buffer.isBuffer(a)).to.be(true);
|
|
done();
|
|
});
|
|
});
|
|
});
|
|
});
|
|
|
|
it('should receive events and pass binary data in a callback', function(done) {
|
|
var srv = http();
|
|
var sio = io(srv);
|
|
srv.listen(function(){
|
|
var socket = client(srv);
|
|
sio.on('connection', function(s){
|
|
s.on('woot', function(fn){
|
|
fn(Buffer.alloc(2));
|
|
});
|
|
socket.emit('woot', function(a){
|
|
expect(Buffer.isBuffer(a)).to.be(true);
|
|
done();
|
|
});
|
|
});
|
|
});
|
|
});
|
|
|
|
it('should have access to the client', function(done){
|
|
var srv = http();
|
|
var sio = io(srv);
|
|
srv.listen(function(){
|
|
var socket = client(srv);
|
|
sio.on('connection', function(s){
|
|
expect(s.client).to.be.an('object');
|
|
done();
|
|
});
|
|
});
|
|
});
|
|
|
|
it('should have access to the connection', function(done){
|
|
var srv = http();
|
|
var sio = io(srv);
|
|
srv.listen(function(){
|
|
var socket = client(srv);
|
|
sio.on('connection', function(s){
|
|
expect(s.client.conn).to.be.an('object');
|
|
expect(s.conn).to.be.an('object');
|
|
done();
|
|
});
|
|
});
|
|
});
|
|
|
|
it('should have access to the request', function(done){
|
|
var srv = http();
|
|
var sio = io(srv);
|
|
srv.listen(function(){
|
|
var socket = client(srv);
|
|
sio.on('connection', function(s){
|
|
expect(s.client.request.headers).to.be.an('object');
|
|
expect(s.request.headers).to.be.an('object');
|
|
done();
|
|
});
|
|
});
|
|
});
|
|
|
|
it('should see query parameters in the request', function(done) {
|
|
var srv = http();
|
|
var sio = io(srv);
|
|
srv.listen(function() {
|
|
var socket = client(srv, {query: {key1: 1, key2: 2}});
|
|
sio.on('connection', function(s) {
|
|
var parsed = require('url').parse(s.request.url);
|
|
var query = require('querystring').parse(parsed.query);
|
|
expect(query.key1).to.be('1');
|
|
expect(query.key2).to.be('2');
|
|
done();
|
|
});
|
|
});
|
|
});
|
|
|
|
it('should see query parameters sent from secondary namespace connections in handshake object', function(done){
|
|
var srv = http();
|
|
var sio = io(srv);
|
|
var client1 = client(srv);
|
|
var client2 = client(srv, '/connection2', {query: {key1: 'aa', key2: '&=bb'}});
|
|
sio.on('connection', function(s){
|
|
});
|
|
sio.of('/connection2').on('connection', function(s){
|
|
expect(s.handshake.query.key1).to.be('aa');
|
|
expect(s.handshake.query.key2).to.be('&=bb');
|
|
done();
|
|
});
|
|
});
|
|
|
|
it('should see the query options sent in the Socket.IO handshake (specific to the given socket)', (done) => {
|
|
const srv = http();
|
|
const sio = io(srv);
|
|
const socket = client(srv, '/namespace',{ query: { key1: 'a', key2: 'b' }}); // manager-specific query option
|
|
socket.query = { key2: 'c' }; // socket-specific query option
|
|
|
|
const success = () => {
|
|
sio.close();
|
|
socket.close();
|
|
done();
|
|
}
|
|
|
|
sio.of('/namespace').on('connection', (s) => {
|
|
expect(s.handshake.query.key1).to.be('a'); // in the query params
|
|
expect(s.handshake.query.key2).to.be('c'); // in the Socket.IO handshake
|
|
success();
|
|
});
|
|
});
|
|
|
|
it('should handle very large json', function(done){
|
|
this.timeout(30000);
|
|
var srv = http();
|
|
var sio = io(srv, { perMessageDeflate: false });
|
|
var received = 0;
|
|
srv.listen(function(){
|
|
var socket = client(srv);
|
|
socket.on('big', function(a){
|
|
expect(Buffer.isBuffer(a.json)).to.be(false);
|
|
if (++received == 3)
|
|
done();
|
|
else
|
|
socket.emit('big', a);
|
|
});
|
|
sio.on('connection', function(s){
|
|
fs.readFile(join(__dirname, 'fixtures', 'big.json'), function(err, data){
|
|
if (err) return done(err);
|
|
data = JSON.parse(data);
|
|
s.emit('big', {hello: 'friend', json: data});
|
|
});
|
|
s.on('big', function(a){
|
|
s.emit('big', a);
|
|
});
|
|
});
|
|
});
|
|
});
|
|
|
|
it('should handle very large binary data', function(done){
|
|
this.timeout(30000);
|
|
var srv = http();
|
|
var sio = io(srv, { perMessageDeflate: false });
|
|
var received = 0;
|
|
srv.listen(function(){
|
|
var socket = client(srv);
|
|
socket.on('big', function(a){
|
|
expect(Buffer.isBuffer(a.image)).to.be(true);
|
|
if (++received == 3)
|
|
done();
|
|
else
|
|
socket.emit('big', a);
|
|
});
|
|
sio.on('connection', function(s){
|
|
fs.readFile(join(__dirname, 'fixtures', 'big.jpg'), function(err, data){
|
|
if (err) return done(err);
|
|
s.emit('big', {hello: 'friend', image: data});
|
|
});
|
|
s.on('big', function(a){
|
|
expect(Buffer.isBuffer(a.image)).to.be(true);
|
|
s.emit('big', a);
|
|
});
|
|
});
|
|
});
|
|
});
|
|
|
|
it('should be able to emit after server close and restart', function(done){
|
|
var srv = http();
|
|
var sio = io(srv);
|
|
|
|
sio.on('connection', function(socket){
|
|
socket.on('ev', function(data){
|
|
expect(data).to.be('payload');
|
|
done();
|
|
});
|
|
});
|
|
|
|
srv.listen(function(){
|
|
var port = srv.address().port;
|
|
var clientSocket = client(srv, { reconnectionAttempts: 10, reconnectionDelay: 100 });
|
|
clientSocket.once('connect', function(){
|
|
srv.close(function(){
|
|
clientSocket.on('reconnect', function(){
|
|
clientSocket.emit('ev', 'payload');
|
|
});
|
|
sio.listen(port);
|
|
});
|
|
});
|
|
});
|
|
});
|
|
|
|
it('should enable compression by default', function(done){
|
|
var srv = http();
|
|
var sio = io(srv);
|
|
srv.listen(function(){
|
|
var socket = client(srv, '/chat');
|
|
sio.of('/chat').on('connection', function(s){
|
|
s.conn.once('packetCreate', function(packet) {
|
|
expect(packet.options.compress).to.be(true);
|
|
done();
|
|
});
|
|
sio.of('/chat').emit('woot', 'hi');
|
|
});
|
|
});
|
|
});
|
|
|
|
it('should disable compression', function(done){
|
|
var srv = http();
|
|
var sio = io(srv);
|
|
srv.listen(function(){
|
|
var socket = client(srv, '/chat');
|
|
sio.of('/chat').on('connection', function(s){
|
|
s.conn.once('packetCreate', function(packet) {
|
|
expect(packet.options.compress).to.be(false);
|
|
done();
|
|
});
|
|
sio.of('/chat').compress(false).emit('woot', 'hi');
|
|
});
|
|
});
|
|
});
|
|
|
|
it('should error with raw binary and warn', function(done){
|
|
var srv = http();
|
|
var sio = io(srv);
|
|
srv.listen(function(){
|
|
var socket = client(srv, { reconnection: false });
|
|
sio.on('connection', function(s){
|
|
s.conn.on('upgrade', function(){
|
|
console.log('\u001b[96mNote: warning expected and normal in test.\u001b[39m');
|
|
socket.io.engine.write('5woooot');
|
|
setTimeout(function(){
|
|
done();
|
|
}, 100);
|
|
});
|
|
});
|
|
});
|
|
});
|
|
|
|
it('should not crash when receiving an error packet without handler', function(done){
|
|
var srv = http();
|
|
var sio = io(srv);
|
|
srv.listen(function(){
|
|
var socket = client(srv, { reconnection: false });
|
|
sio.on('connection', function(s){
|
|
s.conn.on('upgrade', function(){
|
|
console.log('\u001b[96mNote: warning expected and normal in test.\u001b[39m');
|
|
socket.io.engine.write('44["handle me please"]');
|
|
setTimeout(function(){
|
|
done();
|
|
}, 100);
|
|
});
|
|
});
|
|
});
|
|
});
|
|
|
|
it('should not crash with raw binary', function(done){
|
|
var srv = http();
|
|
var sio = io(srv);
|
|
srv.listen(function(){
|
|
var socket = client(srv, { reconnection: false });
|
|
sio.on('connection', function(s){
|
|
s.once('error', function(err){
|
|
expect(err.message).to.match(/Illegal attachments/);
|
|
done();
|
|
});
|
|
s.conn.on('upgrade', function(){
|
|
socket.io.engine.write('5woooot');
|
|
});
|
|
});
|
|
});
|
|
});
|
|
|
|
it('should handle empty binary packet', function(done){
|
|
var srv = http();
|
|
var sio = io(srv);
|
|
srv.listen(function(){
|
|
var socket = client(srv, { reconnection: false });
|
|
sio.on('connection', function(s){
|
|
s.once('error', function(err){
|
|
expect(err.message).to.match(/Illegal attachments/);
|
|
done();
|
|
});
|
|
s.conn.on('upgrade', function(){
|
|
socket.io.engine.write('5');
|
|
});
|
|
});
|
|
});
|
|
});
|
|
|
|
it('should not crash when messing with Object prototype (and other globals)', function(done){
|
|
Object.prototype.foo = 'bar';
|
|
global.File = '';
|
|
// global.Blob = [];
|
|
var srv = http();
|
|
var sio = io(srv);
|
|
srv.listen(function(){
|
|
var socket = client(srv);
|
|
|
|
sio.on('connection', function(s){
|
|
s.disconnect(true);
|
|
sio.close();
|
|
setTimeout(function(){
|
|
done();
|
|
}, 100);
|
|
});
|
|
});
|
|
});
|
|
|
|
it("should ignore a packet received after disconnection", (done) => {
|
|
const srv = http();
|
|
const sio = io(srv);
|
|
|
|
srv.listen(() => {
|
|
const clientSocket = client(srv);
|
|
|
|
const success = () => {
|
|
clientSocket.close();
|
|
sio.close();
|
|
done();
|
|
};
|
|
|
|
sio.on("connection", (socket) => {
|
|
socket.on("test", () => {
|
|
done(new Error("should not happen"));
|
|
});
|
|
socket.on("disconnect", success);
|
|
});
|
|
|
|
clientSocket.on("connect", () => {
|
|
clientSocket.emit("test", Buffer.alloc(10));
|
|
clientSocket.disconnect();
|
|
});
|
|
});
|
|
});
|
|
|
|
it("should leave all rooms joined after a middleware failure", (done) => {
|
|
const srv = http().listen(0);
|
|
const sio = io(srv);
|
|
const clientSocket = client(srv, "/");
|
|
|
|
sio.use((socket, next) => {
|
|
socket.join("room1");
|
|
next(new Error("nope"));
|
|
});
|
|
|
|
clientSocket.on("error", () => {
|
|
expect(sio.of("/").adapter.rooms).to.eql(0);
|
|
|
|
clientSocket.disconnect();
|
|
sio.close();
|
|
done();
|
|
});
|
|
});
|
|
|
|
it("should not join rooms after disconnection", (done) => {
|
|
const srv = http().listen(0);
|
|
const sio = io(srv);
|
|
const clientSocket = client(srv, "/");
|
|
|
|
sio.on("connection", (socket) => {
|
|
socket.disconnect();
|
|
socket.join("room1");
|
|
});
|
|
|
|
clientSocket.on("disconnect", () => {
|
|
expect(sio.of("/").adapter.rooms).to.eql(0);
|
|
|
|
sio.close();
|
|
done();
|
|
});
|
|
});
|
|
|
|
it('should always trigger the callback (if provided) when joining a room', function(done){
|
|
var srv = http();
|
|
var sio = io(srv);
|
|
|
|
srv.listen(function(){
|
|
var socket = client(srv);
|
|
sio.on('connection', function(s){
|
|
s.join('a', function(){
|
|
s.join('a', done);
|
|
});
|
|
});
|
|
});
|
|
});
|
|
|
|
});
|
|
|
|
describe('messaging many', function(){
|
|
it('emits to a namespace', function(done){
|
|
var srv = http();
|
|
var sio = io(srv);
|
|
var total = 2;
|
|
|
|
srv.listen(function(){
|
|
var socket1 = client(srv, { multiplex: false });
|
|
var socket2 = client(srv, { multiplex: false });
|
|
var socket3 = client(srv, '/test');
|
|
socket1.on('a', function(a){
|
|
expect(a).to.be('b');
|
|
--total || done();
|
|
});
|
|
socket2.on('a', function(a){
|
|
expect(a).to.be('b');
|
|
--total || done();
|
|
});
|
|
socket3.on('a', function(){ done(new Error('not')); });
|
|
|
|
var sockets = 3;
|
|
sio.on('connection', function(socket){
|
|
--sockets || emit();
|
|
});
|
|
sio.of('/test', function(socket){
|
|
--sockets || emit();
|
|
});
|
|
|
|
function emit(){
|
|
sio.emit('a', 'b');
|
|
}
|
|
});
|
|
});
|
|
|
|
it('emits binary data to a namespace', function(done){
|
|
var srv = http();
|
|
var sio = io(srv);
|
|
var total = 2;
|
|
|
|
srv.listen(function(){
|
|
var socket1 = client(srv, { multiplex: false });
|
|
var socket2 = client(srv, { multiplex: false });
|
|
var socket3 = client(srv, '/test');
|
|
socket1.on('bin', function(a){
|
|
expect(Buffer.isBuffer(a)).to.be(true);
|
|
--total || done();
|
|
});
|
|
socket2.on('bin', function(a){
|
|
expect(Buffer.isBuffer(a)).to.be(true);
|
|
--total || done();
|
|
});
|
|
socket3.on('bin', function(){ done(new Error('not')); });
|
|
|
|
var sockets = 3;
|
|
sio.on('connection', function(socket){
|
|
--sockets || emit();
|
|
});
|
|
sio.of('/test', function(socket){
|
|
--sockets || emit();
|
|
});
|
|
|
|
function emit(){
|
|
sio.emit('bin', Buffer.alloc(10));
|
|
}
|
|
});
|
|
});
|
|
|
|
it('emits to the rest', function(done){
|
|
var srv = http();
|
|
var sio = io(srv);
|
|
var total = 2;
|
|
|
|
srv.listen(function(){
|
|
var socket1 = client(srv, { multiplex: false });
|
|
var socket2 = client(srv, { multiplex: false });
|
|
var socket3 = client(srv, '/test');
|
|
socket1.on('a', function(a){
|
|
expect(a).to.be('b');
|
|
socket1.emit('finish');
|
|
});
|
|
socket2.emit('broadcast');
|
|
socket2.on('a', function(){ done(new Error('done')); });
|
|
socket3.on('a', function(){ done(new Error('not')); });
|
|
|
|
var sockets = 2;
|
|
sio.on('connection', function(socket){
|
|
socket.on('broadcast', function(){
|
|
socket.broadcast.emit('a', 'b');
|
|
});
|
|
socket.on('finish', function(){
|
|
done();
|
|
});
|
|
});
|
|
});
|
|
});
|
|
|
|
it('emits to rooms', function(done){
|
|
var srv = http();
|
|
var sio = io(srv);
|
|
var total = 2;
|
|
|
|
srv.listen(function(){
|
|
var socket1 = client(srv, { multiplex: false });
|
|
var socket2 = client(srv, { multiplex: false });
|
|
|
|
socket2.on('a', function(){
|
|
done(new Error('not'));
|
|
});
|
|
socket1.on('a', function(){
|
|
done();
|
|
});
|
|
socket1.emit('join', 'woot', function(){
|
|
socket1.emit('emit', 'woot');
|
|
});
|
|
|
|
sio.on('connection', function(socket){
|
|
socket.on('join', function(room, fn){
|
|
socket.join(room, fn);
|
|
});
|
|
|
|
socket.on('emit', function(room){
|
|
sio.in(room).emit('a');
|
|
});
|
|
});
|
|
});
|
|
});
|
|
|
|
it('emits to rooms avoiding dupes', function(done){
|
|
var srv = http();
|
|
var sio = io(srv);
|
|
var total = 2;
|
|
|
|
srv.listen(function(){
|
|
var socket1 = client(srv, { multiplex: false });
|
|
var socket2 = client(srv, { multiplex: false });
|
|
|
|
socket2.on('a', function(){
|
|
done(new Error('not'));
|
|
});
|
|
socket1.on('a', function(){
|
|
--total || done();
|
|
});
|
|
socket2.on('b', function(){
|
|
--total || done();
|
|
});
|
|
|
|
socket1.emit('join', 'woot');
|
|
socket1.emit('join', 'test');
|
|
socket2.emit('join', 'third', function(){
|
|
socket2.emit('emit');
|
|
});
|
|
|
|
sio.on('connection', function(socket){
|
|
socket.on('join', function(room, fn){
|
|
socket.join(room, fn);
|
|
});
|
|
|
|
socket.on('emit', function(room){
|
|
sio.in('woot').in('test').emit('a');
|
|
sio.in('third').emit('b');
|
|
});
|
|
});
|
|
});
|
|
});
|
|
|
|
it('broadcasts to rooms', function(done){
|
|
var srv = http();
|
|
var sio = io(srv);
|
|
var total = 2;
|
|
|
|
srv.listen(function(){
|
|
var socket1 = client(srv, { multiplex: false });
|
|
var socket2 = client(srv, { multiplex: false });
|
|
var socket3 = client(srv, { multiplex: false });
|
|
|
|
socket1.emit('join', 'woot');
|
|
socket2.emit('join', 'test');
|
|
socket3.emit('join', 'test', function(){
|
|
socket3.emit('broadcast');
|
|
});
|
|
|
|
socket1.on('a', function(){
|
|
done(new Error('not'));
|
|
});
|
|
socket2.on('a', function(){
|
|
--total || done();
|
|
});
|
|
socket3.on('a', function(){
|
|
done(new Error('not'));
|
|
});
|
|
socket3.on('b', function(){
|
|
--total || done();
|
|
});
|
|
|
|
sio.on('connection', function(socket){
|
|
socket.on('join', function(room, fn){
|
|
socket.join(room, fn);
|
|
});
|
|
|
|
socket.on('broadcast', function(){
|
|
socket.broadcast.to('test').emit('a');
|
|
socket.emit('b');
|
|
});
|
|
});
|
|
});
|
|
});
|
|
|
|
it('broadcasts binary data to rooms', function(done){
|
|
var srv = http();
|
|
var sio = io(srv);
|
|
var total = 2;
|
|
|
|
srv.listen(function(){
|
|
var socket1 = client(srv, { multiplex: false });
|
|
var socket2 = client(srv, { multiplex: false });
|
|
var socket3 = client(srv, { multiplex: false });
|
|
|
|
socket1.emit('join', 'woot');
|
|
socket2.emit('join', 'test');
|
|
socket3.emit('join', 'test', function(){
|
|
socket3.emit('broadcast');
|
|
});
|
|
|
|
socket1.on('bin', function(data){
|
|
throw new Error('got bin in socket1');
|
|
});
|
|
socket2.on('bin', function(data){
|
|
expect(Buffer.isBuffer(data)).to.be(true);
|
|
--total || done();
|
|
});
|
|
socket2.on('bin2', function(data) {
|
|
throw new Error('socket2 got bin2');
|
|
});
|
|
socket3.on('bin', function(data) {
|
|
throw new Error('socket3 got bin');
|
|
});
|
|
socket3.on('bin2', function(data) {
|
|
expect(Buffer.isBuffer(data)).to.be(true);
|
|
--total || done();
|
|
});
|
|
|
|
sio.on('connection', function(socket){
|
|
socket.on('join', function(room, fn){
|
|
socket.join(room, fn);
|
|
});
|
|
socket.on('broadcast', function(){
|
|
socket.broadcast.to('test').emit('bin', Buffer.alloc(5));
|
|
socket.emit('bin2', Buffer.alloc(5));
|
|
});
|
|
});
|
|
});
|
|
});
|
|
|
|
|
|
it('keeps track of rooms', function(done){
|
|
var srv = http();
|
|
var sio = io(srv);
|
|
|
|
srv.listen(function(){
|
|
var socket = client(srv);
|
|
sio.on('connection', function(s){
|
|
s.join('a', function(){
|
|
expect(Object.keys(s.rooms)).to.eql([s.id, 'a']);
|
|
s.join('b', function(){
|
|
expect(Object.keys(s.rooms)).to.eql([s.id, 'a', 'b']);
|
|
s.join( 'c', function(){
|
|
expect(Object.keys(s.rooms)).to.eql([s.id, 'a', 'b', 'c']);
|
|
s.leave('b', function(){
|
|
expect(Object.keys(s.rooms)).to.eql([s.id, 'a', 'c']);
|
|
s.leaveAll();
|
|
expect(Object.keys(s.rooms)).to.eql([]);
|
|
done();
|
|
});
|
|
});
|
|
});
|
|
});
|
|
});
|
|
});
|
|
});
|
|
|
|
it('deletes empty rooms', function(done) {
|
|
var srv = http();
|
|
var sio = io(srv);
|
|
|
|
srv.listen(function(){
|
|
var socket = client(srv);
|
|
sio.on('connection', function(s){
|
|
s.join('a', function(){
|
|
expect(s.nsp.adapter.rooms).to.have.key('a');
|
|
s.leave('a', function(){
|
|
expect(s.nsp.adapter.rooms).to.not.have.key('a');
|
|
done();
|
|
});
|
|
});
|
|
});
|
|
});
|
|
});
|
|
|
|
it('should properly cleanup left rooms', function(done){
|
|
var srv = http();
|
|
var sio = io(srv);
|
|
|
|
srv.listen(function(){
|
|
var socket = client(srv);
|
|
sio.on('connection', function(s){
|
|
s.join('a', function(){
|
|
expect(Object.keys(s.rooms)).to.eql([s.id, 'a']);
|
|
s.join('b', function(){
|
|
expect(Object.keys(s.rooms)).to.eql([s.id, 'a', 'b']);
|
|
s.leave('unknown', function(){
|
|
expect(Object.keys(s.rooms)).to.eql([s.id, 'a', 'b']);
|
|
s.leaveAll();
|
|
expect(Object.keys(s.rooms)).to.eql([]);
|
|
done();
|
|
});
|
|
});
|
|
});
|
|
});
|
|
});
|
|
});
|
|
|
|
it('allows to join several rooms at once', function(done) {
|
|
var srv = http();
|
|
var sio = io(srv);
|
|
|
|
srv.listen(function(){
|
|
var socket = client(srv);
|
|
sio.on('connection', function(s){
|
|
s.join(['a', 'b', 'c'], function(){
|
|
expect(Object.keys(s.rooms)).to.eql([s.id, 'a', 'b', 'c']);
|
|
done();
|
|
});
|
|
});
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('middleware', function(done){
|
|
var Socket = require('../lib/socket');
|
|
|
|
it('should call functions', function(done){
|
|
var srv = http();
|
|
var sio = io(srv);
|
|
var run = 0;
|
|
sio.use(function(socket, next){
|
|
expect(socket).to.be.a(Socket);
|
|
run++;
|
|
next();
|
|
});
|
|
sio.use(function(socket, next){
|
|
expect(socket).to.be.a(Socket);
|
|
run++;
|
|
next();
|
|
});
|
|
srv.listen(function(){
|
|
var socket = client(srv);
|
|
socket.on('connect', function(){
|
|
expect(run).to.be(2);
|
|
done();
|
|
});
|
|
});
|
|
});
|
|
|
|
it('should pass errors', function(done){
|
|
var srv = http();
|
|
var sio = io(srv);
|
|
var run = 0;
|
|
sio.use(function(socket, next){
|
|
next(new Error('Authentication error'));
|
|
});
|
|
sio.use(function(socket, next){
|
|
done(new Error('nope'));
|
|
});
|
|
srv.listen(function(){
|
|
var socket = client(srv);
|
|
socket.on('connect', function(){
|
|
done(new Error('nope'));
|
|
});
|
|
socket.on('error', function(err){
|
|
expect(err).to.be('Authentication error');
|
|
done();
|
|
});
|
|
});
|
|
});
|
|
|
|
it('should pass `data` of error object', function(done){
|
|
var srv = http();
|
|
var sio = io(srv);
|
|
var run = 0;
|
|
sio.use(function(socket, next){
|
|
var err = new Error('Authentication error');
|
|
err.data = { a: 'b', c: 3 };
|
|
next(err);
|
|
});
|
|
srv.listen(function(){
|
|
var socket = client(srv);
|
|
socket.on('connect', function(){
|
|
done(new Error('nope'));
|
|
});
|
|
socket.on('error', function(err){
|
|
expect(err).to.eql({ a: 'b', c: 3 });
|
|
done();
|
|
});
|
|
});
|
|
});
|
|
|
|
it('should only call connection after fns', function(done){
|
|
var srv = http();
|
|
var sio = io(srv);
|
|
sio.use(function(socket, next){
|
|
socket.name = 'guillermo';
|
|
next();
|
|
});
|
|
srv.listen(function(){
|
|
var socket = client(srv);
|
|
sio.on('connection', function(socket){
|
|
expect(socket.name).to.be('guillermo');
|
|
done();
|
|
});
|
|
});
|
|
});
|
|
|
|
it('should only call connection after (lengthy) fns', function(done){
|
|
var srv = http();
|
|
var sio = io(srv);
|
|
var authenticated = false;
|
|
|
|
sio.use(function(socket, next){
|
|
setTimeout(function () {
|
|
authenticated = true;
|
|
next();
|
|
}, 300);
|
|
});
|
|
srv.listen(function(){
|
|
var socket = client(srv);
|
|
socket.on('connect', function(){
|
|
expect(authenticated).to.be(true);
|
|
done();
|
|
});
|
|
});
|
|
});
|
|
|
|
it('should be ignored if socket gets closed', function(done){
|
|
var srv = http();
|
|
var sio = io(srv);
|
|
var socket;
|
|
sio.use(function(s, next){
|
|
socket.io.engine.on('open', function(){
|
|
socket.io.engine.close();
|
|
s.client.conn.on('close', function(){
|
|
process.nextTick(next);
|
|
setTimeout(function(){
|
|
done();
|
|
}, 50);
|
|
});
|
|
});
|
|
});
|
|
srv.listen(function(){
|
|
socket = client(srv);
|
|
sio.on('connection', function(socket){
|
|
done(new Error('should not fire'));
|
|
});
|
|
});
|
|
});
|
|
|
|
it('should call functions in expected order', function(done){
|
|
var srv = http();
|
|
var sio = io(srv);
|
|
var result = [];
|
|
|
|
sio.use(function(socket, next) {
|
|
result.push(1);
|
|
setTimeout(next, 50);
|
|
});
|
|
sio.use(function(socket, next) {
|
|
result.push(2);
|
|
setTimeout(next, 50);
|
|
});
|
|
sio.of('/chat').use(function(socket, next) {
|
|
result.push(3);
|
|
setTimeout(next, 50);
|
|
});
|
|
sio.of('/chat').use(function(socket, next) {
|
|
result.push(4);
|
|
setTimeout(next, 50);
|
|
});
|
|
|
|
srv.listen(function() {
|
|
var chat = client(srv, '/chat');
|
|
chat.on('connect', function() {
|
|
expect(result).to.eql([1, 2, 3, 4]);
|
|
done();
|
|
});
|
|
});
|
|
});
|
|
|
|
it('should disable the merge of handshake packets', function(done){
|
|
var srv = http();
|
|
var sio = io();
|
|
sio.use(function(socket, next){
|
|
next();
|
|
});
|
|
sio.listen(srv);
|
|
var socket = client(srv);
|
|
socket.on('connect', function(){
|
|
done();
|
|
});
|
|
});
|
|
|
|
it('should work with a custom namespace', (done) => {
|
|
var srv = http();
|
|
var sio = io();
|
|
sio.listen(srv);
|
|
sio.of('/chat').use(function(socket, next){
|
|
next();
|
|
});
|
|
|
|
var count = 0;
|
|
client(srv, '/').on('connect', () => {
|
|
if (++count === 2) done();
|
|
});
|
|
client(srv, '/chat').on('connect', () => {
|
|
if (++count === 2) done();
|
|
});
|
|
});
|
|
|
|
it("should only set `connected` to true after the middleware execution", (done) => {
|
|
const httpServer = http();
|
|
const sio = io(httpServer);
|
|
|
|
const clientSocket = client(httpServer, "/");
|
|
|
|
sio.use((socket, next) => {
|
|
expect(socket.connected).to.be(false);
|
|
expect(socket.disconnected).to.be(true);
|
|
next();
|
|
});
|
|
|
|
sio.on("connection", (socket) => {
|
|
expect(socket.connected).to.be(true);
|
|
expect(socket.disconnected).to.be(false);
|
|
done();
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('socket middleware', function(done){
|
|
var Socket = require('../lib/socket');
|
|
|
|
it('should call functions', function(done){
|
|
var srv = http();
|
|
var sio = io(srv);
|
|
var run = 0;
|
|
|
|
srv.listen(function(){
|
|
var socket = client(srv, { multiplex: false });
|
|
|
|
socket.emit('join', 'woot');
|
|
|
|
sio.on('connection', function(socket){
|
|
socket.use(function(event, next){
|
|
expect(event).to.eql(['join', 'woot']);
|
|
event.unshift('wrap');
|
|
run++;
|
|
next();
|
|
});
|
|
socket.use(function(event, next){
|
|
expect(event).to.eql(['wrap', 'join', 'woot']);
|
|
run++;
|
|
next();
|
|
});
|
|
socket.on('wrap', function(data1, data2){
|
|
expect(data1).to.be('join');
|
|
expect(data2).to.be('woot');
|
|
expect(run).to.be(2);
|
|
done();
|
|
});
|
|
});
|
|
});
|
|
});
|
|
|
|
it('should pass errors', function(done){
|
|
var srv = http();
|
|
var sio = io(srv);
|
|
|
|
srv.listen(function(){
|
|
var clientSocket = client(srv, { multiplex: false });
|
|
|
|
clientSocket.emit('join', 'woot');
|
|
|
|
clientSocket.on('error', function(err){
|
|
expect(err).to.be('Authentication error');
|
|
done();
|
|
});
|
|
|
|
sio.on('connection', function(socket){
|
|
socket.use(function(event, next){
|
|
next(new Error('Authentication error'));
|
|
});
|
|
socket.use(function(event, next){
|
|
done(new Error('nope'));
|
|
});
|
|
|
|
socket.on('join', function(){
|
|
done(new Error('nope'));
|
|
});
|
|
});
|
|
});
|
|
});
|
|
|
|
it('should pass `data` of error object', function(done){
|
|
var srv = http();
|
|
var sio = io(srv);
|
|
|
|
srv.listen(function(){
|
|
var clientSocket = client(srv, { multiplex: false });
|
|
|
|
clientSocket.emit('join', 'woot');
|
|
|
|
clientSocket.on('error', function(err){
|
|
expect(err).to.eql({ a: 'b', c: 3 });
|
|
done();
|
|
});
|
|
|
|
sio.on('connection', function(socket){
|
|
socket.use(function(event, next){
|
|
var err = new Error('Authentication error');
|
|
err.data = { a: 'b', c: 3 };
|
|
next(err);
|
|
});
|
|
|
|
socket.on('join', function(){
|
|
done(new Error('nope'));
|
|
});
|
|
});
|
|
});
|
|
});
|
|
});
|
|
});
|