NodeJs Server Request Testing - javascript

For testing my NodeJs Server I am using mocha and supertest.
But I don`t like the simplicity of my tests, they actually are not checking server properly.
// simple test
describe('Server GET requests', function() {
it('GET /index', function(done){
request(app)
.get('/')
.expect(200, done)
})
})
So the test is only checking that server has a response for the request, but is not checking the correctnes of the response. I want test to be looking something like this:
// test should be
describe('Server GET requests', function() {
it('GET /index', function(done){
request(app)
.get('/')
.expect(200)
.end(function (err, res) {
if (err != null)
done(err);
checkContentTitle('Home Page', res.text);
checkContent(params, res.text);
done();
})
})
})
// function to check the title of the send result
function checkContentTitle(title, htmlText){
// checkTitle(title, parse('title', htmlText));
}
But I can`t find the propriate way of doing this.
What is a good practice of testing server responses, GET-request responses for example?
I suppose I need some tols like html\DOM parser, to get specific tags? Can somebody advise proper tools?

Try the cheerio library:
cheerio
It works like jquery for selecting DOM elements, very easy to use.
You can compare the cheerio returned values with the assertions that you want.
Example of test/test.js:
var assert = require("assert");
var cheerio = require('cheerio');
var request = require('request');
describe('domtesting', function() {
describe('GET /', function () {
it('title must be Hello', function (done) {
request('http://example.com/',function(err,response,html){
if(!err){
var $ = cheerio.load(html);
assert.equal('Hello', $('title').text());
done();
}
else{
console.log(err);
}
})
});
});
});
Use named functions or mocha promise syntax in order to get more readable and maintainable code. I also used the request library for launch http request inside tests.

Related

express, mocha testing always returns 404

My express POST route is:
app.post("/addPost", function(req, res) {
let newComment = { post: req.body.createP, comment: req.body.createC };
myDB.push(newComment);
res.render("index.ejs", { posts: myDB });
});
And my mocha test
describe("POST /", function() {
it("it ", function(done) {
supertest(myApp.app)
.post("/")
.expect(200)
.end(function(err, res) {
if (err) return done(err);
done();
});
});
});
Manually, the POST route works fine, but the mocha test always returns 404 instead of 200. Also, the mocha test for GET routes does work. Any ideas whats causing this?
Plus, how would one test html form data being sent via a POST request. Thanks in advance!

Using chai to mock http requests

