Jasmine HTTP request testing - node.js

Below is my jasmine test code.
const https = require('http');
var base_url = "http://localhost:3000/";
function testAsync(){
return new Promise((resolve, reject)=>{
https.get(base_url, res => {
console.log("result is : " + res);
let data = [];
const headerDate = res.headers && res.headers.date ? res.headers.date : 'no response date';
console.log('Status Code:', res.statusCode);
console.log('Date in Response header:', headerDate);
res.on('data', chunk => {
console.log("inside data : " +data);
data.push(chunk);
});
res.on('end', () => {
console.log("data" + data);
// console.log('Response ended: ');
// const users = JSON.parse(Buffer.concat(data).toString());
// for(user of users) {
// console.log(`Got user with id: ${user.id}, name: ${user.name}`);
// }
});
resolve();
}).on('error', err => {
console.log('Error: ', err);
resolve();
});
});
}
describe("Hello World Server", function() {
describe("GET /", function() {
it("returns status code 200", async function() {
console.log("before http get");
await testAsync();
console.log("after http get");
});
});
});
when I run it, I get the below error. Could someone help to resolve this error please
LOG: 'before http get'
LOG: 'Error: ', TypeError: Failed to fetch
TypeError: Failed to fetch
at module.exports.ClientRequest._onFinish (http://localhost:9876/absolute/var/folders/s7/lslgtwnx2px86cqjhlfynp_w0000gn/T/3e973e3340db6a2c56d8e559cc233f06.browserify.js?9dffcbb6a2ae2b7cbde165353439c6209f6eaf5f:8593:10)
at module.exports. (http://localhost:9876/absolute/var/folders/s7/lslgtwnx2px86cqjhlfynp_w0000gn/T/3e973e3340db6a2c56d8e559cc233f06.browserify.js?9dffcbb6a2ae2b7cbde165353439c6209f6eaf5f:8511:8)
at module.exports.emit (http://localhost:9876/absolute/var/folders/s7/lslgtwnx2px86cqjhlfynp_w0000gn/T/3e973e3340db6a2c56d8e559cc233f06.browserify.js?9dffcbb6a2ae2b7cbde165353439c6209f6eaf5f:2692:5)
at finishMaybe (http://localhost:9876/absolute/var/folders/s7/lslgtwnx2px86cqjhlfynp_w0000gn/T/3e973e3340db6a2c56d8e559cc233f06.browserify.js?9dffcbb6a2ae2b7cbde165353439c6209f6eaf5f:7444:14)
at endWritable (http://localhost:9876/absolute/var/folders/s7/lslgtwnx2px86cqjhlfynp_w0000gn/T/3e973e3340db6a2c56d8e559cc233f06.browserify.js?9dffcbb6a2ae2b7cbde165353439c6209f6eaf5f:7463:3)
at module.exports.Writable.end (http://localhost:9876/absolute/var/folders/s7/lslgtwnx2px86cqjhlfynp_w0000gn/T/3e973e3340db6a2c56d8e559cc233f06.browserify.js?9dffcbb6a2ae2b7cbde165353439c6209f6eaf5f:7391:22)
at module.exports.ClientRequest.end (http://localhost:9876/absolute/var/folders/s7/lslgtwnx2px86cqjhlfynp_w0000gn/T/3e973e3340db6a2c56d8e559cc233f06.browserify.js?9dffcbb6a2ae2b7cbde165353439c6209f6eaf5f:8763:32)
at Object.get (http://localhost:9876/absolute/var/folders/s7/lslgtwnx2px86cqjhlfynp_w0000gn/T/3e973e3340db6a2c56d8e559cc233f06.browserify.js?9dffcbb6a2ae2b7cbde165353439c6209f6eaf5f:8343:6)
at http://localhost:9876/absolute/var/folders/s7/lslgtwnx2px86cqjhlfynp_w0000gn/T/3e973e3340db6a2c56d8e559cc233f06.browserify.js?9dffcbb6a2ae2b7cbde165353439c6209f6eaf5f:10878:13
at new Promise ()
LOG: 'after http get'

Related

NodeJS how do I get body of a request returning 400 Bad Request

I have the following function in NodeJS that I use to make GET and POST calls to REST APIs
function httpRequest(options, postData) {
return new Promise(function(resolve, reject) {
const https = require('https');
var req = https.request(options, function(res) {
// reject on bad status
if (res.statusCode < 200 || res.statusCode >= 300) {
console.log('Bad status code '+res.statusCode+' '+res.statusMessage);
reject(new Error(res.statusMessage));
}else{
var body = [];
res.on('data', function(chunk) {
body.push(chunk);
});
res.on('end', function() {
resolve(Buffer.concat(body).toString());
});
}
});
req.on('error', function(err) {
console.log('problem with request: ' + err.message);
reject(err);
});
if (postData) {
req.write(postData);
}
req.end();
});
}
The calls may result in a 400 Bad Request or some other error, and there is message in the returned Body. I cannot figure out how to read this body message. The variable res does not contain any property with body data and the res.on('data' event is never called so I could read the body message.
Any help is appreciated.
You will need to move a request status verification to the end event handler:
const req = https.request(options, function(res) {
const body = [];
res.on('data', function(chunk) {
body.push(chunk);
});
res.on('end', function() {
const bodyString = Buffer.concat(body).toString();
if (res.statusCode < 200 || res.statusCode >= 300) {
console.log(bodyString);
reject(new Error(res.statusMessage));
} else {
resolve(bodyString);
}
});
});

HTTP write after end NodeJS error after first request

I have a TCP server that receive messages from a IOT device. When a message is received, my TCP server send it to my REST server via HTTP. But after the first request is successfully send, when the TCP server want to send the second message, I get a write after end error.
This is my Code on the TCP server:
const net = require("net");
const server = net.createServer(onConnected);
const http = require("http");
const querystring = require('querystring');
//HTTP STUFF
const req = http.request(options, (res) => {
console.log(`STATUS: ${res.statusCode}`);
console.log(`HEADERS: ${JSON.stringify(res.headers)}`);
res.setEncoding("utf8");
res.on("data", (chunk) => {
console.log(`BODY: ${chunk}`);
})
res.on("end", () => {
console.log("no more data in res");
})
});
req.on("error", (err) => {
if (err.code === "ETIMEDOUT") {
console.log("problem with request: connection timeout");
} else if (err.code === "ECONNRESET") {
console.log("problem with request: read timeout");
} else {
console.error(`problem with request: ${err.message}`);
}
});
function send(postData) {
console.log("start http");
console.log("post data: " + postData);
req.write(postData, function() {
req.end();
});
};
//TCP
server.listen(PORT, HOST, function() {
console.log("Server listening on &j", server.address());
});
function onConnected(sock) {
var remoteAddress = sock.remoteAddress + ":" * sock.remotePort;
console.log("new client connected: %s", remoteAddress);
sock.on("data", function(data) {
console.log("%s says: %s", remoteAddress, data);
let tcp_message = data.toString("utf8");
let postData = querystring.stringify({
"message": tcp_message
});
console.log("tcp message " + tcp_message)
options.headers = {'Content-Length': Buffer.byteLength(postData) }
send(postData);
let mail_text = "Address: " + remoteAddress + " data: " + tcp_message;
});
sock.on("close", function(){
console.log("connection from %s closed", remoteAddress);
});
server.on("error", function(err){
console.log("connection %s error: %s", remoteAddress, err.message);
});
}

Getting error of timeout exceed in mocha

mocha error: timeout of 2000ms exceeded, for async test and hooks ensure the done() callback is being called in this test. if returning a promise, ensure it resolves.
This is what the error i am getting while trying to get response,
This is my index.js file where i export function
exports.info = function(callback) {
var https = require('https');
var options = {
host: 'api.github.com',
path: '/repos/sayanee/build-podcast',
method: 'GET',
headers: { 'User-Agent': 'sayanee' } };
var str = '';
https.request(options, function(response) {
response.on('data', function(data) {
str += data;
});
response.on('end', function() {
callback(JSON.parse(str));
})
response.on('error', function(error) {
console.log(error);
callback();
})
}) .end();
}
This is my indexfile where i describe the test cases
function asyncFunction() {
return new Promise(resolve => {
setTimeout(resolve, 5000);
});
}
describe('Github info', function() {
it.only('returns repo info from github', async function() {
//this.timeout(5000);
await asyncFunction();
word.info(function(reply) {
console.log("er")
expect(reply.language).to.equal('JavaScript');
expect(reply.watchers).to.equal(157);
console.log('RECEIVED');
});
console.log('HELLO'); })
});
Mocha support async test also by passing done callback as param to it that you need to call at test end
describe("Github info", function () {
it.only("returns repo info from github", function (done) {
// set long timeout to be sure word.info finish
this.timeout(5000);
word.info(function (reply) {
console.log("er");
expect(reply.language).to.equal("JavaScript");
expect(reply.watchers).to.equal(157);
console.log("RECEIVED");
// call done at end
done();
});
console.log("HELLO");
});
});
The response is in your question. Mocha is setted up to timeout after 2 second.
Either you makes your request to finish within 2000ms
Either you increase the Mocha timeout, example :
mocha -t 300000
EDIT :
You cannot use async/await mixed up with callbacks
// Wrap your function into a promise
wordInfoPromise() {
return new Promise((resolve, reject) => {
word.info((ret) => {
if (!ret) return reject();
return resolve(ret);
});
});
}
it('returns repo info from github', async function() {
//this.timeout(5000);
await asyncFunction();
const reply = await wordInfoPromise();
console.log("er")
expect(reply.language).to.equal('JavaScript');
expect(reply.watchers).to.equal(157);
console.log('RECEIVED');
console.log('HELLO'); })
});
EDIT 2 :
const req = https.request(options, (res) => {
res.on('data', (d) => {
str += data;
});
res.on('end', () => {
resolve(str);
});
});
req.on('error', (e) => {
reject();
});
req.end();

Node Async.each http.get request not firing/waiting

I have a larger process running through a large collection of locations/devices in an API response and I'm trying to get to individual devices and turn that into a response my target system will understand. However it seems my inline HTTP request is not firing.
I've tried moving the callback out of the 'end' event, but I'm not even getting the logging for earlier up in the function. The only logging output I get is the "getting status for zone xyz"
async.each(tempSystem.zones, function(zone, zoneCallback) {
var applianceDiscovered = {};
console.log("getting status for zone", zone);
var options = {
host: host,
path: '/webapi/' + zone.zoneId + '/status',
headers: {'Authorization' : 'Bearer ' + accessToken}
};
var req = https.get(options, function(res) {
if (res.statusCode != 200) {
console.log("error ", res.statusCode);
}
console.log(res);
var bodyChunks = [];
res.on('data', function(chunk) {
bodyChunks.push(chunk);
});
res.on('end', function() {
if (res.statusCode === 200) {
console.log("get zone status: ", res.statusCode);
var body = Buffer.concat(bodyChunks);
var zoneStatus = JSON.parse(body);
console.log(zoneStatus);
zoneCallback();
} else {
console.log(res.statusCode);
}
});
res.on('error', function(error) {
console.log(error);
});
});
req.on('error', function(e) {
console.log("error: ", e);
});
}, function(err){
console.log("finished with zones");
});

Using Q library for HTTP api response testing in nodejs

how to use Q to make it wait until previous response has come from the server.
What I am looking to do here is compare the response from test server and production server for the same request.
I get the responses back from both the servers, but unable to compare them since the assert statement is executed before the response comes back.
Any one know what I am doing wrong. heres the code.
var Q = require('q');
var path='';
var prodResponse = '';
var tstReponse = '';
Q.fcall(readFile())
.then(secondFunction())
.then(thirdFunction())
.then(function(){
console.log("prodResponse: "+prodResponse);
console.log("tstResponse: "+tstResponse);
assert.strictEqual(prodResponse, tstResponse)
})
.catch(function(){
console.log('error occurred');
})
.done();
function readFile(){
fs.readFile('hostname.json', function (err, data) {
if (err) return console.error(err);
path = JSON.parse(data);
return JSON.parse(data);
});
}
function secondFunction(){
var prodOptions = {
hostname: 'somehostname.com',
port: 80,
path: "/path?"+path.path,
method: 'POST',
headers: {
'Content-Type': 'application/json;charset=UTF-8'
},
auth : ''
};
return http.request(prodOptions, function(res) {
console.log('Prod');
res.setEncoding('utf8');
res.on('data', function (chunk) {
prodResponse = chunk;
return chunk;
});
res.on('end', function() {
console.log('No more data in response.');
})
}).on('error', function(e) {
console.log('problem with request: ' + e.message);
}).end();
}
function thirdFunction(){
// same a second, only difference is the response http.
}
There is multiple errors in your code
Q.fcall(readFile())
Your q variable is q and not Q. So this line will crash because Q is undefined (javascript is case sensitive).
Then, readFile doesn't return any promise (in fact, it returns nothing). So the q library can't use anything to wait the end of any asynchronous work. The then callbacks will be fired immediatly.
You can use Q.ninvoke to make your readFile function return a promise, and you can use Q.defer to create and return a promise from your secondFunction:
var Q = require('q');
var path='';
var prodResponse = [];
var tstReponse = '';
readFile()
.then(secondFunction())
.then(thirdFunction())
.then(function(){
console.log("prodResponse: "+prodResponse);
console.log("tstResponse: "+tstResponse);
assert.strictEqual(prodResponse, tstResponse)
})
.catch(function(){
console.log('error occurred');
})
.done();
function readFile(){
return Q.ninvoke(fs, 'readFile', 'hostname.json').then(function (data) {
path = JSON.parse(data);
return path;
}, function (err) {
console.error(err);
});
}
function secondFunction(){
var prodOptions = {
hostname: 'somehostname.com',
port: 80,
path: "/path?"+path.path,
method: 'POST',
headers: {
'Content-Type': 'application/json;charset=UTF-8'
},
auth : ''
};
var defer = Q.defer();
var chunks = [];
http.request(prodOptions, function(res) {
console.log('Prod');
res.setEncoding('utf8');
res.on('data', function (chunk) {
chunks.push(chunk);
});
res.on('end', function() {
console.log('No more data in response.');
prodResponse = chunks.join('');
defer.resolve(prodResponse);
})
}).on('error', function(e) {
console.log('problem with request: ' + e.message);
defer.reject(e);
}).end();
return defer.promise;
}
function thirdFunction(){
// same a second, only difference is the response http.
}

Resources