MochaJS sending HTTP Request in after hook - node.js

I'm trying to send a http delete request to my web server in Mocha's after hook. Here's the relevant code:
after(function() {
console.log('here at after');
request.del('http://localhost:3000/api/deleteAllTasks', function(req, res) {
console.log(req);
});
});
The problem is that the delete endpoint is never being hit. It console.logs "here at after" but never console.logs the request in the callback for request.del. I'm not sure what is causing this; I know the endpoint works as I've sent curl requests to it successfully. Anyone have any ideas? Ultimately, I want this endpoint to clear the DB after this particular test suite runs.

Betting that your script is ending before the asynchronous request is actually made. Try changing your after(function() {... to include the "done" parameter like after(function(done) {... and calling done() within the inner callback.

Here is a new after block that will make your test work. leetibbett is completely correct.
after(function(done) {
console.log('here at after');
request.del('http://localhost:3000/api/deleteAllTasks', function(err, res) {
console.log(res);
done();
});
});

Related

Node.js only one function executed

I try to execute two functions in a post request but only one is triggered. The function makeEntry executes but the function afterwards renderEntries does'nt. Can anyone help pls?
Here is the code: https://codepaste.net/bpsxsy
This is due to how callbacks work in Javascript. Here is the part which matters:
app.post('/guestbook_post', urlencodedparser, function(req, res){
makeEntry(req, res, Guestbook);
renderEntries(res, Guestbook);
});
You pass res to both functions. But makeEntry invokes res.send() which means it will end the request and send the response back to the client. However, renderEntries was not yet executed, but still waiting in event loop. It will be executed the next time you make a post request, which will lead to very confusing and buggy behaviour.
To make it work as intendeed, refactor functions makeEntry and renderEntries to return the needed result object and render it to the client once. Something like this:
app.post('/guestbook_post', urlencodedparser, function(req, res){
makeEntry(req, Guestbook, (err, entry) => {
renderEntries(entry, Guestbook, (err, result) => {
res.send(result);
});
});
});

"Error: Can't set headers after they are sent" in Express app with Node

I am new to Express and Node, and when testing a protected REST endpoint in my app using Advanced REST Client the data is returned from the endpoint to the Client as expected, however the console logs
"Error: Can't set headers after they are sent"
which stops the server. Searching here on SO, this seems to occur when sending more than one response but I don't see that in my code:
router.get('/books', userAuthenticated, function (req, res, next) {
Book.find({}, function(err, docs){
if(err) {
res.send(err)
} else {
res.send(docs);
// next();
// return;
}
})
});
Is this error expected when sending a request/response to/from the Client or am I missing something in handling the error on the server?
Express is a node.js server that features a concept called "middleware", where multiple layers of code get a chance to operate on a request.
In that case, not only do you need to check that your function is not sending back a response twice, but you have to check that other middleware are not sending back a response as well.
In your case, the code indicates that middleware called "userAuthenticated" is being invoked before this function. You should check if that middleware is already sending a response.
I don't think the problem was in the middleware. It looks like I was calling done() twice in passport deserialize. I commented out the first instance and the problem disappeared in all my routes. Although, I am not sure if I should comment out the first or second instance but I'll work on that next.
passport.deserializeUser(function(obj, done) {
console.log(obj);
Account.findById(obj, function(err, user) {
console.log(user);
//done(err, user);
});
return done(null, obj);
});

Multiple Asynchronous Socket response handling using Mocha

I am trying to prototype a load testing scenario on socket interactions using Mocha and should.js. I have an array of user details which I want to authenticate using socket communication and wish to verify their responses. It works fine for a single user, however when I try to loop for multiple users - I end up with issues. Had gathered some inputs based on the post:Tests from looping through async JavaScript (Mocha) .
Below is the code snippet:
var users = [{name:'A',password:'password',expected:'success'},{name:'B',password:'badPass',expected:'failure'}];
describe('socket Interaction test' , function() {
function socketInteraction(users, done) {
client.emit('userAuthentication', {'name':users.name,'password':users.password}, function(callback) {
console.log('Emit' + users.name);
});
client.on('userAuthenticationResponse', function(response) {
console.log('Resp' + response.status + 'Expected' + users.expected);
response.status.should.equal(users.expected);
done();
});
}
it('Dummy', function(done) {
describe('Mutiple login Test Async', function() {
it('User Login Test', function(done) {
users.forEach(function(users, callback) {
console.log(users.name);
socketInteraction(users, function(err) {
if (err) {
return;
}
done();
});
});
});
});
});
});
The response I get upon running the test is:
socket Interaction test
✓ Dummy
Mutiple login Test Async
A
B
RespsuccessExpectedsuccess
✓ User Login Test
RespsuccessExpectedfailure
2 passing (43ms)
The second test has to fail. Not sure where I have messed up the code. Appreciate some pointers to fix this. Thanks.
The done Parma should be called in the second param of the async.forEach. The done you call in the loop function should be callback(), to tell async that just that user is finished.
You don't have the async finished callback yet at all.
Would have posted code but am on my phone. I can add later if it's not clear.

express timeout on specific app.get

I have a nodejs app which is using express.
For a specific GET request, I would like to set a timeout, and if this timeout is reached, then I would like to completely end the request and redirect to a timeout page.
I tried the following in my route.js file :
app.get('/exec', isLoggedIn, function(req, res) {
var customTimeout = 10000;
req.connection.setTimeout(customTimeout, function(){
console.log("TIMED!");
res.render('timeout.ejs', {
user: req.user,
});
});
//execution of the GET request
res.render('success.ejs', {
user: req.user,
});
});
After 10 seconds, I can see the "TIMED!" message in the logs, but I'm not redirected to the timeout page, and the request is still running in the background...
Can someone help me deal with this ?
This works for me:
app.get('/exec', isLoggedIn, function(req, res) {
var customTimeout = 10000;
res.setTimeout(customTimeout, function(){
console.log("TIMED!");
res.render('timeout.ejs', { user: req.user });
});
res.render('success.ejs', { user: req.user });
});
I'm assuming that instead of the last res.render(), you're executing some sort of operation that may take a lot of time to finish (and after 10 seconds you want to notify the user that the operation timed out).
If that operation isn't cancellable somehow, eventually it will finish and also try to send back a response, in which case you can run into errors (most likely "Can't set headers after they are sent").
So before sending a response, you need to check if one hasn't been sent already by the timeout handler. You can use res.headersSent for that.

After res.send() event in Restify?

I'm trying to add Bugsnag to my Node Restify service. We have a ton of routes already and such so I'm trying not to add Bugsnag calls all over our code base and I'm also trying to do something global so there's never a mistake where a dev forgets to add the error reporting.
Conceptually I want after any res.send() to get the status code. If the statusCode is >=400 i want to notify Bugsnag by calling Bugsnag.notify. I already check for errors everywhere so no errors ever show up to the clients (browsers, phones, etc) but they do get sent, for example, res.send(401, { message: 'You dont have permission to do that' }) which I'd like to be able to hook into and pass who tried to do that, what route, etc. Problem is I can't get the after event to fire at all:
server.on('after', function (req, res, route, error) {
console.log('AFTER')
});
I think I misunderstand what after is for. It's at the top of my index.js before any routes or other middleware (server.use) is defined.
My general code structure looks something like:
server.post('/foo', function (req, res, next) {
FooPolicy.create(req, function (err) {
if (err) return res.send(err.code, err.data);
FooController.create(req.params, function (response) {
res.send(response.code, response.data)
next();
});
});
});
FooPolicy == checking permissions
FooController == actually creating the model/data
The issue is that the after event is currently treated like any other handler. That means that if you don't call next in every code path, the after event will never be emitted.
In the meantime, adding a next call will cause your after event handler to fire.
if (err) {
res.send(err.code, err.data);
next();
return;
}

Resources