Skip to content

Commit

Permalink
make this.session an accessor and add a lot of tests
Browse files Browse the repository at this point in the history
  • Loading branch information
jonathanong committed Nov 21, 2013
1 parent 48582d2 commit 1a3a042
Show file tree
Hide file tree
Showing 4 changed files with 309 additions and 28 deletions.
11 changes: 11 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
test:
@NODE_ENV=test ./node_modules/.bin/mocha \
--require should \
--harmony-generators \
--reporter spec \
--bail

clean:
@rm -rf node_modules

.PHONY: test clean
59 changes: 32 additions & 27 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,22 +30,43 @@ module.exports = function(opts){
debug('session options %j', opts);

return function *(next){
var json = this.cookies.get(key, opts);
var sess, json;

this.sessionOptions = opts;
this.sessionKey = key;

if (json) {
debug('parse %s', json);
var sess = this.session = new Session(this, JSON.parse(json));
} else {
debug('new session');
var sess = this.session = new Session(this);
}
this.__defineGetter__('session', function(){
// already retrieved
if (sess) return sess;
// unset
if (false === sess) return null;

json = this.cookies.get(key, opts);

if (json) {
debug('parse %s', json);
sess = new Session(this, JSON.parse(json));
} else {
debug('new session');
sess = new Session(this);
}

return sess;
});

this.__defineSetter__('session', function(val){
if (null == val) return sess = false;
if ('object' == typeof val) return sess = new Session(this, val);
throw new Error('this.session can only be set as null or an object.');
});

yield next;

// not accessed
if (undefined === sess) return;

// remove
if (!this.session) return sess.remove();
if (false === sess) return this.cookies.set(key, '', opts);

// save
if (sess.changed(json)) sess.save();
Expand Down Expand Up @@ -81,7 +102,7 @@ Session.prototype.toJSON = function(){
var obj = {};

Object.keys(this).forEach(function(key){
if ('isNew' == key[0]) return;
if ('isNew' == key) return;
if ('_' == key[0]) return;
obj[key] = self[key];
});
Expand Down Expand Up @@ -119,20 +140,4 @@ Session.prototype.save = function(){

debug('save %s', json);
ctx.cookies.set(key, json, opts);
};

/**
* Remove the session.
*
* @api private
*/

Session.prototype.remove = function(){
var ctx = this._ctx;
var opts = ctx.sessionOptions;
var key = ctx.sessionKey;

debug('remove');
opts.expires = new Date(0);
ctx.cookies.set(key, '', opts);
};
};
8 changes: 7 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,17 @@
"index.js"
],
"devDependencies": {
"koa": "koajs/koa"
"koa": "koajs/koa",
"mocha": "*",
"should": "*",
"supertest": "*"
},
"license": "MIT",
"dependencies": {
"debug": "*",
"uid2": "0.0.3"
},
"scripts": {
"test": "make test"
}
}
259 changes: 259 additions & 0 deletions test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,259 @@
var koa = require('koa');
var request = require('supertest');
var session = require('./');

