How to run mocha tests in a chronological order? - javascript

I've got a set of modules that run based on a global event emitter. They run based on a chronological chain of events, like so:
boot.ready
server created (because of boot.ready event)
server configured (because of server.created event)
As such, I need to create a server-test.js that performs tests in a chronological order.
Is this possible with Mocha? Something like the following?
var EventEmitter2 = require('eventemitter2').EventEmitter2,
should = require('should');
describe('server', function() {
var mediator = new EventEmitter2({
wildcard: false
});
require('../../src/routines/server/creator')(mediator);
require('../../src/routines/server/configurer')(mediator);
it('should be created after boot', function(done) {
mediator.once('server.created', function(server) {
server.should.exist;
done();
});
it('should be configured after created', function(done) {
mediator.once('server.configured', function() {
done();
});
});
mediator.emit('boot.ready');
});
});
Because there seemed to be some confusion about the way this global event emitter works, this is the server/creator.js module:
module.exports = function(mediator) {
var express = require('express');
mediator.once('boot.ready', function() {
var server = express.createServer();
//event: server created
mediator.emit('server.created', server);
});
};
As you can see, the server is created after boot.ready. This fires server.created, after which the configurer will run which will then fire server.configured.
This chain of events needs to be tested by mocha.

If I'm testing a chain of events the quick way is to do it is nested eventEmitter.once calls like this:
it('executes in the right sequence', function(done) {
mediator.once('boot.ready', function() {
mediator.once('server.created', function() {
done()
})
})
})
edit: as pointed out server.created will be fired before the test's boot.ready handler is fired. Here's a workaround:
it('executes in the right sequence', function(done) {
var bootReadyFired = false
mediator.once('boot.ready', function() {
bootReadyFired = true
})
mediator.once('server.created', function() {
assert.ok(bootReadyFired)
done()
})
})
Hope this helps.

Actually mocha use function.length to your it callbacks to know if you want them asynchronously, so with function(done) you can't known in which order they're run. function() without done argument will run them synchronously.
EDIT
Your mediator is an EventEmitter2 meaning that when you emit something, the handler will be run async. Like I said they's no way to known the order in which the are executed.
The problem is in you required modules, each event should probably be emitted in the handler of the previous. Code is better than words :
// require('../../src/routines/server/creator')(mediator);
// I guess this module creates the server, then it should emit server.created
// require('../../src/routines/server/configurer')(mediator)
// This one should listen to server.created then configure the server
// and finally emit server.configured
// So in it you should have something like this:
mediator.once('server.created', function(server) {
// Here you should configure you're server
// Once it is configured then you emit server.configured
});
Also you should know that emit is immediate in node so you'd better add your listeners before emitting.
Hope this is clear.

Related

Is there a way to put socket.io events into functions?

