I have the following TypeScript and nodeJS file which registers a series of socket.io namespaces. I then have some mocha tests which test those namespaces, however, my first test always fails, unless I am live reloading, in which case the second time around the tests will pass. NB: the db.Line.findAll()
and similar functions are sequelize functions returning promises.
export class RealTimeStations {
public complete: Promise<boolean>;
server: any;
constructor(io: any) {
this.server = io;
this.complete = Promise.resolve(db.Line.findAll()).then(lines => {
// do some mapping to generate routes and cells
this.registerEndPoints(routes, [], cells);
}).catch(err => console.log(err))
}
registerEndPoints(routes: Array<string>, nsps: Array<any>, cells: Array<string>) {
for (let i = 0; i < routes.length; i++) {
nsps.push(this.server.of('/api/testNamespace/' + routes[i]));
let that = this;
nsp.on('connection', function (socket) {
that.emitInitialPackage(nsps[i], routes[i], cells[i]);
});
}
}
emitInitialPackage(nsp: any, name: string, cell: any) {
return db.Line.find({/* Some sequelize params*/}).then(results => {
nsp.emit('value', results);
}).catch(err => console.log(err));
}
}
I have seen this problem before, where the socketio setup wasn't being completed before the test executed, hence I moved to the promise based approach, however, this test now fails first time around but then on 2nd and subsequent livereloads, it passes...
describe('Stations Socket /api/getLine/stations', function () {
beforeEach(function (done) {
models.sequelize.sync({ force: true }).then(function () { //setup SQLite db
sequelize_fixtures.loadFile('C:/Users/George/Source/Repos/Coty%20Monitoring%20System/server/seeders/default.json', db) //seed the db
.then(function () {
app.set('port', '3000');
server = http.createServer(app);
server.listen('3000', function () { });
var io = require('socket.io').listen(server);
new RealTimeStations(io).complete.then(() => { //config socketio namespaces
socket = require('socket.io-client')('http://localhost:3000/api/testNamespace/2');
done();
});
});
})
})
describe('Setup', () => {
it('Should connect and receive correct state', function (done) {
socket.on('connect', function () {
socket.on('value', function (test) {
test.stations.should.equal('"expected value"');
done();
});
});
});
});
afterEach(function () {
socket.disconnect();
server.close();
socket = null;
})
})
Update:
The issue is that the nsp.emit('value', results);
line doesn't get executed before the complete
promise resolves. This means that when the test begins and connects to the server, the value event isn't triggered, and as the connect event is only sent once, the test just timeouts.
So I need a way of linking the complete promise to the emitInitialPackage
promise.