node.js / express / mocha testing post request issue - node.js

I built an app using node.js + expressjs and am using mocha to test my post request. My test is failing because the response from my post request is null but I don't know why...
My API:
api.post('/api/addreport', function(req, res) {
console.log('add report hit..'); //this does not print during testing
console.log(req.body); //this does not print during testing
res.sendStatus(200);
});
My test:
var express = require('express');
var app = express();
var chai = require('chai');
var expect = require('chai').expect;
var should = require('should');
var supertest = require('supertest');
var server = supertest.agent("https://localhost:3001");
var request = require('supertest');
var bodyParser = require('body-parser');
//Body parser
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
it("should post", function(done){
request(app.listen())
.post('/api/addreport/')
.send(data)
.end(function(res){
console.log('---response---');
console.log(res); //returns null
expect(res.status).to.equal(200); //returns status of null
done();
})
});
running mocha ajax results in:
1) should post:
Uncaught TypeError: Cannot read property 'status' of null
My data:
var data = {
report_id: 'abc123' + Math.random(10),
project_code: 'test_project_code',
startDate: '2016-01-01',
endDate: '2016-01-15',
};
Can someone help?
Thanks in advance!

If you are using supertest it doesn't require that you start your app in any port. Just add app.listen at supertest request
var express = require('express');
var app = express();
var chai = require('chai');
var expect = require('chai').expect;
var should = require('should');
var supertest = require('supertest');
var server = supertest.agent("https://localhost:3001");
var request = require('supertest');
var bodyParser = require('body-parser');
//Body parser
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
it("should add report", function(done){
request(app.listen()) // change here
.post('/api/addreport/')
.send(data)
.expect(200)
.end(function(err,res){
done();
});
});

Related

Both POST/GET requests yield a 404 error in Postman. Is my Express routing to blame?

I am intending to set up a Node.js server with MongoDB to handle HTTP CRUD requests. Upon setting up my endpoint I was initially able to receive POST/GET requests, however the handling of the document objects became the issue. Upon trying to fix this issue I am now unable to POST/GET at all? Is this simply a syntax issue or is my code doomed?
const MongoClient = require('mongodb').MongoClient;
var QRCode = require('qrcode');
var canvasu = require('canvas');
var express = require('express');
var mongoose = require('mongoose')
var app = express();
var port = process.env.PORT || 3000;
var bodyParser = require('body-parser');
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
var db;
var collection
var Patient = require('./ShiftAssist/models/patientModel');
var router = express.Router();
''
CODE FOR CONNECTION
''
router.get('/patients/:Pnum', function(req,res,next){
Patient.findOne({Pnum:req.params.Pnum},function(err,patient){
if (err) return next(err);
res.json(patient);
})
});
app.use('/', router);
app.listen(3000, function () {
console.log('Example app listening on port ' + port + '!');
});
Expected: GET request to http://127.0.0.1:3000/patients/XXXXXX with a document identifier, returns entire document
Actual: Timeout Error
try to change you route by /patients/:Pnum
and your request should be http://127.0.0.1:3000/patients/XXXXXX
source: https://expressjs.com/en/guide/routing.html
EDIT: Code i used so far
var express = require('express');
var app = express();
var router = express.Router();
router.get('/patients/:Pnum', function (req, res, next) {
setTimeout(() => res.json({ ok: req.params.Pnum }), 1000)
});
app.use('/', router);
app.listen(3000);

Testing failed with Mocha, Chai and Supertest (NodeJS), retrieving data from mongodb

It is my first time testing the routes in node js and I'm using mocha, supertest and chai. Here is my server.js file:
const express = require('express');
const app = express();
const path = require('path');
const http = require('http').Server(app);
const io = require('socket.io')(http);
const bodyParser = require('body-parser');
const fs = require('fs');
//const helpers = require('./includes/helpers.js');
var cors = require('cors');
app.use(cors());
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(express.static(path.join(__dirname, '../dist/chat/')));
require('./listen.js')(http);
app.use((req, res, next) => {
res.setHeader("Access-Control-Allow-Origin","*");
res.setHeader("Access-Control-Allow-Headers","Origin, X-Requested-With, Content-Type, Accept");
res.setHeader("Access-Control-Allow-Methods","GET, POST, PATCH, DELETE, OPTIONS");
next();
});
const MongoClient = require('mongodb').MongoClient;
const url = 'mongodb://localhost:27017';
MongoClient.connect(url, { poolSize: 10 }, function (err, client) {
if (err) { return console.log(err) }
const dbName = 'testdb';
const db = client.db(dbName);
require('./routes/create.js')(app, db);
require('./routes/remove.js')(app, db);
require('./routes/update.js')(app, db);
require('./routes/read.js')(app, db);
require('./routes/add.js')(app, db);
require('./routes/auth.js')(app, db);
require('./routes/search.js')(app, db);
});
And i want to test the read.js route, basically the read route returns a JSON array which has a few key/value parameters e.g. id (key), name (key) etc.
this is my test.js file:
var assert = require('assert');
const express = require('express');
const app = express();
var read = require('../server/routes/read.js');
var http = require('http');
var helpers = require('./include/helpers');
//var api = require('../server/server.js');
var should = require('chai').should();
var expect = require('chai').expect;
var supertest = require('supertest');
var api = supertest('http://localhost:3000');
var request = require('supertest');
describe('The read route',()=>{
it('should be an object with valid parameters',function(done){
api.get('/api/read')
.set('Accept','application/json')
.expect(200)
.end(function(err,res){
if (err) throw err;
expect(res.body).to.not.equal(null);
expect(res.body).to.have.property('id');
done();
});
});
});
The testing works fine, the only issue is that when i run the line: 'expect(res.body).to.have.property('id')' , the test fails saying that expected [], i dont get it whats wrong, my read route returns a JSON array with parameters: {id:4,prodname:'iPhone',type'phone',description:'Nice phone'} (BTW it is returning data from mongodb)
it should detect the id inside the parameter. Any help?

