Getting random results on Travis - node.js

My tests gives random results on Travis. Here are the logs where my tests did fail on Travis:
https://travis-ci.org/superzaky/node-portfolio-zaky/builds/149718369
And here are the logs where my tests did pass on Travis:
https://travis-ci.org/superzaky/node-portfolio-zaky/builds/149560005
Both branches contain the exact same code.
And on my computer I can also make the tests pass link to screenshot: http://i.imgur.com/zXOINsD.png
I had also cloned my repository on my laptop. And there the tests also pass.. I suspect it has something to do with the way I had written
my tests in 100-Login.js:
require('../utils');
require('events').EventEmitter.prototype._maxListeners = 100;
var supertest = require("supertest");
var should = require("should");
var assert = require('chai').assert;
var app = require('../../app');
// This agent refers to PORT where our program is running.
var server = supertest.agent(app);
// UNIT test begin
describe("A user logs in", function () {
it('should create a SINGLE session on /api/auth/login POST', function (done) {
//calling LOGIN api
server
.post('/api/auth/login')
.send({
username: "jimmy",
password: "open"
})
.expect("Content-type", /json/)
.expect(200)
.end(function (err, res) {
var data = {
_id: "000000000000000000000001",
name: "Jimmy Doe",
username: "jimmy",
admin: false
};
res.status.should.equal(200);
assert.deepEqual(res.body, data);
done();
});
});
it('should display a SINGLE session on /api/auth/ GET', function (done) {
//We check if a session is created by sending a GET request to /api/auth
server
.get('/api/auth/')
.expect("Content-type", /json/)
.expect(200)
.end(function (err, res) {
var data = {
_id: "000000000000000000000001",
name: "Jimmy Doe",
username: "jimmy",
admin: false
};
res.status.should.equal(200);
assert.deepEqual(res.body, data);
done();
});
});
it('should delete a SINGLE session on /api/auth/logout GET', function (done) {
//We check if a session is created by sending a GET request to /api/auth
server
.get('/api/auth/logout')
.expect("Content-type", /json/)
.expect(200)
.end(function (err, res) {
var data = "Successfully logged out";
res.status.should.equal(200);
assert.deepEqual(res.body, data);
done();
});
});
it('should NOT display a SINGLE session on /api/auth/ GET', function (done) {
//We check if a session is created by sending a GET request to /api/auth
server
.get('/api/auth/')
.expect("Content-type", /json/)
.expect(404)
.end(function (err, res) {
var data = "Session not found";
res.status.should.equal(404);
assert.deepEqual(res.body, data);
done();
});
});
});
require('events').EventEmitter.prototype._maxListeners = 0;
And here is the actual code that made the tests pass link: https://github.com/superzaky/node-portfolio-zaky/blob/travis/controllers/AuthController.js
But that looks fine to me. Anyone that maybe has a clue on how to fix this problem?

You should check what's in your local database.
Based on your other tests, which initially register a user with username = john (see this test, line 20), there will be no user with username = jimmy, which is what you use as the username credential when POSTing to /api/auth/login in the test that fails (see this test, line 18).
The tests that pass on your local machine probably pass because you also have a user named "jimmy" in your local db.
As far as why the second test fails, it fails because the session creation test fails right before it and it is expecting a session to exist for "jimmy".

Related

Why does my timeout is exceeded?

I'm developing an API with Node.js and Express and i'm using Mocha and Supertest to write unit tests. I have a BIG file of tests which test every route with almost random parameters to see if my error handling works well.
Everything was great until, for no reason, my requests are starting to timeout.
This is more or less my code :
var supertest = require("supertest");
var should = require("should");
var server = supertest.agent("http://localhost:3000");
function requestAuth(url, type, auth, params, callback) {
if (params == null) {
server[type](url)
.type('form')
.auth(auth.email, auth.password)
.expect("Content-type",/json/)
.expect(200)
.end(callback);
}
else {
server[type](url)
.send(params)
.auth(auth.email, auth.password)
.type('form')
.expect("Content-type",/json/)
.expect(200)
.end(callback);
}
}
describe('Testing route 1', function() {
describe('Testing param 1 error handling', function() {
it('should return error 1', function(done) {
requestAuth(route1, "post", {email: email, password: password}, {param1: "blahblahblah"},
function(err, res) {
res.body.should.have.property('error');
done();
});
});
it('should return error 2', function(done) {
requestAuth(route1, "post", {email: email, password: password}, {param1: "blahblahblah"},
function(err, res) {
res.body.should.have.property('error');
done();
});
});
// etc
});
describe('Testing param 2 error handling', function() {
it('should return error 3', function(done) {
requestAuth(route1, "post", {email: email, password: password}, {param1: "blahblahblah"},
function(err, res) {
res.body.should.have.property('error');
done();
});
});
it('should return error 4', function(done) {
requestAuth(route1, "post", {email: email, password: password}, {param1: "blahblahblah"},
function(err, res) {
res.body.should.have.property('error');
done();
});
});
// etc
});
//etc
});
describe('Testing route 2', function() {
//etc
});
Except that i have of LOT of tests.
At some point, let say that when i'm testing route 8, every tests starts to fail with the following message :
12) Route 8 Testing Param 1 error handling should return error 1:
Error: timeout of 2000ms exceeded
at null.<anonymous> (/usr/lib/nodejs/mocha/lib/runnable.js:139:19)
at Timer.listOnTimeout (timers.js:92:15)
I really don't get it. Everything worked well since then, done is called at the end of every request, should be good. Nothing happens on the server side even though routes are ok. This is really weird...
Also, if the route 8 tests are getting weird, and that i comment route 7 tests for example, than route 9 tests will starts to act wrong.
I think this is coming from supertest. Is it possible that it is overloaded ? How could i fix that ?
Thanks in advance for your responses.
Your tests themselves have a time limit to complete your actions. This means that if the resource isn't set up and available in those two seconds, or if the test completes after two seconds it will fail. Use this.timeout = [milliseconds] as the first line of the failing test to extend the timeout.
MochaJS Test Level Timeouts

