I'm testing my API with supertest
I want to check that my CSRF token protection works, and then disable it for the other tests.
For this I set NODE_ENV
to test
or not_test
app.js
var csrf = require('csurf');
var app = express();
if (process.env.NODE_ENV !== 'test') {
app.use(csrf({ cookie: true }));
app.use(function(req, res, next) {
res.cookie('XSRF-TOKEN', req.csrfToken());
return next();
});
}
Test CSRF
process.env.NODE_ENV = 'not_test';
var app = require("app.js");
var request = require('supertest')(app);
var testAccount = {
"login": "test",
"pass": "test"
};
describe('CSRF protection', function() {
it('On /login', function(done){
request
.post('/login')
.send(testAccount)
.expect(403, done);
});
});
Test login NODE_ENV is now test
process.env.NODE_ENV = 'test';
var app = require("app.js");
var request = require('supertest').agent(app);
var testAccount = {
"login": "test",
"pass": "test"
};
describe('API Admin roads', function() {
before(function (done) {
request
.post('/login')
.send(testAccount)
.end(done);
});
it('/api/admin/groups/', function(done){
request
.get('/api/admin/groups/')
.expect(200, done);
});
});
The problem is, only the first process.env.NODE_ENV
is taken into account, if I set it to not_test
and then to test
I will still be in not_test
mode.
Tests can be executed in many ways and their execution sequence isn't always the same (e.g. mocha --parallel option).
So, rewriting a shared variable like process.env
and manipulating the require
cache it's not a reliable way to solve this problem. It's an hack - today it works but it will broke easily when you (or your workmates) will change the code tomorrow.
An easier and cleaner way to do that, is to return an init function from your app.js
file and get the app
object as the output of this function call. In this way you can pass to it an explicit option to enable/disable the csrf token protection:
//app.js
module.exports = function appSetup(opts) {
var csrf = require('csurf');
var app = express();
if (opts.csrfEnabled) {
app.use(csrf({ cookie: true }));
app.use(function(req, res, next) {
res.cookie('XSRF-TOKEN', req.csrfToken());
return next();
});
}
// more express handlers ...
// app.use(...)
return app;
}
Then disable it in your tests without csrf:
var app = require("app.js");
var request = require('supertest')(app({csrfEnabled: false}));
And enable it where you need it:
var app = require("app.js");
var request = require('supertest')(app({csrfEnabled: true}));
Obviously you need to update you app start code, e.g. bin/start.js
:
var app = require('../app')({csrfEnabled: true});
var server = http.createServer(app);
// and so on...
Advantages of this approach:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With