Expects aren't working in Chai as Promised results - javascript

I'm new to Promises in JavaScript, and whilst it seems to be working for me to an extent, I'm unable to test the 'reject' value.
I'm passing through an Error, and want to ensure that it is an error and more importantly, that the error code matches what I'm expecting.
return new Promise(function(resolve, reject){
tableService.deleteEntity(config.azureTable.tableName,
visitor.azureEntity(), function (error, response) {
// If successful, go on.
if (!error) {
resolve(response);
}
// If unsuccessful, log error.
else {
/* If we know it's a resourceNotFound
that's causing the error, return that. */
if (error.code === 'ResourceNotFound') {
reject(new Error('Record not found'));
}
// For unexpected errros.
else {
reject(new Error('Table service error (delete): ' + error));
}
}
});
});
The test, in Mocha - using chai and chai-as-promised. Everything else is working (I have 24 passing tests) - but this one has me stuck!
it('return an error when the lookup fails', function (done) {
storage.delete(globalUUID).then(function(sucess) {
done(sucess);
}, function(error) {
expect(error).to.be.an(Error);
done();
});
});
Any help would be greatly appreciated.

You are not using chai-as-promised anywhere. If your first code example is the body of the storage.delete method, then your test should look like:
it('return an error when the lookup fails', function() {
expect(storage.delete(globalUUID)).to.be.rejectedWith(Error);
});

Related

Parse CloudCode sometimes does not work