Dynamically testing authentication RESTful API (NodeJS, Mocha, SuperAgent)

Goal:
I am trying to test my authentication RESTful API. The tools i am using are NodeJS with the modules: Mocha, Supertest(.agent) and chai(.assert).
What i tried:
var users = [ new User("admin", "secretPass"), new User("guest", "Pass")];
describe('request some protected data', function(){
users.forEach(function(user){
before(function(){
agent.post('/login').send({ user.username, user.key })
.end(function(err, res) {
}
}
it('get data', function(done){
agent.get('/data').send({ user.username, user.key })
.end(function(err, res) {
// assertions on data
}
}
}
}
The problem:
Using something similar to the snippet above results in multiple before functions being executed at once and after that all the tests(it).
So agent will always be logged in as the last user in users.
I tried to replace before with beforeEach and place it above users.forEach, but then user will be out of scope.
Can anyone provide me with a small snippet of code that will explain a suitable solution for my problem?
You need to tell Mocha that your before function is asynchronous, by accepting a done parameter and calling it when logging in has completed, e.g.
before(function(done){
agent.post('/login').send({ user.username, user.key })
.end(function(err, res) {
// I assume you're logged in here...
done();
}
}
Of course, you'll also want to add the required error handling etc. You'll probably want to create a new describe block for each user too, otherwise all of the login calls will run before any user tests happen, e.g.
users.forEach(function(user){
describe("user X tests", function() { // <-- NEW
before(function(){
agent.post('/login').send({ user.username, user.key })
.end(function(err, res) {
}
}
it('get data', function(done){
agent.get('/data').send({ user.username, user.key })
.end(function(err, res) {
// assertions on data
}
}
}); // <- NEW
}

send authenticated request via supertest with mocha on a passport managed API

It's been 24 hours since I first had this issue. I know there plenty of similar ones, specially on SO but I can't figure out how to solve it.
I have specific requirement :
I have some routes to test without authentication.
I have some routes to test with specific users.
I use a passport local strategy.
So I decided to test my API like :
var request = require('supertest');
...
describe('Routes', function () {
var anAgent;
var anotherAgent;
before(function (done) {
anAgent = request.agent(app);
anotherAgent = request.agent(app);
async.parallel([
function (callback) {
anAgent
.post('/api/users/login')
.send({user:user, password:password})
.expect(200)
.end(callback);
},
function (callback) {
userAgent
.post('/api/users/login')
.send({user:anotherUser, password:anotherPassword})
.expect(200)
.end(callback);
}
], done);
});
describe('/superroute', function () {
it('should return the user', function (done) {
anAgent
.post('/api/superroute')
.send(params)
.expect(200)
.end(function (err, res) {
should.not.exist(err);
res.body.err.should.equal('Super route');
done();
});
});
...
});
...
});
The route /superroute is describe like
express.Router().post('/superroute', auth.ensureAuthenticated, superCtrl.superroute);
Where ensureAuthenticated middleware call the req.isAuthenticated() of passport.
This API works fine when I use it from a simple angular front but when I run the test with mocha, the passport.deserializeUser method is not called and isAuthenticated return false. With the fact that the user is correctly logged and retrieved from the /login call, it's all I know.
So the call returns 401 instead of 200.
What can I've possibly missed ?

How do I simulate Strongloop's update method with Supertest/Superagent?

I'm working on some tests for strongloop/loopback APIs using supertest and mocha. One of the standard endpoints is Model/update. Update is actually a form of PersistedModel.updateAll which takes in a query and then posts to all entries that match the query. This is a picture of what a successful request looks like in the explorer:
Notice from the picture that the request URL is mainly just a query string, and that it returns 204. I know from the superagent docs that you can submit querys with a post. However I'm having a lot of trouble duplicating this with my tests.
Here are my require statements:
var request = require('supertest');
var app = require('../server');
var assert = require('chai').assert;
var chance = require('chance').Chance();
Here are my tests
describe('/api/Points/update', function(){
var updatedZip = "60000";
it('should grab a Point for a before reference', function(done) {
json('get', '/api/Points/' +addID )
.end(function(err, res) {
assert.equal(res.body.zipcode, addZip, 'unexpected value for zip');
done();
});
});
it('should update the Point w/ a new zipcode', function(done) {
var where = {"zipcode": "60035"};
var data ={"zipcode": updatedZip};
request(app)
.post('/api/Points/update')
.query({"where": {"zipcode": "60035"}})
.send({
data : data
})
.end(function(err, res) {
assert.equal(res.status, 204, 'update didnt take');
done();
});
});
it('should check to see that the Point was updated', function(done) {
json('get', '/api/Points/' +addID )
.end(function(err, res) {
assert.equal(res.body.zipcode, updatedZip, 'updated zip was not applied');
done();
});
});
The first test passes, meaning that it returned a 204 as the status of the request however it fails the second test meaning that even though it found the query acceptable it didn't actually apply the update. I've tried a number of different formulations but none of them have worked. Please let me know how I could possibly simulate this! Thanks in advance for your help!

Node.js / Mocha / Supertest REST api -- a del() stopped working after I added a second suite

so I've got a model I'm trying to test. It has custom endpoints as well as the standard REST endpoints. I built a suite to test the standard ops. First I posted, then I upserted(a put w/o an id...basically a post), then I got. Finally I deleted the entry created when I posted, and just clean up after myself I put in an after hook to delete the point I had upserted. This worked and it was good.
Then, in the same file I added another suite, this one testing my custom endpoints. Now my hook that was supposed to delete the upserted point failed. This was not good. I tried wrapping my test for delete in a new describe statement, but again it didn't work. Eventually I did away w/ the hook altogether and just sent 2 .del calls and it still didn't work. I'm at my wits end. Please let me know if you can figure out why this isn't working and how to make it work. Thank you in advance!
Here is my code:
var request = require('supertest');
var app = require('../server');
var chai = require('chai');
var chance = require('chance').Chance();
var assert= require('assert');
function json(verb, url) {
return request(app)[verb](url)
.set('Content-Type', 'application/json')
.set('Accept', 'application/json')
.expect('Content-Type', /json/);
}
describe('Testing standard REST endpoints-(CREATE, GET,PUT, DELETE)', function() {
//This suite tests the CREATE functionality
var ptOneID;
var lat1 =chance.latitude({fixed: 7, min: 41, max: 42});
var lng1 = chance.longitude({fixed:7, min: -88, max:-87});
it('should post a new point', function(done) {
var pt1 = new app.loopback.GeoPoint({lat: lat1, lng: lng1});
json('post', '/api/Points')
.send({
location: pt1,
})
.expect(200)
.end(function(err, res) {
ptOneID= res.body.id;
done();
});
});
//This test preforms a put with out an id-- an upsert
var lat5 =chance.latitude({fixed: 7, min: 41, max: 42});
var lng5 = chance.longitude({fixed:7, min: -88, max:-87});
var ptTwoID
it('should preform an UPSERT since were not specifying ID', function(done) {
var pt5 = new app.loopback.GeoPoint({lat: lat5, lng: lng5});
json( 'put','/api/Points/' )
.send({
location: pt5,
})
.end(function(err, res) {
var updatedPoint = res.body;
ptTwoID = updatedPoint.id;
done();
})
});
it('should return a list of all points', function(done) {
json('get', '/api/Points')
.expect(200)
.end(function(err, res) {
var points = res.body;
assert(Array.isArray(points));
assert.equal(points.length, 2, 'array length incorrect');
done();
});
});
//originally I didnt have the delete tests wrapped in a describe I added it to see if it changed anything
describe('DELETE has its own suite', function() {
//Delete the point
it('should DELETE the Point created by our POST test', function(done){
json('del', '/api/Points/' + ptOneID)
.end(function(err, res) {
assert.equal(res.status, 204, 'delete failed');
done();
})
});
it('should DELETE the Point we upserted',function(done){
json('del', '/api/Points'+ ptTwoID)
.end(function(err, res) {
assert.equal(res.status, 204, 'upsert delete failed');
done();
});
});
it('testing to see if posted point is still there', function(done){
json('get', '/api/Points/' + ptOneID)
.end(function(err, res) {
assert.equal(res.status, 404, 'posted point not deleted unsure emoticon');
done();
})
});
//this part was originally wrapped in an after hook, and worked perfectly until I added the describe for custom endpoints
it('testing to see if upserted point is still there', function(done){
json('get', '/api/Points/' + ptTwoID)
.end(function(err, res) {
assert.equal(res.status, 404, 'upserted pt not deleted unsure emoticon');
done();
})
});
});
});
//This suite tests the beforeSave behavior
describe('Testing Custom endpt', function() {
blah blah blh
});
One last interesting thing: When I try to do the upsert delete, the delete returns a 404, meaning not found, however the get returns a 200 status meaning it was successfully found. Please please let me know what is going on here.

Resources