3

I want to test a web app server side CRUD logics. But only login user can visit the web app.

if (res.locals.user){
  //CRUD functions here
} 

I know how to use Mocha and Chai to test these CRUD functions without the login check there, but how can I mock login user to test them? Use cookie?

Russj
  • 649
  • 10
  • 20

2 Answers2

2

I generally do something along the lines of:

var request = require('supertest');

describe('My tests', function(){

    var agent = request.agent(app);

    //before all the tests run, log in
    before(function(done){
        request(app)
        .post('/login')
        .send({
            username: 'a@b.com',
            password: 'password123'
        })
        .end(function (err, res) {
            if (err) { return done(err); }

            agent.saveCookies(res);

            done();
        });

    });

    it('Does something when logged in', function (done){
        var req = request(app).get('/account/something')
        .expect(200);

        //attach the logged in cookies to the agent
        agent.attachCookies(req);

        req.end(done);

        //assertions here
    });
})

Fire off a login request first, save the cookies to the agent

Then, in requests I want to use the authenticated request. attach the cookies to it.

app is the instance of the Express app

Alex
  • 34,123
  • 47
  • 189
  • 315
2

@Russj, assuming that:

  • you're using passport-local as your passport authentication strategy
  • you're using supertest to simulate your api calls
  • you already have an file that exports your Express app

Then this is how I would go about testing authenticated end-points:

var request = require('supertest'),
    agent = request.agent();
    mongoose = require('mongoose'),
    // this examples assumes /path/to/your/app exports your Express app
    app = require('/path/to/your/app'), 
    // replace this with the model you use for authentication
    UserModel = mongoose.model('UserModel');
    // this example assumes your user model looks something like the following:
    // 
    //     UserModel = new mongoose.Schema({
    //       username:  String,
    //       password: String
    //     });

describe('testing authenticated end-point', function () {
    var UserModel, testuser;

    before(function (done) {

        // this is just to ensure we have a user to log in for your tests
        UserModel.findOneAndUpdate({ 
            { username: 'testuser' }, 
            { username: 'testuser', password: 'testpassword' }, 
            { upsert: true }, // this will create the user if it doesn't already exist
            function(err, doc) {
                testuser = doc
            }
        });

        // I assume /simulate-login is not an existing route in your app
        app.get('/simulate-login', function(req, res) {
            req.login(testuser); // .login is exposed in req by passport
        });

        // now we simulate login of our testuser and save  the cookies
        request(app)
            .get('/simulate-login')
            .end(function (err, res) {
                    if (err) { return done(err); }

                    // save cookies
                    agent.saveCookies(res);

                    done();
            });
    });

    // clean up after ourselves
    after(function () {
        UserModel.remove({ username: 'testuser' }).exec();
    });

    // now we can test an authenticated end-point as long as we attach the saved cookies
    it('should do whatever...', function (done) {
        var req;

        req = request(app)
            .get('/path/to/route/to/test')
            .expect(200);

        // attach cookies
        agent.attachCookies(req);

        // do your reqeust
        req.end(done);          
    });

});
JME
  • 3,452
  • 12
  • 22