I'm testing a nodejs app written using express. For the unit testing I'm using chai and sinon. I have the following route in my API that I would like to test.
In my test, I'm simulating the get request with the following code:
chai.request(app)
.get('/downloads')
.send({ wmauth: {
_identity: {
cn: "username",
}
} })
.end((err, res) => {
res.status.should.be.equal(200);
res.body.should.be.a('object');
res.body.should.have.property('Items', []);
AWS.restore('DynamoDB.DocumentClient');
done();
However, I'm always getting the error "Cannot read property '_identity' of undefined". Because the object "wmauth" is not sent in the request, so it is undefined. I have tried to use the send method to try to include it in the request, but no luck. I guess I need to mock it somehow and send it into the request but have no idea how to do it. Could someone help me with this?
Below the method to test:
app.get('/downloads', async (req, res) => {
const created_by_cn = req.wmauth['_identity'].cn;
if(!created_by_cn) {
return res.status(400).json({
error: 'Mandatory parameters: created_by_cn',
});
}
try {
const data = await downloadService.getDownloads(created_by_cn);
return res.status(200).json(data);
}
catch(error){
res.status(500).json({error: error.message});
}
});
THanks
I guess you forgot to use req.body as in:
const created_by_cn = req.body.wmauth['_identity'].cn;
Hope can solve your issue
Since chai-http use superagent, so according to its doc, you need to use query() in order to pass query parameter in get request:
chai.request(app)
.get('/downloads')
.query({ wmauth: {_identity: {cn: "username"}}})
.end((err, res) => { ... });
Then in the express route you can find the parameters in req.query:
app.get('/downloads', function (req, res) {
const created_by_cn = req.query.wmauth._identity.cn;
...
})

Retrieving metrics through librado using NodeJS

Good morning!
I'm having troubles trying to get a single number from librato to use in a html page.
I just want to get the last value of the metric AWS.Billing.EstimatedCharges.total, the name of the client that spent that value and put it all together in a HTML page (simple, but not to me)
I'm trying to use this API https://github.com/goodeggs/librato-node
And I still not figured out how to solve this problem.
ps: I cannot use the embed chart.
var http = require('http');
http.createServer(function (req, res) { }).listen(1337, "127.0.0.1");
console.log('Server running at 127.0.0.1:1337/');
var librato = require('librato-node');
api = librato.configure({email: 'myemail', token: 'mytoken'});
librato.start(); process.once('SIGINT', function() { librato.stop();
// stop optionally takes a callback });
// Don't forget to specify an error handler, otherwise errors will be thrown
librato.on('error', function(err) { console.error(err); });
Try npm install librato-metrics, there's a lot of guessing here so please report back }8*)
const client = require('librato-metrics').createClient(
{
email: process.env.LIBRATO_METRICS_EMAIL,
token: process.env.LIBRATO_METRICS_TOKEN
}
const payload = {
count: 1,
resolution: 60
};
client.get('/metrics/AWS.Billing.EstimatedCharges.total', payload,
function(err, response) {
if (err) {
console.error(err, payload);
} else {
console.log(response);
}
});
```

Strongloop Loopback remote hooks not triggered with supertest?

We are testing our loopback API code using spec.js files like this:
Require libs:
var app = rewire('../..');
var request = require('supertest');
var assert = require('chai').assert;
json helper method to standardize headers and content type:
function json(verb, url) {
return request(app)[verb](url)
.set('Content-Type', 'application/json')
.set('Accept', 'application/json')
.expect('Content-Type', /json/);
}
A test of a custom remote method that requires auth:
describe("Order remote methods", function() {
var accessTokenId, userId;
// authenticate before each test and save token
before(function(done) {
json('post', '/api/People/login')
.send({ email: 'user#email.com', password: 'password' })
.expect(200)
.end(function(err, res) {
accessTokenId = res.body.id;
userId = res.body.userId;
assert(res.body.id);
assert(res.body.userId);
done();
});
});
it("should fetch user orders", function(done) {
json('get', '/api/Orders/specialOrders')
.set('Authorization', accessTokenId)
.send({id: userId})
.expect(200)
.end(function(err, res) {
var orders = res.body.orders;
assert(Array.isArray(orders), "Orders should be an array");
// more asserts for explicit data values
done();
});
});
});
/api/Orders/specialOrders is a custom remote method that does a custom query on the Order model, which works as expected. But when I add a beforeRemote hook for this model, it does not get triggered by running the test. Is this expected or is my test setup not complete?
Remote hook:
Order.beforeRemote('specialOrders', function(ctx, unused, next) {
console.log('[userOrders]');
console.log('ctx req token: ', ctx.req.accessToken.userId);
console.log('ctx args: ', ctx.req.params.id);
// prevent remote method from being called
// even without a next(), remote is executed!
next(new Error('testing error'));
});
Running the same custom method via the Explorer UI, the beforeRemote hook is triggered as expected, and reports the custom error (or hangs when the next() is not present).
Is it possible to get supertest to trigger remote hooks in tests like this or am I missing some app setup in the spec file?

Mongoose open connection issue with Supertest

I am unable to run multiple Supertest/Mocha tests as I get an error Error: Trying to open unclosed connection. - I found this post which suggest looping and checking connection status. Wondering if there is a better way? perhaps something that was added in Supertest recently to handle this.
In your Mocha tests add a before function to connect to MongoDB like so
var mongoose = require('mongoose');
describe('My test', function() {
before(function(done) {
if (mongoose.connection.db) return done();
mongoose.connect('mongodb://localhost/puan_test', done);
});
});
Ok - was pretty close. What I had to do was remove the describe method call and place a before() call in a common file to all tests - supertest or just straight mocha unit tests.
var db;
// Once before all tests - Supertest will have a connection from the app already while others may not
before(function(done) {
if (mongoose.connection.db) {
db = mongoose.connection;
return done();
}
db = mongoose.connect(config.db, done);
});
// and if I wanted to load fixtures before each test
beforeEach(function (done) {
fixtures.load(data, db, function(err) {
if (err) throw (err);
done();
})
});
By omitting the describe() call the above it makes it available to all tests.
// Also you can use the 'open' event to call the 'done' callback
// inside the 'before' Mocha hook.
before((done) => {
mongoose.connect('mongodb://localhost/test_db');
mongoose.connection
.once('open', () => {
done();
})
.on('error', (err) => {
console.warn('Problem connecting to mongo: ', error);
done();
});
});

Categories