Ghost/test/unit/api/v3/session_spec.js
Fabien O'Carroll 23154f0739
Refactored session service (#11701)
* Refactored SessionStore to use @tryghost/errors

no-issue

* Updated tests to test exposed API

no-issue

This will make refactoring easier, as we only have the "public" contract to maintain

* Refactored session functionality to SessionService

no-issue

This splits the session logic away from the HTTP responding logic,
which will allows us to decouple session creation/modification from the
API. Eventually this can be used to create sessions based on magiclink
style tokens.

* Instantiated and exported the new SessionService

no-issue

* Refactored session middleware to take session service

no-issue

This removes duplication of code and makes the middleware more explicit
that it's just a wrapper around the session service.

* Updated to use external @tryghost/session-service

no-issue
2020-04-02 16:27:31 +02:00

145 lines
5.4 KiB
JavaScript

const should = require('should');
const sinon = require('sinon');
const models = require('../../../../core/server/models');
const {UnauthorizedError} = require('../../../../core/server/lib/common/errors');
const sessionController = require('../../../../core/server/api/canary/session');
const sessionServiceMiddleware = require('../../../../core/server/services/auth/session').middleware;
describe('v3 Session controller', function () {
before(function () {
models.init();
});
afterEach(function () {
sinon.restore();
});
it('exports an add method', function () {
should.equal(typeof sessionController.add, 'function');
});
it('exports an delete method', function () {
should.equal(typeof sessionController.delete, 'function');
});
describe('#add', function () {
it('throws an UnauthorizedError if the object is missing a username and password', function () {
return sessionController.add({}).then(() => {
should.fail('session.add did not throw');
},(err) => {
should.equal(err instanceof UnauthorizedError, true);
});
});
it('it checks the username and password and throws UnauthorizedError if it fails', function () {
const userCheckStub = sinon.stub(models.User, 'check')
.rejects(new Error());
return sessionController.add({data: {
username: 'freddy@vodafone.com',
password: 'qu33nRul35'
}}).then(() => {
should.fail('session.add did not throw');
},(err) => {
should.equal(err instanceof UnauthorizedError, true);
});
});
it('it returns a function that calls req.brute.reset, sets req.user and calls createSession if the check works', function () {
const fakeReq = {
brute: {
reset: sinon.stub().callsArg(0)
}
};
const fakeRes = {};
const fakeNext = () => {};
const fakeUser = models.User.forge({});
sinon.stub(models.User, 'check')
.resolves(fakeUser);
const createSessionStub = sinon.stub(sessionServiceMiddleware, 'createSession');
return sessionController.add({data: {
username: 'freddy@vodafone.com',
password: 'qu33nRul35'
}}).then((fn) => {
fn(fakeReq, fakeRes, fakeNext);
}).then(function () {
should.equal(fakeReq.brute.reset.callCount, 1);
const createSessionStubCall = createSessionStub.getCall(0);
should.equal(fakeReq.user, fakeUser);
should.equal(createSessionStubCall.args[0], fakeReq);
should.equal(createSessionStubCall.args[1], fakeRes);
should.equal(createSessionStubCall.args[2], fakeNext);
});
});
it('it returns a function that calls req.brute.reset and calls next if reset errors', function () {
const resetError = new Error();
const fakeReq = {
brute: {
reset: sinon.stub().callsArgWith(0, resetError)
}
};
const fakeRes = {};
const fakeNext = sinon.stub();
const fakeUser = models.User.forge({});
sinon.stub(models.User, 'check')
.resolves(fakeUser);
const createSessionStub = sinon.stub(sessionServiceMiddleware, 'createSession');
return sessionController.add({data: {
username: 'freddy@vodafone.com',
password: 'qu33nRul35'
}}).then((fn) => {
fn(fakeReq, fakeRes, fakeNext);
}).then(function () {
should.equal(fakeReq.brute.reset.callCount, 1);
should.equal(fakeNext.callCount, 1);
should.equal(fakeNext.args[0][0], resetError);
});
});
});
describe('#delete', function () {
it('returns a function that calls destroySession', function () {
const fakeReq = {};
const fakeRes = {};
const fakeNext = () => {};
const destroySessionStub = sinon.stub(sessionServiceMiddleware, 'destroySession');
return sessionController.delete().then((fn) => {
fn(fakeReq, fakeRes, fakeNext);
}).then(function () {
const destroySessionStubCall = destroySessionStub.getCall(0);
should.equal(destroySessionStubCall.args[0], fakeReq);
should.equal(destroySessionStubCall.args[1], fakeRes);
should.equal(destroySessionStubCall.args[2], fakeNext);
});
});
});
describe('#get', function () {
it('returns the result of User.findOne', function () {
const findOneReturnVal = new Promise(() => {});
const findOneStub = sinon.stub(models.User, 'findOne')
.returns(findOneReturnVal);
const result = sessionController.read({
options: {
context: {
user: 108
}
}
});
should.equal(result, findOneReturnVal);
should.deepEqual(findOneStub.args[0][0], {
id: 108
});
});
});
});