I wanna encapsulate socket.io events into functions to make it more readable for my project, here is an example. I am trying to put this:
io.on('connection', (socket) =>{
//code
});
Into something like this:
function isThereANewConnection() {
io.on('connection', (socket) =>{
//..return true?
});
}
function update() {
if(isThereANewConnection()) {
//do something with the socket data..
}
}
I cannot seem to figure out how i could implement this since i cannot return something from the function. Does anyone know how to do this?
You haven't really explained what you're trying to accomplish by putting "events into functions" so it's hard to know precisely what you want it to look like.
At it's heart, nodejs is an event driven environment. As such, you register event listeners and they call you when there's an event. That's the structure of the socket.io connection event.
If you don't want everything inline such as this:
io.on('connection', (socket) =>{
//code
});
You can put the event listener callback into a function itself such as:
io.on('connection', onConnection);
Then, somewhere else (either in the same module or imported into this module), you would define the onConnection function.
function onConnection(socket) {
// put your code here to handle incoming socket.io connections
socket.on('someMsg', someData => {
// handle incoming message here
});
}
Note: inline callback functions (of the type you seem to be asking to avoid) are very common in nodejs programming. One of the reasons for using them is that when they are inline, they have available to them all the variables from the parent scope (without having to pass them all as arguments) and there are times this is very useful. So, it might be a style that you will find useful rather than avoiding.
I don't think this is going to structure your code in a way that is more readable and useful to you. But if you did want this, you could use async/await.
async function getNewConnection() {
return await new Promise((resolve, reject) => {
io.on('connection', resolve);
});
}
Then in your other code:
const socket = await getNewConnection();
Really though, for this connection handler you should stick with the callback pattern. It keeps things simple for you. Run your updates when the connection comes in, and not the other way around.
Update: I have kinda found the OOP solution for this (it is not the best):
class ConnectionHandler {
init() {
this.listenForConnections();
}
listenForConnections() {
io.on('connection', (socket) =>{
//do stuff
this.newConnection = true;
this.update();
});
}
// the update method contains all the logical decisions of a class
update() {
if(this.isThereANewConnection()) {
//add connection to list.. or handle the rest of the logic
}
//render screen
}
isThereANewConnection() {
if(this.newConnection) {
this.newConnection = false;
return true;
}
return false;
}
}

Nodejs, Sinon: How to test some functions are called upon an event

