Node.js - simple Restify POST Mocha test failing - node.js

I have a simple Node.js Rest server with a single POST service using Restify. I am trying to write a simple Mocha test, however it fails with a timeout, although succeeds with a REST Console test (browser plugin).
My server code:
/**
* Module dependencies
*/
var restify = require('restify');
var events = require('events');
var util = require('util');
/**
* Create App
*/
var server = restify.createServer({
name: 'test',
version: '0.0.1'
});
var eventsEmitter = new events.EventEmitter();
/**
* Configuraion
*/
server.use(restify.acceptParser(server.acceptable));
server.use(restify.queryParser());
server.use(restify.bodyParser());
/**
* Routes
*/
server.post('/post', function (req, res, next) {
var text = "";
req.setEncoding("utf8");
req.on("data", function (chunk) {
text += chunk;
});
req.on("end", function () {
res.send(200, {ok: 'ok'});
});
return next();
});
/**
* Listen
*/
server.listen(8080, function () {
console.log('%s listening at %s', server.name, server.url);
});
The Mocha test is as follows:
var restify = require('restify');
var assert = require('assert');
// init the test client
var client = restify.createJsonClient({
url: 'http://127.0.0.1:8080',
version: '*'
});
describe('service: post endpoint', function() {
// Test #1
describe('200 response check', function() {
it('should get a 200 response', function(done) {
client.post('/post', { hello: 'world' }, function(err, req, res, data) {
if (err) {
throw new Error(err);
}
else {
if (data.code != 200) {
throw new Error('invalid response from /post');
}
done();
}
});
});
});
});
Can anyone advise why the test would timeout (I have tested with increasing the timeout in Mocha), but succeed through a browser?

The problem is that Restify calls your server.post('/post', handler) function when the request is finished being received. You don't have to wait for the data and end events. It is something that Restify (and other libraries like it, eg. Express) do for you. So all you need to do is write
server.post('/post', function (req, res, next) {
res.send(200, {ok: 'ok'});
});
And then you should not have a timeout. You were having the timeout because your handler was waiting for events that already came.

Related

ERR_HTTP_HEADERS_SENT node js socket connection

I am building an API that uses socket connection to interact with a server backend built in C#. This is what I have so far
const request = require('request');
const express = require('express');
const app = express();
var server = require('http').createServer(app);
var cors = require("cors");
app.use(cors());
const net = require('net');
const client = new net.Socket();
const stringToJson=require('./stringToJson')
const port = process.env.PORT;
const host = process.env.HOST;
client.keepAlive=true
client.on('close', function() {
console.log('Connection closed');
});
app.get('/getScores',function (req,res) {
let dataSend=''
client.on('data', function (data) {
console.log('Server Says : ' + data);
if(data!='ANALYSIS-ERROR'){
dataSend=stringToJson.stringToJson(data)
}
else{
dataSend=stringToJson.stringToJson('0:0.0:0.0:0.0:0:0:0.0:0.0:0.0:0.0:0.0:0:0.0:0.0:0.0:0.0:0.0:0:0.0:0.0:0.0:0.0:0.0:0:0.0:0.0:0.0:0.0:0.0')
}
client.destroy()
return res.send(dataSend)
});
client.connect(port, host, function () {
client.write(`GENERAL-ANALYSIS|${req.query.id}|${req.query.website}|`)
return
});
return
})
app.get('/getPlace',function (req,res) {
console.log(req.query)
request(
{ url: `https://maps.googleapis.com/maps/api/place/textsearch/json?query=${req.query.name}+in+${req.query.city}&key=${process.env.API_KEY}` },
(error, response, body) => {
if (error || response.statusCode !== 200) {
return res.status(500).json({ type: 'error', message: error.message });
}
return res.json(JSON.parse(body));
}
)
})
//TODO ADD 404 500 PAGES
app.use((req, res, next) => {
res.status(404).send("Sorry can't find that!");
});
app.use((err, req, res, next) => {
console.error(err.stack);
res.status(500).send('Something broke!');
});
server.listen(9000, () => {
console.log(`App running at http://localhost:9000`);
});
Basically it creates a connection with the server and listens for some data to be sent back. Then processes the string and sends it to the React frontend. The api calls are made by the frontend using axios
It works but if you refresh the page it throws this error Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
How do I fix this?
Try setting the headers as found in the documentation request.setHeader(name, value)
request.setHeader('Content-Type', 'application/json');