Nodejs return data after get request inside a post request

i'm trying to pass get request answer to the post request but can't, can someone help me please?
var app = require('express')();
var http = require('http').Server(app);
var bodyParser = require('body-parser');
var request = require('request');
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
http.listen(9999, function() {
console.log('listening...');
});
app.post('/bot',function(req,res){
var apiurl = 'https://apiURI'
request(apiurl, function(error,response,body){
res.send(body)
})
}
when i receive the api answer should send to client who make the post request with res.send
error: Can't set headers after they are sent.
Error solved, deleting the end() method outside the get request due to it's a async request (my mistake)
var app = require('express')();
var http = require('http').Server(app);
var bodyParser = require('body-parser');
var request = require('request');
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
http.listen(9999, function() {
console.log('listening...');
});
app.post('/bot',function(req,res){
var apiurl = 'https://newsapi.org/v1/articles?source=techcrunch&apiKey=72cc6a313e2b4fb3af09e4593ee06fbc'
request(apiurl, function(error,response,body){
res.send(body)
})
//res.end()
})

Request body undefined in supertest

I am testing an express API with supertest. I am trying to pass in body parameters into the test, as can be seen in the code snippets below, but it appears that the body parameters don't get passed in correctly since I get an error message that the body parameters are undefined.
Running the test with command mocha --recursive returns the following error:
Cannot read property 'email' of undefined
Below is the code from file email-suite.js referencing supertest
'use strict';
var express = require("express");
var bodyParser = require('body-parser');
var mongoose = require("mongoose");
var app = express();
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
var supertest = require("supertest");
var chai = require("chai");
var should = chai.should();
var api = require("../server.js");
describe("Email Module", function() {
this.timeout(25000);
before(function(done){
mongoose.createConnection(/* connectionstring */);
mongoose.connection.on('open', function(err) {
if(err) console.log(err);
console.log('connected to server');
});
done();
});
it("Check Email Count", function(done) {
var body = { email: "email#email.com" };
supertest(api)
.post("/emailCount")
.set('Accept', 'application/json')
.send(body) // body is undefined
.expect(200)
.expect('Content-Type', /json/)
.end(function(err, res) {
if(err) return done(err);
res.body.count.should.equal(2);
done();
});
});
});
Below is the code from file email-api.js
'use strict';
var express = require("express");
var bodyParser = require('body-parser');
var router = express.Router();
var app = express();
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
router.post('/emailCount', function(req, res) {
var email = req.body.email; // req.body is undefined
}
module.exports = router;
Below is the code from the file server.js
var express = require("express");
var app = express();
app.set("port", process.env.PORT || 3000);
var router = require("./user/email-api");
app.use('/', router);
app.listen(app.get("port"), function() {
console.log("App started on port " + app.get("port"));
});
module.exports = app;
Put body-parser always after express object and before every routes in main server file like this
var app = express();
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: true}));
//Router task start from here
Other wise always will get undefined since router call first and body parsed later.
Thank you abdulbarik for your answer. I want to add some extra information to aid clarity in case people are still getting undefined values for the request body object, and if (as in my case) your routers and tests are setup differently.
Here is the router that we shall test:
// router.js
const express = require("express");
const router = express.Router();
router.post("/", (req, res) => {
res.json({ success: true, data: req.body });
});
module.exports = router;
The following test code will result in the request body being undefined, and thus the test failing:
// router.test.js
const express = require("express");
const request = require("supertest");
const bodyParser = require("body-parser");
// set up the test app - this will fail
const app = express();
app.use("/routerPath", require("./router")); // this will cause the test to fail, as the router should be setup after the body-paser
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
// run the test
it("successful response", async () => {
const response = await request(app)
.post("/routerPath")
.send({
firstname: "John",
lastname: "Smith",
})
.set("Accept", "application/json");
expect(response.status).toEqual(200);
expect(response.body).toEqual({
success: true,
data: {
firstname: "John",
lastname: "Smith",
},
});
});
The reason why, as explained by abdulbarik, is that the body-parser code should always be before the router code, so that the parser runs before the router. To make the test pass, simply swap these lines around:
// set up the test app - this will work now
const app = express();
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use("/routerPath", require("./router")); // the router setup should happen after the body-parse setup
I hope that is a helpful clarification.

express router use meld to log request parameters and response

I use meld in my express project and I wanna log my api request with meld,This code below is my first try:
var meld = require('meld');
var express = require('express');
var router = express.Router();
var app = express();
var logger = {
apiAround:function(method){
//TODO:log before request
var result = method.proceed();
//TODO:log after request
return result;
}
};
meld.around(router,'get',logger.apiAround);
router.get('/',function(req,res){
//TODO:handle request
});
app.use('/',router);
but it seems not work,what is the problem?
I found the solution to this problem,actually I want to record my request param/response/response time,so this is code with middleware response-time
var responseTime = require('response-time');
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(responseTime(function(req,res,time){
if(req.baseUrl.indexOf('/xxxxxx') !== -1)
{
console.log(req.body);
console.log(time);
console.log(res);
}
}));

Resources