Rethinkdb with nodejs and expresso - node.js

I am trying to use rethinkdb and test it via expresso. I have function
module.exports.setup = function() {
var deferred = Q.defer();
r.connect({host: dbConfig.host, port: dbConfig.port }, function (err, connection) {
if (err) return deferred.reject(err);
else deferred.resolve();
});
return deferred.promise;
});
I am testing it like this
module.exports = {
'setup()': function() {
console.log("in setup rethink");
db.setup().then(function(){
console.log(clc.green("Sucsessfully connected to db!"));
}).catch(function(err){
console.log('error');
assert.isNotNull(err, "error");
});
}
};
And I am runing code like this
expresso db.test.js
But expresso shows error 100% 1 tests even in case of error.
I tried to put throw err; in catch, but nothing changes.
But if I put assert.eql(1, 2, "error"); in the begining of setup() it fails as expected;
Is there something, that caches errors? How can I make it fail as it should be?
For squalize I found
Sequelize.Promise.onPossiblyUnhandledRejection(function(e, promise) {
throw e;
});
Is there something like this for rethink db?

The problem is that this test is asynchronous, and you're treating it as a synchronous test. You need to do the following:
module.exports = {
'setup()': function(beforeExit, assert) {
var success;
db.setup().then(function(){
success = true;
}).catch(function(err){
success = false;
assert.isNotNull(err, "error");
});
beforeExit(function() {
assert.isNotNull(undefined, 'Ensure it has waited for the callback');
});
}
};
Mocha vs Express
You should consider taking a look at mocha.js, which has a much nicer API for asynchronous operations by passing the done function. The same test would look like this:
module.exports = {
'setup()': function(done) {
db.setup().then(function(){
assert.ok(true);
}).catch(function(err){
assert.isNotNull(err, "error");
})
.then(function () {
done();
});
}
};
Promises
The first function you wrote can be re-written in the following manner, because the RethinkDB driver, by default, returns a promise on all operations.
module.exports.setup = function() {
return r.connect({host: dbConfig.host, port: dbConfig.port });
});

Related

Node.js callback is not a function

Running a simple redis test
var redis = require(__dirname+'/server/redis.js');
redis.redisTest(function(res){
RedisState = res;
});
redis.js
redisTest: function(callback){
GameDBCon.set('my test key', 'my test value');
GameDBCon.get('my test key', function (error, result) {
if (error) {
callback(false);
console.log(error);
throw error;
}
console.log('GET result ->' + result);
callback(true);
});
},
error from redis.js at callback(true);
callback is not a function, I see a lot of similar issues like this but its not making much sense. Additionally I have similar code that does work.
Shouldn't this callback work?

Catching / capturing chrome storage sync errors

If we use this code:
chrome.storage.sync.set({settings: x}, function() {
console.log('Settings saved');
});
what is the best way to capture an error, is this the right way?
chrome.storage.sync.set({settings: x}, function() {
if (chrome.runtime.lastError) {
return cb(chrome.runtime.lastError);
}
console.log('Settings saved');
cb(null);
});
Yes, it's a best way to capture errors with usage of all chrome async API.
Using try ... catch in your callback won't help. Also,
It's async, so using try around the original API call won't help either.
You could promisify it to manage errors and callback hell better.
var promisify = function (fn) {
var args = Array.prototype.slice.call(arguments).slice(1);
return new Promise(function(resolve, reject) {
fn.apply(null, args.concat(function (res) {
if (chrome.runtime.lastError) {
return reject(chrome.runtime.lastError);
}
return resolve(res);
}));
});
};
then you can use it as follows:
function setStorageItems(items) {
return promisify(chrome.storage.sync.set, items);
}
setStorageItems({settings: 'x'}).then(function() {
console.log('settings saved');
})
.catch(function (err) {
console.error(err);
});

Promises not working as expected with async.each

