Is there any way to directly access the req
object in supertest
, while/after the request is being tested? I want to test my passport
strategies, so I want to check req.user
, req.session
, and perhaps others. I know I can test page redirects or flash, as those are what my strategies do, but it seems useful to see if there is a user on the req
object, as well. If I do this, I can also check how many users there are at any one time.
I will sign users up with the “local-signup” strategy, which is defined thusly:
'use strict'; // get passport & mongoose var passport = require('passport'); var LocalStrategy = require('passport-local').Strategy; var UserModel = require('mongoose').model('User'); module.exports = function() { // signup function passport.use('local-signup', new LocalStrategy({ passReqToCallback: true // pass the entire request to the callback }, function(req, username, password, done) { process.nextTick(function() { // find a user with the same username UserModel.findOne({username: username}, function(err, user) { // if there is an error, log it then return it if(err) { console.log("Error finding a user in the database: " + err); return done(err); } // if a user was already found if(user) { return done(null, false, "User already exists"); } // if we get this far, create a new user from the request body var newUser = new UserModel(req.body); // save it and sign it in newUser.save(function(err) { if(err) { console.log("Error during signup: " + err); return done(err); } return done(null, newUser); }); }); }); } )); };
One way I use this strategy is like this:
My “local” strategy is defined like this:
'use strict'; var passport = require('passport'); var LocalStrategy = require('passport-local').Strategy; var UserModel = require('mongoose').model('User'); module.exports = function() { // create our local passport strategy & use it passport.use(new LocalStrategy({ // use the default names for the username & password fields usernameField: 'username', passwordField: 'password' }, // main strategy function function(username, password, done) { // find user with given username UserModel.findOne({ username: username }, // with this username, do this function(err, user) { // if there's an error, log it then pass it along if(err) { console.log("Error during login: " + err); return done(err); } // if the username and/or password is incorrect, return an error // along with a message if(!user || !user.authenticate(password)) { return done(null, false, { message: 'Invalid username and/or password' }); } // if everything is correct, return the user document from the database return done(null, user); }); } )); };
I use both strategies like this, for example:
app.route(pageName).post(function(req, res, next) { passport.authenticate(strategyName, function(err, user, info) { if(err || !user) { res.status(401).send(info); } else { req.login(user, function(err) { if(err) { res.status(400).send(err); } else { res.send(null); } }); } })(req, res, next); });
I tried
request = require('supertest'); this.authServer = require('../my-server'); request(this.authServer) .put('/signup') .set('Content-Type', 'application/json') .set('Host', 'konneka.org') .send(this.fullUser) .end(function(req, res, done) { console.log(res); });
The res
object I logged, inside the end()
function, which was way too long to show here, has a req
object defined on it, but it seems to only have the objects & functions that were defined before the request was opened. In other words, it does not have req.user
, req.session
, or other objects I want, because they are defined after the request completes and a new request is started. I noticed it has status codes, as well, which are only defined after the request completes, so I must be missing something.
Is there any way to get access to the req
object after the request you are testing is ended? Or am I going about this completely the wrong way?
Answers:
Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.
Method 1
You cannot do what you want using supertest
.
Not sure if this helps but I’ll add a little context to clarify the answer:
supertest
is a wrapper on top of superagent
(client side) with some basic hooks into express
to start up the HTTP listener. Under the hood, it really is not any different from starting up your express app, waiting for it to listen on a port, making an HTTP request to that port, and parsing the result. In fact, that is exactly what it does.
So essentially supertest
only has access to what ever your client would have access to (a browser or some API client). In other words, if it isnt in the HTTP response body, you wont have access to it. req.user
and req.sesssion
are server side state variables that are (most likely) not in the response (unless you are doing something strange).
If you want to test in exactly the way you describe, you will have to use some alternative strategy of testing, not supertest
.
Method 2
I found this question when I thought I wanted to do this, and for me it worked well to check the status of the user created by the request instead of verifying the content of the req object. You do have access to the full database where I assume you users somehow ends up.
All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0