Say I have an object in my code, let's say a User.
User is an eventEmitter so in many places in the code I do like:
User.on('register', notifyFriends);
User.on('register', sendWelcomeEmail);
This lines are in different files in principal.
I want to make sure that the relevant functions are called in my test so I do something like this:
describe('User Events', () => {
before(() => {
sinon.stub(userListeners, 'notifyFriends').callsFake(async () => {});
});
after(() => {
userListeners.notifyFriends.restore();
});
describe('register', () => {
it('should trigger the "notifyFriends" handler once user is registered', () => {
UserModel.emit('register');
expect(userListeners.notifyFriends).to.be.calledOnce();
});
});
});
Problem is the the function is run after the expect statement so the test fails obviously.
An easy way to solve it is to run the expect inside a Timeout block and hope that the function is called within the given time.
But I want to know if there is a better, more elegant way to do it.
The issue was different.
The code that registers to the handlers was executed before the stub was made. (So the function wasn't a spy yet)
So make sure to run the stub, only after run the rest of the code in the application that registers to the evetns.

checking that an event fired with mocha

How can I test that an element fired an event with mocha? I've got an ugly solution working, but it's not very readable, takes a long time to time out when it fails, and doesn't give good failure messaging.
describe('test-element', function() {
var el;
beforeEach(function() {
el = document.createElement('test-element');
});
it('fires a save event', function(done) {
el.addEventListener('save', function() {
done();
});
el.save();
});
In a perfect world, I think something like this would be cooler.
it('fires a save event', function() {
el.save();
expect(el).to.have.firedEvent('save');
});
});
Am I going about this the right way? Is there a better approach or a custom matcher library I should be using?
How about spying on the fire function...?
Not sure what stubbing/spying library you're using but lets say Sinon.JS. So something like...
var spy = sinon.spy(el, 'fire');
el.save();
expect(spy.calledWith('save')).to.be.true;

How to add a delay before starting a Mocha test case?

I'm writing a unit test for my simple Node.js application using Mocha. The application has a class which connects to a Mongo database, fetch the record, and store the formulated record as a field. Simply, the class looks like this:
SampleClass.prototype.record = []; // Store the loaded record
SampleClass.prototype.init = function(db){
var self = this;
self.db = mongoose.connection; // Say we already have mongoose object initialized
self.db.once('open',function(){
/* schema & model definitions go here */
var DataModel = mongoose.model( /* foobar */);
DataModel.findOne(function(err,record){
/* error handling goes here */
self.record = record; // Here we fetch & store the data
});
});
}
As seen from the snippet above, once the SampleClass.init() is called, the Sample.record will not instantly get populated from the database. The data is asynchronously populated once the event 'open' is fired. Thus, there will possibly be a delay after SampleClass.init() until the Sample.record is populated.
So it comes into a complication when I write a Mocha test like this:
var testSampleClass = new SampleClass();
describe('SampleClass init test',function(){
testSampleClass.init('mydb');
it('should have 1 record read from mydb',function(){
assert.equal(testSampleClass.record.length,1);
});
});
The assertion above will always fail because testSampleClass.record will not get populated straightaway after init. It needs a gap of time to load the data.
How can I delay the test case so it starts a few seconds or more after testSampleClass.init is called? Is it also possible to trigger the test case right after an event of my class is fired? Otherwise, this simple case will always fail which I know this is not correct at all.
#alexpods made a great suggestion. Add following to your test collection so that each test step will wait for 500 msec before running.
beforeEach(function (done) {
setTimeout(function(){
done();
}, 500);
});
or in ES6
beforeEach(done => setTimeout(done, 500));
Thanks #Timmerz for the suggestion
Use before() or beforeEach hooks (see here and here). They take done callback as argument, which you must call when some asynchronous staff will be completed. So you test should looks like:
describe('SampleClass init test',function(){
before(function(done) {
testSampleClass.init('mydb', done);
});
it('should have 1 record read from mydb',function(){
assert.equal(testSampleClass.record.length,1);
});
});
And your init method:
SampleClass.prototype.record = []; // Store the loaded record
SampleClass.prototype.init = function(db, callback){
var self = this;
self.db = mongoose.connection; // Say we already have mongoose object initialized
self.db.once('open',function(){
/* schema & model definitions go here */
var DataModel = mongoose.model( /* foobar */);
DataModel.findOne(function(err,record){
/* error handling goes here */
self.record = record; // Here we fetch & store the data
callback();
});
});
}

How to unit test this code

I googled on how to unit test but examples are so simple. the examples always show functions that return something or do ajax that returns something - but never have i seen examples that do callbacks, nested callbacks and functions that are "one-way", that they just store something and never return anything.
say i have a code like this, how should i go about testing it?
(function(){
var cache = {};
function dependencyLoader(dependencies,callback2){
//loads a script to the page, and notes it in the cache
if(allLoaded){
callback2()
}
}
function moduleLoader(dependencies, callback1){
dependencyLoader(dependencies,function(){
//do some setup
callback1()
});
}
window.framework = {
moduleLoader : moduleLoader
}
}());
framework.moduleLoader(['foo','bar','baz'],function(){
//call when all is loaded
})
This illustrates a problem with keeping things private in an anonymous function in javascript. It's a bit difficult to validate that things are working internally.
If this was done test first then the cache, dependencyLoader and moduleLoader should be publicly available on the framework object. Or else it would be difficult to validate that the cache was handled properly.
To get things going I'd recommend you take a gander on BDD, that conveniently gives you an approach to help you start by letting you spell out the behaviour with a given-when-then convention. I like to use Jasmine, which is a javascript BDD framework (that integrates with jstestdriver), for this kind of thing and the unit tests I'd make for the sample you have above would be:
describe('given the moduleloader is clear', function() {
beforeEach(function() {
// clear cache
// remove script tag
});
describe('when one dependency is loaded', function() {
beforeEach(function() {
// load a dependency
});
it('then should be in cache', function() {
// check the cache
});
it('then should be in a script tag', function() {
// check the script tag
});
describe('when the same dependency is loaded', function() {
beforeEach(function () {
// attempt to load the same dependency again
});
it('then should only occur once in cache', function() {
// validate it only occurs once in the cache
});
it('then should only occur once in script tag', function() {
// validate it only occurs once in the script tag
});
});
});
// I let the exercise of writing tests for loading multiple modules to the OP
});
Hope these tests are self explanatory. I tend to rewrite the tests so that they nest nicely, and usually the actual calls are done in the beforeEach functions while the validation are done in the it functions.

Categories

Resources