I'm somehow not able to find the solution. Here is what I'm doing:
async.each(bottles, function(bottle) {
// set substance quantity to 0
updateQuantity(bottle[constant.SUBSTANCE_ID], 0)
.then(function() {
bottle[constant.EXPIRY] = expiry;
bottle[constant.IS_AVAILABLE] = true;
updateRecord(bottle)
.then(function() {
console.log('Updated');
},
function() {});
}, function() {});
}, function() {
console.log('Finished');
});
console.log('Done');
The method updateQuantity and updateRecord returns promises and are using Knex update in the background which also returns a promise.
I want the output of the above code to be:
Updated
Updated
Finished
Done
But the output I'm getting is:
Done
Updated
Updated
So, the callback of async.each is not working and the code is not waiting for async.each to finish.
You have to call the passed in callback from the async.each operation. As it is, async doesnt know when your callback resolves.
Also, DONE should always be the first text you see as async.each doesn't block. When you start running running the script, async.each will be registered, but because your code is asynchronous it will reach the console.log('Done') before the updateRecord and updateQuantities complete
async.each(bottles, function(bottle, callback) {
updateQuantity(bottle[constant.SUBSTANCE_ID], 0)
.then(function() {
...
updateRecord(bottle)
.then(function() {
console.log('Updated');
callback();
},
function() {});
}, function() {});
}, function() {
console.log('Finished');
});
console.log('Done');
Don't use async.js at all with promises, they are capable of what you need with their builtin methods and you don't need to fall back to callbacks.
bottles.reduce(function(prev, bottle) {
return prev.then(function() {
// set substance quantity to 0
return updateQuantity(bottle[constant.SUBSTANCE_ID], 0)
}).then(function() {
bottle[constant.EXPIRY] = expiry;
bottle[constant.IS_AVAILABLE] = true;
return updateRecord(bottle);
}).then(function() {
console.log('Updated');
});
}, Promise.resolve()).then(function() {
console.log('Finished successfully');
}, function(err) {
console.error(err)
}).then(function() {
console.log('Done'); // notice you must put this in the callback
});
console.log('Started');

Jasmine Testing Node.js Async modules

I\m trying to write unit tests for some code I wrote, the problem I'm running into is I expect my mock callback to be called after executing the function but my test fails as it is never called.
describe("Asynchronous specs", function() {
var mockNext;
beforeEach(function() {
mockNext = jasmine.createSpy('mockNext');
var res;
parallelRequests.APICall(testObject[0], null, mockNext);
});
it("callback spy should be called", function () {
expect(mockNext).toHaveBeenCalled();
});
});
The function being tested is quite simple:
function APICall(options, res, next) {
request(options, callback);
function callback(error, response, body) {
if (error) {
if (error.code === 'ETIMEDOUT') {
return logger.error('request timed out: ', error);
next(error);
}
logger.error('request failed: ', error);
next(error);
}
next(null);
}
}
The issue I suspect is jasmine testing the expectation before the mock callback is executed in API Call due to request's async nature. I've tried using what others suggest of using done() and flags but with no luck. Would appreciate some guidance in this matter.
Your beforeEach code is asynchronous. You have to tell yasmin when your beforeEach logic is done. You can solve this by the callback method done, that is passed to each test. Try this:
describe("Asynchronous specs", function() {
var mockNext;
beforeEach(function(done) {
parallelRequests.APICall(testObject[0], null, function(){
mockNext = jasmine.createSpy('mockNext');
mockNext();
done();
});
});
it("callback spy should be called", function () {
expect(mockNext).toHaveBeenCalled();
});
});

How To Write a Mocha test for async waterfall

I have written a mocha test case for the async waterfall, "function2" is module which call for mongodb to get data, when i am trying to run the same code in node.js this async code works, but when i am do mocha test the "function2" call for mongodb throws error saying "[Error: Cannot determine state of server]".
i got to know the reason that the test is getting executed fast without waiting for mongodb to connect and return result.
can someone suggest me how to solve this problem. thanks in advance.
var function1 = require('../../method1');
var function2 = require('../../method2');
var function3 = require('../../method3');
describe('controller : ', function () {
it('should not return error', function (done) {
async.waterfall([
function(callback){
function1.method1(app.request, app.response, function(err,result) {
if(err){
callback(err,null);
}
else{
var var1 = result;
callback(null, var1);
}
});
},
function(var1, callback){
//Here I have a Mongodb Call
function2.method2(var1,function(err,result) {
if(err) {
callback(err,null);
}
else{
var var2= result;
var context = {
"c1": var1,
"c2": var2
};
callback(null, context);
}
});
},
function(context, callback){
function2.method2(context, function(err,result) {
if(err){
console.error(err);
callback(err,null);
}
else{
context.c3 = {};
result.forEach(function(e, i) {
for(var key in e) {
context.c3[key] = e[key];
}
});
callback(null, context);
}
});
},
function(context, callback){
should.exist(context);
}
],
function (err, result) {
should.not.exist(err);
should.exist(result);
});
});
});
I'm not sure but try to wait when connection (which use your module) is established.
before(function(done) {
connection.on('open', done);
});

Resources