I want to update a field in the 'NotesDB' that indicates the number of comments on a specific Note. Parse Cloudcode should do this automatically after saving a comment.
In practice it sometimes does and it sometimes doesn't (even with the same user, on the same note). The comment itself is always saved properly.
Is there any way i can improve this code..?
Parse.Cloud.afterSave("CommentsDB", function(request) {
var OriginalNote = request.object.get("OriginalPostId");
var query = new Parse.Query("NoteDB");
query.get(OriginalNote, {
success: function(post) {
post.increment("NumberOfComments");
post.save();
},
error: function(error) {
console.log("An error occured :(");
}
});
As you code stands, it is not possible to see if the post.save() call is failing or not (and if it is, why), maybe try chaining your promises :
query.get(OriginalNote,{useMasterKey:true}).then (function (post) {
post.increment("NumberOfComments");
return post.save(null,{useMasterKey:true});
}).then (function (savedPost) {
console.log('post incremented ok to ' + savedPost.get('NumberOfComments'));
},function (err) {
//this function will catch any error in the promise chain : query.get() or post.save()
console.error('An error occured : ' + err.message);
});

Trapping AssertionError in nested callback function

I am writing an updated testing library for Node.js and am trying to properly trap errors that occur in test callbacks
for some reason, the following code doesn't trap an AssertionError:
process.on('uncaughtException',function(err){
console.error(err); //an instance of AssertionError will show up here
});
[file1,file2,file2].forEach(function (file) {
self.it('[test] ' + path.basename(file), {
parallel:true
},function testCallback(done) {
var jsonDataForEnrichment = require(file);
request({
url: serverEndpoint,
json: true,
body: jsonDataForEnrichment,
method: 'POST'
}, function (error, response, body) {
if (error) {
done(error);
}
else {
assert(response.statusCode == 201, "Error: Response Code"); //this throws an error, which is OK of course
done();
}
});
});
});
I handle the callback (I named it "testCallback" above), with this code:
try {
if (!inDebugMode) {
var err = new Error('timed out - ' + test.cb);
var timer = setTimeout(function () {
test.timedOut = true;
cb(err);
}, 5000);
}
test.cb.apply({
data: test.data,
desc: test.desc,
testId: test.testId
}, [function (err) { //this anonymous function is passed as the done functon
cb(err);
}]);
}
catch (err) { //assertion error is not caught here
console.log(err.stack);
cb(err);
}
I assume the problem is that callbacks that result from async functions like those made in the request module, cannot be trapped by simple error handling.
What is the best way to trap that error?
Should I just flesh out the process.on('uncaughtException') handler? Or is there a better way?
The best way to handle this appears to be Node.js domains, a core module
https://nodejs.org/api/domain.html
it will likely be deprecated soon, but hopefully there will be a replacement that can have similar functionality, because the domain module is saving my ass right now, as I have no other way to trap errors, because the errors might be generated by my users' code, not my code.

Best way to debug promises running in parallel

Am developing backend of an app using nodejs+express and using RSVP for promises.
Problem : whenever there is an error or exception in one of the functions that is unexpected the execution is stuck. Is there any way i can find which one of the functions have the error.
The code looks like this :
function checkifvalid_call() {
return new RSVP.Promise(function(fulfil, reject) {
common.checkifvalid(test, function(isValid) {
if (isValid === false) {
logger.fatal("Not valid test....sending invalid result")
res.send({
"Error": "Invalid test"
});
}
});
});
}
function secondtest_call() {
return new RSVP.Promise(function(fulfil, reject) {
common.secondtest(test, function(isValid) {
if (isValid === false) {
logger.fatal("Not valid second test....sending invalid result")
res.send({
"Error": "Invalid second test"
});
}
});
});
}
RSVP.allSettled([checkifvalid_call(), secondtest_call()]).then(function(ret_array) {
console.log("Calls finished");
logger.debug("sending result..............")
res.send("success);
}).catch(function(reason) {
logger.debug("Exception encountered : " + reason);
}).finally(function() {
logger.debug("All done finally")
});
RSVP.on('error', function(reason) {
console.assert(false, reason);
});
Thank you.
Try using try{}catch, and use RSVP's error handler on each of the promises instead of the entire thing. The current set of handlers only checks if 'allSettled' has an error afaik.
This blog post explains promises very well:
How To Use Promises

Orchestrate.js triggers both 'promise.fail' and 'promise.then'

Orchestrate has a client for NodeJS. It is based on promises so I should define a function then and a function fail. The first should be triggered when the request is successful and the second one when it fails. But sometimes it triggers both and I don't understand why.
Here is an example of a function that calls both then and fail:
user.checkToken = function (token, db, callback) {
if (token) {
db.get('acces_tokens', token).then(function (res) {
if (new Date(res.body.expire) > new Date()) {
//Token is valid
callback(res.body.user, res.body.expire);
} else {
//Token has expired
callback(false, "Token has expired");
}
}).fail(function (err) {
callback(false, "ERROR");
});
} else {
callback(false, "A token is needed");
}
};
I do not understand it :(
EDIT: It turn out it only does this when I call it from certain functions. This is even weirder.
EDIT 2: I've been doing some debuging. I console.logged the entire promise like this:
console.log(
db.get('acces_tokens', token)
.then(function (res) {
if (new Date(res.body.expire) > new Date()) {
//Token in valid
callback(res.body.user, res.body.expire);
} else {
//Token has expired
callback(false, "Token has expired");
}
}).fail(function (err) {
callback(false, "ERROR");
})
)
And I got this:
{ promise: [Circular],
_isPromise: true,
_successFn: null,
_failFn: [Function],
_scope: [Circular],
_boundArgs: null,
_hasContext: false,
_nextContext: undefined,
_currentContext: undefined }
As you can see _successFn is null. I guess this is the problem but I do not understand why it is null :(
But sometimes it triggers both and I don't understand why.
Because in the pattern you used - shortened to promise.then(callback).fail(callback) - callback might be called twice. If promise succeeds, your first callback is called, but when that callback throws an exception then the promise returned by promise.then(callback) is rejected and will call the fail callback you attached to it.
You'll need to use something along the lines of promise.then(callback, callback) to prevent this from happening. See When is .then(success, fail) considered an antipattern for promises? for more explanations.
Of course, it would be better if you'd screw callbacks alltogether and just return a promise from your checkToken function :-)

How to bubble error correctly from Promise without throw?

I have the following TypeScript method which returns a promise:
public loadSavedLogin(): ng.IPromise<MyApp.Models.User> {
return this._myAppService.getUser(this.savedUserId).then((result: MyApp.Models.User) => {
if (result) {
this.userId = result.UserID;
this.userName = result.UserName;
}
return result;
}, (error) => {
this._isAuthError = true;
return error;
}
);
}
The problem I have is in the promise's error callback. The upstream calls to this method also rely on a promise so if the error does not bubble up correctly, the upstream promise doesn't function correctly. I found a hackish solution:
(error) => {
try {
this._isAuthError = true;
return error;
} catch (e) {
//If any error occurred above make sure to still throw
throw error;
} finally {
//Allow upstream promises to continue as expected
throw error;
}
}
This works but looks, feels, and is probably all wrong. I feel like I'm missing a proper implementation when handling and bubbling errors in a promise. There has to be a more proper/correct way of handling the error function in this promise as I've done, and yet still allow upstream promise's making a call to this method to work properly as well when handling their own error function.
How do I get the error to bubble without the series of hackish throw statements?
Note: It seems redundant to return the error and throw as well, but the IPromise interface I'm using will not compile if I don't return a value. This is why I return and throw the error.
Note: I read a ton of the questions on handling errors with promises, but none of them are answering the question as I'm asking in regards to preventing the hackish approach I've taken.
I am not conversant with TypeScript, but here is a javascript solution, where you use $q.reject
.then(function() {},
function(error) {
this._isAuthError = true;
return $q.reject(error);
});`
Just throw the error instead of ever returning it:
public loadSavedLogin(): ng.IPromise<MyApp.Models.User> {
return this._myAppService.getUser(this.savedUserId).then((result: MyApp.Models.User) => {
if (result) {
this.userId = result.UserID;
this.userName = result.UserName;
}
return result;
}, (error) => {
this._isAuthError = true;
throw error;
}
);
}
Note that a valid return (i.e. not returning a promise / rejected promise) from a rejection handler makes the next promise in the chain fulfilled.

Categories