How to fix 'headers already sent' error in node

So I'm trying to create a node app that calls an ldap serve and to authenticate users. In the code below, the app successfully connects to the server and processes the request. But when I try to send a response back, I get this error:
throw new ERR_HTTP_HEADERS_SENT('set');
^
Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
I'm not really sure why this is occurring. I'm pretty new to node, express, and ldap
// ldapjs required for ldap connection
const ldap = require('ldapjs');
//express required for exposing endpoints
const express = require('express');
const app = express();
const assert = require('assert');
var client = ldap.createClient({
url: 'ldap://someserve.com'
});
//Search filter for users in the directory
var opts = {
filter: '(&(objectCategory=person)(objectClass=user))',
scope: 'sub',
};
//General Ldap serch user
var UserName = '123.test.com';
var Pass = '123longpass'
//Base URL
app.get('/', (req,res) => {
res.send('hello from node')
});
//Get all ldap users
app.get('/api/ldapUsers', (req, res) =>
{
client.bind(UserName, Pass, function (err)
{
client.search('DC=sdf,DC=sdfa,DC=gdfgd', opts, function (err, search)
{
search.on('searchEntry', function (entry)
{
res.setHeader('Content-Type', 'application/json');
var users = entry.object;
console.log(users);
res.json(users);
res.end();
});
});
});
// client.unbind( err => {
// assert.ifError(err);
// });
});
const port = process.env.PORT || 3000;
app.listen(port, () => console.log(`Listening on port ${port}...`));
searchEntry event is called once for each found item which means you are calling res.json multiple times.
Try this:
app.get('/api/ldapUsers', (req, res) =>
{
client.bind(UserName, Pass, function (err)
{
client.search('DC=sdf,DC=sdfa,DC=gdfgd', opts, function (err, search)
{
var users = [];
search.on('searchEntry', function (entry) {
users.push(entry.object);
});
search.on('end', function (entry) {
res.setHeader('Content-Type', 'application/json');
console.log(users);
res.json(users);
res.end();
});
});
});
});

Mocha test not reaching 2nd Express callback and returning to 1st

