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

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();
})
});
});

Related

issue with react ui communicating with node

This is the react fetch:
var json = {
json: JSON.stringify({
a: 1,
b: 2
}),
delay: 3
};
fetch('/saveInfo', {
method: 'post',
headers: {
'Accept': 'application/json, text/plain, */*',
'Content-Type': 'application/json'
},
body: JSON.stringify(json.json)
})
.then(function (response) {
return response.json();
})
.then(function (result) {
alert(result);
console.log("The file was saved!");
})
.catch (function (error) {
console.log('Request failed');
});
This is node:
<pre>
var express = require('express');
module.exports = function(app) {
var router = express.Router();
router.get('/', function (req, res) {
console.log('from node');
console.log(req);
res.json({status: 'UP'});
});
app.use("/saveInfo", router);
}
</pre>
The code above doesn't work with the 2nd parameter to the fetch.
But when I execute it w/o the second parameter to fetch as below:
fetch('/saveInfo')
.then(function (response) {
return response.json();
})
.then(function (result) {
alert(result);
console.log("The file was saved!");
})
.catch (function (error) {
console.log('Request failed');
});
Works fine and is able to communicate to the node program.
Can any one help me with this what is wrong. I wanted to send the react's UI forms state t the node program.
You need to add a handler for the POST requests also.
In the fetch method for 1st case, you have given the method type as POST but node doesn't have any handling for that.
However, when you don't give the second parameter, it is considered as GET request and is intercepted by router.get.
Just add this in the node (before app.use line):
router.post("/", function (req, res) {
console.log('from node');
console.log(req);
res.json({status: 'UP'});
});
It will enable node to listen for POST requests.
Edit: To have access to post request body params in router.post, you need body-parser package. Install this package and add these two lines before initializing the express router:
app.use(bodyParser.json())
app.use(bodyParser.urlencoded({ extended: false }))
Read http://jilles.me/express-routing-the-beginners-guide/ for detailed explanation

how to get data from an api on the server side and pass the data retrieved to pugjs file using expressjs?

sample code:
// index.pug
p #{polls}
// apiendpoint
http://localhost:8080/api/polls
// routes file (index.js):
Here, how do I make get request to the api, and pass the retrieved result from api(locals) to polls variable while rendering the profile.pug
app.route('/profile')
.get(isLoggedIn, function (req, res) {
res.render('profile', {'polls': passvaluehere});
});
});
You can also use **http** module like this
var http = require('http');
var options = {
host: 'localhost',
path: '/api/polls',
port: '80',
method: 'GET'
};
var req = http.request(options, response);
var str = ''
response.on('data', function (chunk) {
str += chunk;
});
response.on('end', function () {
console.log(str);
res.render('profile', {'polls': str});
});
req.end();

Node.js: Unable to compress response using express

I am using express version 4.13.4 and the following code for my app.js. I have tried changing the location of app.use(compression()) which did not show any effect. when I run the application I saw no evidence of compression in viewing the chrome dev tools response headers i.e it doesn't have the gzip content-encoding header.
I am new to node js.I want to gzip compress my response to browser. Please help me fix this issue.
var compression = require('compression')
var express = require('express');
var http = require('http');
var app = express();
app.use(compression());
var settings = {
UiServerPort: 8080,
ApiServerHost: "localhost",
ApiServerPort: 12121
};
app.use('/ui', express.static('ui'));
app.all('/api/*', function (req, res) {
var options = {
host: settings.ApiServerHost,
port: settings.ApiServerPort,
path: req.url.substring(4),
method: 'POST'
};
var requestData = '';
req.on('data', function (data) { requestData += data; });
req.on('end', function () {
var request = http.request(options, function (response) {
var responseData = '';
res.flush();
response.on('data', function (data) { responseData += data; });
response.on('end', function () {
res.statusCode = response.statusCode;
res.write(responseData);
res.end();
});
});
request.write(requestData);
request.end();
});
});
app.listen(settings.UiServerPort)
you saw " Vary Accept-Encoding " ?? if you don't use compression , this won't show. and I paste your code ,but It can't run.
Instead of
app.use(compression())
You should add this piece of code :
app.use(compression({filter: shouldCompress}))
function shouldCompress (req, res) {
if (req.headers['x-no-compression']) {
// don't compress responses with this request header
return false
}
// fallback to standard filter function
return compression.filter(req, res)
}
PS : it works for me.

Error: "tunneling socket could not be established, cause=getaddrinfo ENOTFOUND" code: 'ECONNRESET'

I am using node wget to download files from URL and I am getting this error.
If I use simple wget command to download files it working fine, but I want download file from node module
here is my code
var wget = require('wget');
var router = express.Router();
/* GET home page. */
router.get('/', function(req, response) {
var options = {
protocol: 'https',
host: 'raw.github.com',
path: '/Fyrd/caniuse/master/data.json',
proxy: 'http://host:port',
method: 'GET'
};
var req = wget.request(options, function(res) {
var content = '';
if (res.statusCode === 200) {
res.on('error', function(err) {
console.log(err);
});
res.on('data', function(chunk) {
content += chunk;
});
res.on('end', function() {
console.log(content);
});
} else {
console.log('Server respond ' + res.statusCode);
}
});
req.end();
req.on('error', function(err) {
console.log(err);
});
response.render('index', { title: 'Express' });
});
module.exports = router;
I stumble upon this question. This is probably caused by the proxy not supporting HTTPS. Try a proxy that supports HTTPS and the problem should be solved.

Node.js - simple Restify POST Mocha test failing

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.

Resources