Are the req and res objects somehow accessible globally in NodeExpress? - node.js

req.session.username = user.username;
I'm using supertest to test route handling. In my log in handling code I have the following if a user logs in successfully -
req.session.username = user.username;
But in the supertest call back function I don't have access to the req object.
request(app)
.post('/login')
.send({username: 'dummy_username', password: 'valid_password'})
.end(function(err, res){
if (err) { return done(err); }
expect(err).toBe(null);
expect(res.status).toEqual(200);
done();
});
I would like to add in something like expect(req.session.username).toBe('dummy_username') but obviously I can't I do this when req is not available to me. So is there a way of referencing the req object?

Supertest is for testing the responses only, since testing the request (and the server-side manipulations thereof) would be testing implementation details instead of behavior. supertest isn't the right tool for this job. You can write pure unit tests for some of your server side functions, OR you can have the /login route include the user's information in the response body (which is typical) and have supertest verify that information matches what was in the request.

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!

How can I use nock.js to mock node-webshot requests?

What is proper way to mock requests sent by node Webshot during a test using nock.js?
I tried following code to capture mocked response of http://example.com/foo.html as foo.png but the mock doesn't seem to work.
const nock = require("nock");
const webshot = require("webshot");
describe("mock webshot request", function(){
this.timeout(20000);
beforeEach(function(){
nock("http://example.com").persist().get("/foo.html").reply(200, "<h1>Foo</h1>");
});
afterEach(function () {
nock.cleanAll();
});
it("captures mocked response", function(done){
webshot("http://example.com/foo.html", "foo.png",function(err) {
nock.isDone();
if(!err) done();
});
});
});
Edit:
The solution was to pass mocked response body to Webshot rather than url:
webshot("<h1>Foo</h1>", ...
Nock expects the http request to happen in the same process.
Note: node-webshot is a wrapper for PhantonJS which run in another process.
In your case Nock is setup in one process, but the http request happens in another process. So you cannot mock http request done by node-webshot like the way your are currently doing.
What you need is support for mocking http request built into node-webshot i.e you will have to add this feature to node-webshot if it doesn't have it.

expect (js) not working inside superagent (js)

I'm trying to do TDD for the Rest APIs that I've been creating. New to NodeJS.
I've created a Rest API, and on the response I want to perform all the expect checks. To make an HTTP request I'm using SuperagentJS (also tried RequestJS).
Here is how my code looks like (Snippet only, not whole code)
var expect = require("chai").expect;
var request = require("superagent");
describe("Creation of New Entity", function(){
it("Create a New Entity", function(){
request
.get("http://localhost")
.end(function(err, httpResponse){
expect("1234").to.have.length(3);//equals(500);
expect(200).to.equals(200);
});
});
});
No matter what I try, mocha always gives successful result. (All test cases passed)
Please tell what I'm missing here. What should I do to implement test cases on httpRespnse. I'm sure that request is working fine, because whenever I use console.log(httpResponse.text), it is returning the default apache home page.
All networking in node.js is asynchronous, therefore you must use the mocha asynchronous flavor of it("Create a New Entity", function(done) { and call the done callback when your test is done.
var expect = require("chai").expect;
var request = require("superagent");
describe("Creation of New Entity", function(){
it("Create a New Entity", function(done){
request
.get("http://localhost")
.end(function(err, httpResponse){
expect(err).not.to.exist();
expect("1234").to.have.length(3);//equals(500);
expect(200).to.equals(200);
done()
});
});
});

Node.js - Unit Testing Middleware

I have an api with a middleware function which I use to filter incoming requests. The functions checks the present of a token in the header, then makes two calls to the database, one to check the token and one to get some information and pass it on to the request object, if the 1st call was successful.
I am struggling to understand how to unit test this functions, by mocking up the request object and also the database calls.
middleware.js
exports.checkToken = function (req, res, next) {
if (!req.get('token')) {
return res.status(400).json('Bad request');
}
var token = req.get('token'); //get token from the header
User.findOne({'token': token}, function(err, user) {
// skipped error checking or no user found
Account.findOne({'_id': user.account}, function(err, account) {
// skipped error checking or no account found
req.somevalue = account;
return next();
});
});
};
Currently I am using mocha, chai and sinon and was thinking of the following:
mock User.findOne and Account.findOne using sinon.stub()
not really sure what to do about the req, res and next objects. How to emulate these?
I think the best choice is to use supertest.
https://www.npmjs.com/package/supertest
This package allow to run tests that emulate the full request cicle on the application.

HMAC Authentication with Supertest

I need to intercept the supertest request to sign my requests as our endpoints all require to be signed.
We follow a similar HMAC Signing process as AWS, I can generate the signature fine. But I see no easy way to intercept the request to iterate through the http request headers etc...
Ideally I thought I could do:
it("return 401 if auth header is signed wrong", function (done) {
api
.post('/v1/users/sessions')
.use(function(request, response){
hmac.signRequest(request, wrongSecret, wrongAccess);
})
.expect(401)
.end(function (err, res) {
if (err) return done(err);
done();
});
On the Super-Agent project there appears to be .use(fn) method. Which has the req,res passed through as params to the callback.
But that seems to not apply to the supertest agent.
Am I missing something or is there another simple way to do this?

Resources