I need help in the below code. I am testing a service which is sending request to a particular endpoint and I need to capture the body of the request, (using node express for this). The runner is mocha tests and has more than 1 it block.
When I am debugging the test, first it block works as expected (assertion passes), but when the control reaches second it block ,once the request is posted, the control is back to the first block again and the assertion in second block is never reached. What am I doing wrong here?
{
var express = require("express");
var bodyPaser = require('body-parser');
var expressObj = new express();
expressObj.use(bodyPaser.json());
describe('describe', function () {
before('describe', function () {
expressObj.listen(8080);
});
it('first It', function (done) {
expressObj.post('/mytest/first', function (req, res) {
res.send("Hello");
// assert.equal(JSON.stringify(req.body), JSON.stringify('first":test'));
done();
});
});
it('second it', function (done) {
expressObj.post('/mytest/first', function (req, res) {
res.send("Hello");
// assert.equal(JSON.stringify(req.body), JSON.stringify('first":test'));
done();
});
});
});
The first and second tests are merely setting up the route, but you aren't actually sending a request to either of the routes you've described. So the tests begin, but the first one isn't actually doing anything, so done is never called, which is why the second test doesn't begin to run at all. To test these routes you'll need to create a request for each route after defining them. Here is a working demo of your code:
var express = require("express");
var bodyPaser = require('body-parser');
var expressObj = new express();
expressObj.use(bodyPaser.json());
const request = require('request');
describe('describe', function () {
before('describe', function (done) {
expressObj.listen(8080, function(err) {
if(err) {
console.error(err);
done(err);
return;
}
console.log('listening on localhost:8080');
done();
});
});
it('first It', function (done) {
expressObj.post('/mytest/first', function (req, res) {
res.send("Hello");
// assert.equal(JSON.stringify(req.body), JSON.stringify('first":test'));
done();
});
request.post('http://localhost:8080/mytest/first');
});
it('second it', function (done) {
expressObj.post('/mytest/second', function (req, res) {
res.send("Hello");
// assert.equal(JSON.stringify(req.body), JSON.stringify('first":test'));
done();
});
request.post('http://localhost:8080/mytest/second');
});
});

TDD Test first Nodejs express Rest Api - unit testing middlewere / controllers / routes

I'm trying to figure out how to test first my node js rest api app.
so far i've been using nock to intercept and mock any http call and by that test my service as a component. (component testing?)
i want to start unit testing my app so my test pyramid is more balanced and tests will be easier to write.
searching the web i got to this approach:
http://www.slideshare.net/morrissinger/unit-testing-express-middleware
var middleware = require('./middleware');
app.get('example/uri', function (req, res, next) {
middleware.first(req, res)
.then(function () { next(); })
.catch(res.json)
.done();
}, function (req, res, next) {
middleware.second(req, res)
.then(function () { next(); })
.catch(res.json)
.done();
});
(basicly pulling the middleware out and testing it)
since this presentation is from 2014 i was wondering what are the current up to date methods for unit testing express apps?
I had the same problem and I used another approach.
First I created a file included in all my tests that start node and export a function to send an http request:
process.env.NODE_ENV = 'test';
var app = require('../server.js');
before(function() {
server = app.listen(3002);
});
after(function(done) {
server.close(done);
});
module.exports = {
app: app,
doHttpRequest: function(path, callback) {
var options = {
hostname: 'localhost',
port: 3002,
path: path,
method: 'GET',
headers: {
'Content-Type': 'application/json',
'Content-Length': 0
}
};
var req = http.request(options,
function(response) {
response.setEncoding('utf8');
var data = '';
response.on('data', function(chunk) {
data += chunk;
});
response.on('end', function() {
callback(data, response.statusCode);
});
});
req.end();
}
}
Then I called my server using the previous declared method:
var doHttpRequest = require('./global-setup.js').doHttpRequest;
var expect = require('chai').expect;
describe('status page test', function() {
it('should render json', function(done){
doHttpRequest('/status', function(response) {
expect(JSON.parse(response).status).to.eql('OK');
done();
})
});
});

Mocha test case for query based functions

I am new to Mocha. Can someone suggest how to write test case for "retrieveEmployee" function.
var mysql = require('mysql');
var dbconfig = {
host:'localhost',
user:'root',
password:'root',
database:'db',
port:'3306'
};
exports.retrieveEmployee = function(req, res){
var connection = mysql.createConnection(dbconfig);
var query ='SELECT emp_Id, emp_Name FROM employee';
connection.query(query, function(err, rows, fields){
if(err)
throw err;
res.render('index', { title: 'Employee', 'items':rows });
});
};
I am using 'MySql' for database.
If your intent is to assert page renderings/functionality I'd use something like Zombie.
Ex:
app.js
app.get("/", function(req, res, next) {
res.render("index", {title: 'Hello World!'});
});
test/app.js
var Browser = require('zombie');
var app = require('../app');
describe("a html endpoin", function() {
var server;
beforeEach(function(done) {
server = app.listen(7331, done);
});
afterEach(function(done) {
server.close(done);
});
it("has some title", function(done) {
var browser = new Browser();
browser.visit("http://localhost:7331/")
.then(function() {
var title = browser.text('title');
assert.equal(title, 'Hello World!');
done();
});
});
});
If your intent is more of an API endpoint, then something like supertest would work nicely.
Ex:
app.js
app.get("/api", function(req, res, next) {
res.send({foo: 'bar'});
});
test/app.js
var request = require('supertest');
var app = require('../app');
describe("an api endpoint", function() {
it("returns some sort of json", function(done) {
request(app)
.get("/api")
.expect(200, {foo: 'bar'}, done);
});
});
However, both Zombie or supertest can be used to do both of these tasks.
Zombie
supertest
Use the assertion library of your choice.

Resources