Testing NodeJs with Mocha/Sinon - Sails - node.js

I'm relatively new to nodejs and sailsjs framework, and I really enjoy write code with it, but coming from a PHP background I found testing nodeJs a bit weird.
I'm trying to test with mocha and sinon the method login of my AuthService, but being not expert I would need an example on how do you achieve a successful test for it , unfortunately documentation online is still a bit poor an example will be a lots useful thanks!
login: function(username,password,callback) {
User.findOneByUsername(username, function(err,user){
// If has some error
if (err) { return callback(err) }
// if the user is not found with that username
if (!user) { return callback(err,false); }
// if is found we match the password
bcrypt.compare(password, user.password, function (err, res) {
if (!res || err) return callback(err,false);
return callback(err,true,user);
});
});
}
If you can make light on this will be really appreciated

Check we.js example for how to setup you tests:
link: https://github.com/wejs/we-example/tree/master/test ( with only "headless browser" tests now )
For integration and unit tests with supertest check: https://github.com/wejs/we/tree/emberjsDev/tests

Related

Maintaining session while testing using SuperTest

I am looking to use supertest to test API requests and responses. Following is what I have tried so far.
route.test.js
const testUtils = require('./setupTestUtils');
let authenticateUser = request.agent(app);
before(function(done){
testUtils.login(authenticateUser, userCredentials).then((res) => {
expect(res.statusCode).to.equal(200);
done();
}, (err) => {
console.log(err);
done(err);
});
});
setupTestUtils.js
function login (rest, testUserLogin) {
let defer = Q.defer();
rest.post('/login')
.send(testUserLogin)
.expect(200)
.end(function () {
rest.get('/loggedin')
.expect((res) => {
if (err) {
console.log('ERROR: ' + JSON.stringify(err));
defer.reject(err);
} else {
defer.resolve(res);
}
})
.end();
});
return defer.promise;
}
In my app.js, I use passport to authenticate. After authentication, I use the session.regenerate function to regenerate the session ID to avoid session fixation.
The initial post request to login passes without any failure. However, the subsequent GET request 'loggedIn' fails. This function internally uses the req.isAuthenticated() function from passport. This always returns false.
On investigation, I found that the session ID between the regenerated session and the request object (for req.isAuthenticated()) is different.
From my search, I understand that the cookies should be maintained automatically by the use of 'agent' from supertest. However that doesnt seem to be the case for me. I have also tried maintaining the cookies from the initial response. That doesnt seem to work for me either. " res.headers['set-cookie'] " comes in as undefined (not sure why that is happening either).
Can someone please help me understand what I am missing here.?
Am using versions - Supertest #v6.0.1 and passport #v0.4.1
I found the solution to my issue in an old github issue raised on supertest's page. Linking it here for reference.
Essentially, the supertest runs express in insecure port and I had configured my session otherwise. Ideally, we would have to check the environment before setting this variable to false - as represented here.
Hope this saves someone the time I spent!

React frontend doesn't receive return from nodejs backend in Reactjs + Nodejs App

My backend login process is running on a Nodejs 12.16.1. The code is following:
router.post("/elogin", async (req, res) => {
try {
if (!req.body.userName || !req.body.password) throw new Error("No match"); //<<==this line causes error and jump to catch
let emp = await Employee.findOne({where: {username, password}});
if (!emp) throw new Error("No match!");
return res.status(200).send(_.pick(emp, ['id', 'cell', 'cell_country', 'name']))
} catch(err) {
return res.status(400).send("Hi Not working right now"); //<<===this return stuck and never come out.
}
});
In debug the code stuck at drainQueues in Bluebird which is a promise library according to online info. The execution never ends and stuck here. This is a normal return and I don't see how it shall be stuck.
The front end is React and Fetch. The action type does not matter. The get is stuck as well.
You try to use postman to see if it returns. If there is, then there may be a problem with the backend code

testing external api calls in node.js using mocha.js