describe('Koa Session', function(){
var cookie;

describe('when options.signed = true', function(){
describe('when app.keys are set', function(){
it('should work', function(done){
var app = koa();
app.keys = ['a', 'b'];
app.use(session());
app.use(function *(){
this.body = this.session.sid;
});

request(app.listen())
.get('/')
.expect(200, done);
})
})

describe('when app.keys are not set', function(){
it('should throw', function(done){
var app = koa();
app.use(session());
app.use(function *(){
this.session.sid;
});

request(app.listen())
.get('/')
.expect(500, done);
})
})
})

describe('when options.signed = false', function(){
describe('when app.keys are not set', function(){
it('should work', function(done){
var app = koa();
app.use(session({
signed: false
}));
app.use(function *(){
this.body = this.session.sid;
});

request(app.listen())
.get('/')
.expect(200, done);
})
})
})

describe('this.sessionOptions', function(){
it('should be populated', function(done){
var app = App();
app.use(function *(){
this.body = this.sessionOptions;
});
request(app.listen())
.get('/')
.expect('Content-Type', /json/)
.expect(200, done);
})
})

describe('this.sessionKey', function(){
it('should be populated', function(done){
var app = App();
app.use(function *(){
this.body = this.sessionKey;
});
request(app.listen())
.get('/')
.expect(200)
.expect('koa:sess', done);
})
})

describe('new session', function(){
describe('when not accessed', function(){
it('should not Set-Cookie', function(done) {
var app = App();
app.use(function *(){
this.body = 'greetings';
})
request(app.listen())
.get('/')
.expect(200, function(err, res){
if (err) return done(err);
res.header.should.not.have.property('set-cookie');
done();
})
})
})

describe('when accessed', function(done){
it('should Set-Cookie', function(done){
var app = App();
app.use(function *(){
this.session.message = 'hello';
this.body = '';
})
request(app.listen())
.get('/')
.expect('Set-Cookie', /koa:sess/)
.expect('Set-Cookie', /hello/)
.expect(200, function(err, res){
if (err) return done(err);
cookie = res.header['set-cookie'].join(';');
done();
})
})

it('should set .sid', function(done){
var app = App();
app.use(function *(){
this.body = this.session.sid;
})
request(app.listen())
.get('/')
.expect('Set-Cookie', /sid/)
.expect(200, done)
})

it('should not set .isNew', function(done){
var app = App();
app.use(function *(){
this.body = this.session.sid;
})
request(app.listen())
.get('/')
.expect('Set-Cookie', /koa:sess/)
.expect(200, function(err, res){
if (err) return done(err);
res.header['set-cookie'].should.not.match(/isNew/);
done();
})
})
})
})

describe('saved session', function(){
describe('when not accessed', function(){
it('should not Set-Cookie', function(done){
var app = App();
app.use(function *(){
this.body = 'aklsdjflasdjf';
})
request(app.listen())
.get('/')
.set('Cookie', cookie)
.expect(200, function(err, res){
if (err) return done(err);
res.header.should.not.have.property('set-cookie');
done();
})
})
})

describe('when accessed but not changed', function(){
it('should be the same session', function(done){
var app = App();
app.use(function *(){
this.session.message.should.equal('hello');
this.body = 'aklsdjflasdjf';
})
request(app.listen())
.get('/')
.set('Cookie', cookie)
.expect(200, done);
})

it('should not Set-Cookie', function(done){
var app = App();
app.use(function *(){
this.session.message.should.equal('hello');
this.body = 'aklsdjflasdjf';
})
request(app.listen())
.get('/')
.set('Cookie', cookie)
.expect(200, function(err, res){
if (err) return done(err);
res.header.should.not.have.property('set-cookie');
done();
})
})
})

describe('when accessed and changed', function(){
it('should Set-Cookie', function(done){
var app = App();
app.use(function *(){
this.session.money = '$$$';
this.body = 'aklsdjflasdjf';
})
request(app.listen())
.get('/')
.set('Cookie', cookie)
.expect('Set-Cookie', /money/)
.expect(200, done);
})
})
})

describe('when session = ', function(){
describe('null', function(){
it('should expire the session', function(done){
var app = App();
app.use(function *(){
this.session = null;
this.body = 'asdf';
})
request(app.listen())
.get('/')
.expect('Set-Cookie', /expire/)
.expect(200, done);
})
})

describe('{}', function(){
it('should create a session', function(done){
var app = App();
app.use(function *(){
this.session = { message: 'hello' };
this.body = 'asdf';
})
request(app.listen())
.get('/')
.expect('Set-Cookie', /sid/)
.expect('Set-Cookie', /hello/)
.expect(200, done);
})
})

describe('anything else', function(){
it('should throw', function(done){
var app = App();
app.use(function *(){
this.session = 'asdf'
})
request(app.listen())
.get('/')
.expect(500, done);
})
})
})
})

function App(options) {
var app = koa();
app.keys = ['a', 'b'];
app.use(session(options));
return app;
}

0 comments on commit 1a3a042

Please sign in to comment.