I'm trying to write tests for my npm module, which takes care of communicating with my backend api. this module will sit inside a cordova android app, and will take care of any api calls. the issue that i'm having seems to be an understanding of mocha, but i've had a good look around the internet and can't find a solution so i turn to the masses. As an example, i have a function like
test: function() {
request.get({
url: defaultHost,
headers: {
}
}, function(err, httpResponse, body) {
if(err) {
return err;
} else {
console.log(body);
return body;
}
});
}
this works will. i'm now trying to create the test for it in mocha. the problem that i'm getting is that i have no idea how to get the return function from the .get call into the mocha test. the api returns json, so i know that i'm going to have to be doing an is equal comparison, but at the moment i can't even get it to print the results. i think the problem with is that with my other mocha tests that i can get working, they all have an argument that you pass in where as this doesn't. my current code for the test looks like this.
describe('#test', function() {
it('tests api reachability;', function() {
var test = new test();
});
});
if someone can explain what is required afterwards or even just point me in the right direction on google, that would be awesome. i'm normally pretty good at the google, but failing to find direction on this one.
I think nock will solve this issue. Let's assume you sending get request to some resource (http://domain.com/resource.json) and the tests would be like this:
var nock = require('nock');
// ...
describe('#test', function() {
beforeEach(function () {
nock('http://domain.com')
.get('resource.json')
.reply(200, {
message: 'some message'
});
});
it('tests api reachability;', function() {
var test = new test();
});
});

how to authenticate valid user in nodejs and mongo DB

I have a problem in validating user name and password in nodejs and mongodb . Below is the code what i tried. Password validation not working. what i am doing wrong here...
server.get('/login', function(req, res)
{
var status=""
user.findOne({name: req.query.username}, function(err, users)
{
if( err || !users)
{
console.log("No users found");
status="failed"
}
else
{
if(password==req.query.password)
{
status="success"
}
else
{
status="failed"
}
}
});
res.send(status);
});
Node.js runs on an asynchronous event loop, which means that your code won't necessary run the way you may always think it will (synchronously). To overcome this issue, there are a couple options: callbacks, or promises. Promises are generally the preferred route, and there are a couple libraries which I suggest: bluebird (is awesome) or async (which I haven't used a lot, but many prefer it).
If you'd like to work without promises for right now, you could fix your issue this way:
user.findOne({name: req.query.username}, function(err, users) {
if( !err && users && password === req.query.password ) {
res.send({ status: 'success' });
}
else { res.send({ status: 'failed' }); }
});
Again, the reason your code is not working is because the event loop reaches your res.send(status) before the database query has been resolved. My suggestion should work fine for you, but as your processes become more complex, I would look into promises to resolve any further async issues.

Testing an API wrapper

I'm writing an API wrapper for an external API, to be used in our application.
I have adopted a test-driven approach for this project but since I have little to no experience with writing API wrappers, I'm not sure if I'm on the right track.
I understand that I should not be testing the external API, nor should I be hitting the network in my tests. I'm using Nock to mock my requests to the API.
However, I'm not sure I'm doing this correctly.
I made some requests to the API using curl and put the (XML) response in a file, for example: /test/fixtures/authentication/error.js:
module.exports = "<error>Authorization credentials failed.</error>"
Since I don't want to hit the network, but want to make sure my wrapper parses the XML to JSON, I figured I needed sample data.
My test looks like this:
describe("with an invalid application key", function() {
var cl, api;
before(function(done) {
api = nock(baseApi)
.get('/v1/auth/authenticate')
.reply(200, fixtures.authentication.error);
done();
});
after(function(done) {
nock.cleanAll();
done();
});
it("returns an error", function(done) {
cl = new APIClient(auth.auth_user, auth.auth_pass, "abcd1234");
cl.authenticate(function(err, res) {
should.exist(err);
err.should.match(/Authorization credentials failed./);
should.not.exist(res);
api.isDone().should.be.true;
done();
});
});
});
With my tested code looking like this:
APIClient.prototype.authenticate = function(callback) {
var self = this;
request({
uri: this.httpUri + '/auth/authenticate',
method: 'GET',
headers: {
auth_user: this.user,
auth_pass: this.pass,
auth_appkey: this.appkey
}
}, function(err, res, body) {
if (err) {
return callback('Could not connect to the API endpoint.');
}
self.parser.parseXML(body, function(err, result) {
if (err) { return callback(err); }
if (result.error) { return callback(result.error); }
self.token = result.auth.token[0];
return callback(null, result);
});
});
};
Now, this seems to be working fine for the authentication side of things (I also have a 'success' fixture, which returns the 'success' XML and I check if the returned JSON is actually correct.
However, the API I'm using also has endpoints like:
/data/topicdata/realtime/:reportxhours/:topics/:mediatypes/:pageIndex/:pageSize
I'm not sure how to test all (should I?) possible combinations with URLs like those. I feel like I can hardly put 30 XML responses in my fixtures directory. Also, when mocking responses, I'm afraid to miss out on possible errors, edge cases, etc. the external API might return. Are these valid concerns?
If anyone has any pointers, and/or knows of any open-source and well-tested API wrappers I could take a look at, I'd be very grateful.
I think your concern is very valid and I suggest you to also build tests using Zombie or other simular request-based testing frameworks.

Resources