Subscribers: Migrations for new table + perms

refs #6301

- add new subscribers table with tests
- add permissions for subscribers endpoint
- minor improvments to test code
This commit is contained in:
Hannah Wolfe 2016-04-19 15:12:18 +01:00
parent 85c1e1407f
commit c41c09ef97
11 changed files with 350 additions and 106 deletions

View File

@ -0,0 +1,16 @@
var commands = require('../../schema').commands,
db = require('../../db'),
table = 'subscribers',
message = 'Creating table: ' + table;
module.exports = function addSubscribersTable(logger) {
return db.knex.schema.hasTable(table).then(function (exists) {
if (!exists) {
logger.info(message);
return commands.createTable(table);
} else {
logger.warn(message);
}
});
};

View File

@ -5,7 +5,8 @@ module.exports = [
require('./02-add-visibility-column-to-key-tables'),
// Add mobiledoc column to posts
require('./03-add-mobiledoc-column-to-posts'),
// Add social media columns to isers
require('./04-add-social-media-columns-to-users')
// Add social media columns to users
require('./04-add-social-media-columns-to-users'),
// Add subscribers table
require('./05-add-subscribers-table')
];

View File

@ -1,12 +1,13 @@
// Update the permissions & permissions_roles tables to get the new entries
var utils = require('../utils');
// Update the permissions & permissions_roles tables to add entries for clients
var utils = require('../utils'),
resource = 'client';
function getClientPermissions() {
return utils.findModelFixtures('Permission', {object_type: 'client'});
function getPermissions() {
return utils.findModelFixtures('Permission', {object_type: resource});
}
function getClientRelations() {
return utils.findPermissionRelationsForObject('client');
function getRelations() {
return utils.findPermissionRelationsForObject(resource);
}
function printResult(logger, result, message) {
@ -18,13 +19,13 @@ function printResult(logger, result, message) {
}
module.exports = function addClientPermissions(options, logger) {
var modelToAdd = getClientPermissions(),
relationToAdd = getClientRelations();
var modelToAdd = getPermissions(),
relationToAdd = getRelations();
return utils.addFixturesForModel(modelToAdd).then(function (result) {
printResult(logger, result, 'Adding permissions fixtures for clients');
printResult(logger, result, 'Adding permissions fixtures for ' + resource + 's');
return utils.addFixturesForRelation(relationToAdd);
}).then(function (result) {
printResult(logger, result, 'Adding permissions_roles fixtures for clients');
printResult(logger, result, 'Adding permissions_roles fixtures for ' + resource + 's');
});
};

View File

@ -0,0 +1,31 @@
// Update the permissions & permissions_roles tables to add entries for subscribers
var utils = require('../utils'),
resource = 'subscriber';
function getPermissions() {
return utils.findModelFixtures('Permission', {object_type: resource});
}
function getRelations() {
return utils.findPermissionRelationsForObject(resource);
}
function printResult(logger, result, message) {
if (result.done === result.expected) {
logger.info(message);
} else {
logger.warn('(' + result.done + '/' + result.expected + ') ' + message);
}
}
module.exports = function addSubscriberPermissions(options, logger) {
var modelToAdd = getPermissions(),
relationToAdd = getRelations();
return utils.addFixturesForModel(modelToAdd).then(function (result) {
printResult(logger, result, 'Adding permissions fixtures for ' + resource + 's');
return utils.addFixturesForRelation(relationToAdd);
}).then(function (result) {
printResult(logger, result, 'Adding permissions_roles fixtures for ' + resource + 's');
});
};

View File

@ -4,5 +4,7 @@ module.exports = [
// add ghost-scheduler client
require('./02-add-ghost-scheduler-client'),
// add client permissions and permission_role relations
require('./03-add-client-permissions')
require('./03-add-client-permissions'),
// add subscriber permissions and permission_role relations
require('./04-add-subscriber-permissions')
];

View File

@ -249,6 +249,31 @@
"name": "Delete clients",
"action_type": "destroy",
"object_type": "client"
},
{
"name": "Browse subscribers",
"action_type": "browse",
"object_type": "subscriber"
},
{
"name": "Read subscribers",
"action_type": "read",
"object_type": "subscriber"
},
{
"name": "Edit subscribers",
"action_type": "edit",
"object_type": "subscriber"
},
{
"name": "Add subscribers",
"action_type": "add",
"object_type": "subscriber"
},
{
"name": "Delete subscribers",
"action_type": "destroy",
"object_type": "subscriber"
}
]
}
@ -277,7 +302,8 @@
"theme": "all",
"user": "all",
"role": "all",
"client": "all"
"client": "all",
"subscriber": "all"
},
"Editor": {
"post": "all",
@ -286,7 +312,8 @@
"tag": "all",
"user": "all",
"role": "all",
"client": "all"
"client": "all",
"subscriber": ["add"]
},
"Author": {
"post": ["browse", "read", "add"],
@ -295,7 +322,8 @@
"tag": ["browse", "read", "add"],
"user": ["browse", "read"],
"role": ["browse"],
"client": "all"
"client": "all",
"subscriber": ["add"]
}
}
},

View File

@ -198,5 +198,21 @@ module.exports = {
user_id: {type: 'integer', nullable: false, unsigned: true, references: 'users.id'},
client_id: {type: 'integer', nullable: false, unsigned: true, references: 'clients.id'},
expires: {type: 'bigInteger', nullable: false}
},
subscribers: {
id: {type: 'increments', nullable: false, primary: true},
uuid: {type: 'string', maxlength: 36, nullable: false, validations: {isUUID: true}},
name: {type: 'string', maxlength: 150, nullable: true},
email: {type: 'string', maxlength: 254, nullable: false, unique: true, validations: {isEmail: true}},
status: {type: 'string', maxlength: 150, nullable: false, defaultTo: 'pending', validations: {isIn: [['subscribed', 'pending', 'unsubscribed']]}},
post_id: {type: 'integer', nullable: true, unsigned: true, references: 'posts.id'},
subscribed_url: {type: 'text', maxlength: 2000, nullable: true, validations: {isEmptyOrURL: true}},
subscribed_referrer: {type: 'text', maxlength: 2000, nullable: true, validations: {isEmptyOrURL: true}},
unsubscribed_url: {type: 'text', maxlength: 2000, nullable: true, validations: {isEmptyOrURL: true}},
unsubscribed_at: {type: 'dateTime', nullable: true},
created_at: {type: 'dateTime', nullable: false},
created_by: {type: 'integer', nullable: false},
updated_at: {type: 'dateTime', nullable: true},
updated_by: {type: 'integer', nullable: true}
}
};

View File

@ -135,6 +135,20 @@ describe('Database Migration (special functions)', function () {
permissions[33].should.be.AssignedToRoles(['Administrator', 'Editor', 'Author']);
permissions[34].name.should.eql('Delete clients');
permissions[34].should.be.AssignedToRoles(['Administrator', 'Editor', 'Author']);
console.log(permissions[38]);
// Subscribers
permissions[35].name.should.eql('Browse subscribers');
permissions[35].should.be.AssignedToRoles(['Administrator']);
permissions[36].name.should.eql('Read subscribers');
permissions[36].should.be.AssignedToRoles(['Administrator']);
permissions[37].name.should.eql('Edit subscribers');
permissions[37].should.be.AssignedToRoles(['Administrator']);
permissions[38].name.should.eql('Add subscribers');
permissions[38].should.be.AssignedToRoles(['Administrator', 'Editor', 'Author']);
permissions[39].name.should.eql('Delete subscribers');
permissions[39].should.be.AssignedToRoles(['Administrator']);
});
describe('Populate', function () {
@ -195,7 +209,7 @@ describe('Database Migration (special functions)', function () {
result.roles.at(3).get('name').should.eql('Owner');
// Permissions
result.permissions.length.should.eql(35);
result.permissions.length.should.eql(40);
result.permissions.toJSON().should.be.CompletePermissions();
done();

View File

@ -132,10 +132,12 @@ describe('Fixtures', function () {
});
describe('01-move-jquery-with-alert', function () {
var moveJquery = fixtures004[0];
it('tries to move jQuery to ghost_foot', function (done) {
getObjStub.get.returns('');
fixtures004[0]({}, loggerStub).then(function () {
moveJquery({}, loggerStub).then(function () {
settingsOneStub.calledOnce.should.be.true();
settingsOneStub.calledWith('ghost_foot').should.be.true();
settingsEditStub.calledOnce.should.be.true();
@ -152,7 +154,7 @@ describe('Fixtures', function () {
+ '<script type="text/javascript" src="https://code.jquery.com/jquery-1.11.3.min.js"></script>\n\n'
);
fixtures004[0]({}, loggerStub).then(function () {
moveJquery({}, loggerStub).then(function () {
settingsOneStub.calledOnce.should.be.true();
settingsOneStub.calledWith('ghost_foot').should.be.true();
settingsEditStub.calledOnce.should.be.false();
@ -166,7 +168,7 @@ describe('Fixtures', function () {
it('does not move jQuery to ghost_foot if the setting is missing', function (done) {
settingsOneStub.returns(Promise.resolve());
fixtures004[0]({}, loggerStub).then(function () {
moveJquery({}, loggerStub).then(function () {
settingsOneStub.calledOnce.should.be.true();
settingsOneStub.calledWith('ghost_foot').should.be.true();
settingsEditStub.called.should.be.false();
@ -182,7 +184,7 @@ describe('Fixtures', function () {
configUtils.set({privacy: {useGoogleFonts: false}});
getObjStub.get.returns('');
fixtures004[0]({}, loggerStub).then(function () {
moveJquery({}, loggerStub).then(function () {
settingsOneStub.calledOnce.should.be.true();
settingsOneStub.calledWith('ghost_foot').should.be.true();
settingsEditStub.calledOnce.should.be.true();
@ -196,8 +198,10 @@ describe('Fixtures', function () {
});
describe('02-update-private-setting-type', function () {
var updateSettingType = fixtures004[1];
it('tries to update setting type correctly', function (done) {
fixtures004[1]({}, loggerStub).then(function () {
updateSettingType({}, loggerStub).then(function () {
settingsOneStub.calledOnce.should.be.true();
settingsOneStub.calledWith('isPrivate').should.be.true();
getObjStub.get.calledOnce.should.be.true();
@ -215,7 +219,7 @@ describe('Fixtures', function () {
it('does not try to update setting type if it is already set', function (done) {
getObjStub.get.returns('private');
fixtures004[1]({}, loggerStub).then(function () {
updateSettingType({}, loggerStub).then(function () {
settingsOneStub.calledOnce.should.be.true();
settingsOneStub.calledWith('isPrivate').should.be.true();
getObjStub.get.calledOnce.should.be.true();
@ -233,8 +237,10 @@ describe('Fixtures', function () {
});
describe('03-update-password-setting-type', function () {
var updateSettingType = fixtures004[2];
it('tries to update setting type correctly', function (done) {
fixtures004[2]({}, loggerStub).then(function () {
updateSettingType({}, loggerStub).then(function () {
settingsOneStub.calledOnce.should.be.true();
settingsOneStub.calledWith('password').should.be.true();
settingsEditStub.calledOnce.should.be.true();
@ -250,7 +256,7 @@ describe('Fixtures', function () {
it('does not try to update setting type if it is already set', function (done) {
getObjStub.get.returns('private');
fixtures004[2]({}, loggerStub).then(function () {
updateSettingType({}, loggerStub).then(function () {
settingsOneStub.calledOnce.should.be.true();
settingsOneStub.calledWith('password').should.be.true();
getObjStub.get.calledOnce.should.be.true();
@ -268,8 +274,10 @@ describe('Fixtures', function () {
});
describe('04-update-ghost-admin-client', function () {
var updateClient = fixtures004[3];
it('tries to update client correctly', function (done) {
fixtures004[3]({}, loggerStub).then(function () {
updateClient({}, loggerStub).then(function () {
clientOneStub.calledOnce.should.be.true();
clientOneStub.calledWith({slug: 'ghost-admin'}).should.be.true();
getObjStub.get.calledTwice.should.be.true();
@ -290,7 +298,7 @@ describe('Fixtures', function () {
getObjStub.get.withArgs('secret').returns('abc');
getObjStub.get.withArgs('status').returns('enabled');
fixtures004[3]({}, loggerStub).then(function () {
updateClient({}, loggerStub).then(function () {
clientOneStub.calledOnce.should.be.true();
clientOneStub.calledWith({slug: 'ghost-admin'}).should.be.true();
getObjStub.get.calledTwice.should.be.true();
@ -309,7 +317,7 @@ describe('Fixtures', function () {
getObjStub.get.withArgs('secret').returns('abc');
getObjStub.get.withArgs('status').returns('development');
fixtures004[3]({}, loggerStub).then(function () {
updateClient({}, loggerStub).then(function () {
clientOneStub.calledOnce.should.be.true();
clientOneStub.calledWith({slug: 'ghost-admin'}).should.be.true();
getObjStub.get.calledTwice.should.be.true();
@ -331,7 +339,7 @@ describe('Fixtures', function () {
getObjStub.get.withArgs('secret').returns('not_available');
getObjStub.get.withArgs('status').returns('enabled');
fixtures004[3]({}, loggerStub).then(function () {
updateClient({}, loggerStub).then(function () {
clientOneStub.calledOnce.should.be.true();
clientOneStub.calledWith({slug: 'ghost-admin'}).should.be.true();
getObjStub.get.calledOnce.should.be.true();
@ -350,11 +358,13 @@ describe('Fixtures', function () {
});
describe('05-add-ghost-frontend-client', function () {
var addClient = fixtures004[4];
it('tries to add client correctly', function (done) {
var clientAddStub = sandbox.stub(models.Client, 'add').returns(Promise.resolve());
clientOneStub.returns(Promise.resolve());
fixtures004[4]({}, loggerStub).then(function () {
addClient({}, loggerStub).then(function () {
clientOneStub.calledOnce.should.be.true();
clientOneStub.calledWith({slug: 'ghost-frontend'}).should.be.true();
clientAddStub.calledOnce.should.be.true();
@ -369,7 +379,7 @@ describe('Fixtures', function () {
it('does not try to add client if it already exists', function (done) {
var clientAddStub = sandbox.stub(models.Client, 'add').returns(Promise.resolve());
fixtures004[4]({}, loggerStub).then(function () {
addClient({}, loggerStub).then(function () {
clientOneStub.calledOnce.should.be.true();
clientOneStub.calledWith({slug: 'ghost-frontend'}).should.be.true();
clientAddStub.called.should.be.false();
@ -382,7 +392,8 @@ describe('Fixtures', function () {
});
describe('06-clean-broken-tags', function () {
var tagObjStub, tagCollStub, tagAllStub;
var tagObjStub, tagCollStub, tagAllStub,
cleanBrokenTags = fixtures004[5];
beforeEach(function () {
tagObjStub = {
@ -396,7 +407,7 @@ describe('Fixtures', function () {
it('tries to clean broken tags correctly', function (done) {
tagObjStub.get.returns(',hello');
fixtures004[5]({}, loggerStub).then(function () {
cleanBrokenTags({}, loggerStub).then(function () {
tagAllStub.calledOnce.should.be.true();
tagCollStub.each.calledOnce.should.be.true();
tagObjStub.get.calledOnce.should.be.true();
@ -414,7 +425,7 @@ describe('Fixtures', function () {
it('tries can handle tags which end up empty', function (done) {
tagObjStub.get.returns(',');
fixtures004[5]({}, loggerStub).then(function () {
cleanBrokenTags({}, loggerStub).then(function () {
tagAllStub.calledOnce.should.be.true();
tagCollStub.each.calledOnce.should.be.true();
tagObjStub.get.calledOnce.should.be.true();
@ -432,7 +443,7 @@ describe('Fixtures', function () {
it('does not change tags if not necessary', function (done) {
tagObjStub.get.returns('hello');
fixtures004[5]({}, loggerStub).then(function () {
cleanBrokenTags({}, loggerStub).then(function () {
tagAllStub.calledOnce.should.be.true();
tagCollStub.each.calledOnce.should.be.true();
tagObjStub.get.calledOnce.should.be.true();
@ -449,7 +460,7 @@ describe('Fixtures', function () {
it('does nothing if there are no tags', function (done) {
tagAllStub.returns(Promise.resolve());
fixtures004[5]({}, loggerStub).then(function () {
cleanBrokenTags({}, loggerStub).then(function () {
tagAllStub.calledOnce.should.be.true();
tagCollStub.each.called.should.be.false();
tagObjStub.get.called.should.be.false();
@ -464,7 +475,8 @@ describe('Fixtures', function () {
});
describe('07-add-post-tag-order', function () {
var tagOp1Stub, tagOp2Stub, tagObjStub, postObjStub, postCollStub, postAllStub;
var tagOp1Stub, tagOp2Stub, tagObjStub, postObjStub, postCollStub, postAllStub,
addPostTagOrder = fixtures004[6];
beforeEach(function () {
tagOp1Stub = sandbox.stub().returns(Promise.resolve());
@ -489,7 +501,7 @@ describe('Fixtures', function () {
it('calls load on each post', function (done) {
// Fake mapThen behaviour
postCollStub.mapThen.callsArgWith(0, postObjStub).returns([]);
fixtures004[6]({}, loggerStub).then(function () {
addPostTagOrder({}, loggerStub).then(function () {
postAllStub.calledOnce.should.be.true();
postCollStub.mapThen.calledOnce.should.be.true();
postObjStub.load.calledOnce.should.be.true();
@ -508,7 +520,7 @@ describe('Fixtures', function () {
postCollStub.mapThen.returns([]);
postAllStub.returns(Promise.resolve());
fixtures004[6]({}, loggerStub).then(function () {
addPostTagOrder({}, loggerStub).then(function () {
loggerStub.info.calledOnce.should.be.true();
loggerStub.warn.calledOnce.should.be.true();
postAllStub.calledOnce.should.be.true();
@ -527,7 +539,7 @@ describe('Fixtures', function () {
// By returning from mapThen, we can skip doing tag.load in this test
postCollStub.mapThen.returns(postObjStub);
fixtures004[6]({}, loggerStub).then(function () {
addPostTagOrder({}, loggerStub).then(function () {
loggerStub.info.calledThrice.should.be.true();
loggerStub.warn.called.should.be.false();
postAllStub.calledOnce.should.be.true();
@ -551,7 +563,7 @@ describe('Fixtures', function () {
// By returning from mapThen, we can skip doing tag.load in this test
postCollStub.mapThen.returns(postObjStub);
fixtures004[6]({}, loggerStub).then(function () {
addPostTagOrder({}, loggerStub).then(function () {
loggerStub.info.calledThrice.should.be.true();
loggerStub.warn.called.should.be.false();
postAllStub.calledOnce.should.be.true();
@ -574,7 +586,7 @@ describe('Fixtures', function () {
// By returning from mapThen, we can skip doing tag.load in this test
postCollStub.mapThen.returns([postObjStub]);
fixtures004[6]({}, loggerStub).then(function () {
addPostTagOrder({}, loggerStub).then(function () {
loggerStub.info.calledOnce.should.be.true();
loggerStub.warn.calledOnce.should.be.true();
postAllStub.calledOnce.should.be.true();
@ -597,7 +609,7 @@ describe('Fixtures', function () {
// By returning from mapThen, we can skip doing tag.load in this test
postCollStub.mapThen.returns([postObjStub]);
fixtures004[6]({}, loggerStub).then(function () {
addPostTagOrder({}, loggerStub).then(function () {
loggerStub.info.calledThrice.should.be.true();
loggerStub.warn.called.should.be.false();
postAllStub.calledOnce.should.be.true();
@ -625,7 +637,7 @@ describe('Fixtures', function () {
// By returning from mapThen, we can skip doing tag.load in this test
postCollStub.mapThen.returns([postObjStub]);
fixtures004[6]({}, loggerStub).then(function () {
addPostTagOrder({}, loggerStub).then(function () {
loggerStub.info.calledThrice.should.be.true();
loggerStub.warn.called.should.be.false();
postAllStub.calledOnce.should.be.true();
@ -656,7 +668,8 @@ describe('Fixtures', function () {
});
describe('08-add-post-fixture', function () {
var postOneStub, postAddStub;
var postOneStub, postAddStub,
addPostFixture = fixtures004[7];
beforeEach(function () {
postOneStub = sandbox.stub(models.Post, 'findOne').returns(Promise.resolve());
@ -664,7 +677,7 @@ describe('Fixtures', function () {
});
it('tries to add a new post fixture correctly', function (done) {
fixtures004[7]({}, loggerStub).then(function () {
addPostFixture({}, loggerStub).then(function () {
postOneStub.calledOnce.should.be.true();
loggerStub.info.calledOnce.should.be.true();
loggerStub.warn.called.should.be.false();
@ -678,7 +691,7 @@ describe('Fixtures', function () {
it('does not try to add new post fixture if it already exists', function (done) {
postOneStub.returns(Promise.resolve({}));
fixtures004[7]({}, loggerStub).then(function () {
addPostFixture({}, loggerStub).then(function () {
postOneStub.calledOnce.should.be.true();
loggerStub.info.called.should.be.false();
loggerStub.warn.calledOnce.should.be.true();
@ -719,10 +732,11 @@ describe('Fixtures', function () {
sequenceStub.firstCall.args[0][0].should.be.a.Function().with.property('name', 'runVersionTasks');
sequenceStub.secondCall.calledWith(sinon.match.array, sinon.match.object, loggerStub).should.be.true();
sequenceStub.secondCall.args[0].should.be.an.Array().with.lengthOf(3);
sequenceStub.secondCall.args[0].should.be.an.Array().with.lengthOf(4);
sequenceStub.secondCall.args[0][0].should.be.a.Function().with.property('name', 'updateGhostClientsSecrets');
sequenceStub.secondCall.args[0][1].should.be.a.Function().with.property('name', 'addGhostFrontendClient');
sequenceStub.secondCall.args[0][2].should.be.a.Function().with.property('name', 'addClientPermissions');
sequenceStub.secondCall.args[0][3].should.be.a.Function().with.property('name', 'addSubscriberPermissions');
// Reset
sequenceReset();
@ -733,11 +747,12 @@ describe('Fixtures', function () {
describe('Tasks:', function () {
it('should have tasks for 005', function () {
should.exist(fixtures005);
fixtures005.should.be.an.Array().with.lengthOf(3);
fixtures005.should.be.an.Array().with.lengthOf(4);
});
describe('01-update-ghost-client-secrets', function () {
var queryStub, clientForgeStub, clientEditStub;
var queryStub, clientForgeStub, clientEditStub,
updateClient = fixtures005[0];
beforeEach(function () {
queryStub = {
@ -754,7 +769,7 @@ describe('Fixtures', function () {
queryStub.fetch.returns(new Promise.resolve({models: []}));
// Execute
fixtures005[0]({}, loggerStub).then(function () {
updateClient({}, loggerStub).then(function () {
clientForgeStub.calledOnce.should.be.true();
clientEditStub.called.should.be.false();
loggerStub.info.called.should.be.false();
@ -768,7 +783,7 @@ describe('Fixtures', function () {
queryStub.fetch.returns(new Promise.resolve({models: [{id: 1}]}));
// Execute
fixtures005[0]({}, loggerStub).then(function () {
updateClient({}, loggerStub).then(function () {
clientForgeStub.calledOnce.should.be.true();
clientEditStub.called.should.be.true();
loggerStub.info.calledOnce.should.be.true();
@ -779,7 +794,8 @@ describe('Fixtures', function () {
});
describe('02-add-ghost-scheduler-client', function () {
var clientOneStub;
var clientOneStub,
addClient = fixtures005[1];
beforeEach(function () {
clientOneStub = sandbox.stub(models.Client, 'findOne').returns(Promise.resolve({}));
@ -789,7 +805,7 @@ describe('Fixtures', function () {
var clientAddStub = sandbox.stub(models.Client, 'add').returns(Promise.resolve());
clientOneStub.returns(Promise.resolve());
fixtures005[1]({}, loggerStub).then(function () {
addClient({}, loggerStub).then(function () {
clientOneStub.calledOnce.should.be.true();
clientOneStub.calledWith({slug: 'ghost-scheduler'}).should.be.true();
clientAddStub.calledOnce.should.be.true();
@ -804,7 +820,7 @@ describe('Fixtures', function () {
it('does not try to add client if it already exists', function (done) {
var clientAddStub = sandbox.stub(models.Client, 'add').returns(Promise.resolve());
fixtures005[1]({}, loggerStub).then(function () {
addClient({}, loggerStub).then(function () {
clientOneStub.calledOnce.should.be.true();
clientOneStub.calledWith({slug: 'ghost-scheduler'}).should.be.true();
clientAddStub.called.should.be.false();
@ -817,7 +833,8 @@ describe('Fixtures', function () {
});
describe('03-add-client-permissions', function () {
var modelResult, addModelStub, relationResult, addRelationStub;
var modelResult, addModelStub, relationResult, addRelationStub,
addClientPermissions = fixtures005[2];
beforeEach(function () {
modelResult = {expected: 1, done: 1};
@ -831,7 +848,7 @@ describe('Fixtures', function () {
it('should find the correct model & relation to add', function (done) {
// Execute
fixtures005[2]({}, loggerStub).then(function () {
addClientPermissions({}, loggerStub).then(function () {
addModelStub.calledOnce.should.be.true();
addModelStub.calledWith(
fixtureUtils.findModelFixtures('Permission', {object_type: 'client'})
@ -853,7 +870,7 @@ describe('Fixtures', function () {
// Setup
modelResult.expected = 3;
// Execute
fixtures005[2]({}, loggerStub).then(function () {
addClientPermissions({}, loggerStub).then(function () {
addModelStub.calledOnce.should.be.true();
addModelStub.calledWith(
fixtureUtils.findModelFixtures('Permission', {object_type: 'client'})
@ -871,6 +888,63 @@ describe('Fixtures', function () {
});
});
});
describe('04-add-subscriber-permissions', function () {
var modelResult, addModelStub, relationResult, addRelationStub,
addSubscriberPermissions = fixtures005[3];
beforeEach(function () {
modelResult = {expected: 1, done: 1};
addModelStub = sandbox.stub(fixtureUtils, 'addFixturesForModel')
.returns(Promise.resolve(modelResult));
relationResult = {expected: 1, done: 1};
addRelationStub = sandbox.stub(fixtureUtils, 'addFixturesForRelation')
.returns(Promise.resolve(relationResult));
});
it('should find the correct model & relation to add', function (done) {
// Execute
addSubscriberPermissions({}, loggerStub).then(function () {
addModelStub.calledOnce.should.be.true();
addModelStub.calledWith(
fixtureUtils.findModelFixtures('Permission', {object_type: 'subscriber'})
).should.be.true();
addRelationStub.calledOnce.should.be.true();
addRelationStub.calledWith(
fixtureUtils.findPermissionRelationsForObject('subscriber')
).should.be.true();
loggerStub.info.calledTwice.should.be.true();
loggerStub.warn.called.should.be.false();
done();
});
});
it('should warn the result shows less work was done than expected', function (done) {
// Setup
modelResult.expected = 3;
// Execute
addSubscriberPermissions({}, loggerStub).then(function () {
addModelStub.calledOnce.should.be.true();
addModelStub.calledWith(
fixtureUtils.findModelFixtures('Permission', {object_type: 'subscriber'})
).should.be.true();
addRelationStub.calledOnce.should.be.true();
addRelationStub.calledWith(
fixtureUtils.findPermissionRelationsForObject('subscriber')
).should.be.true();
loggerStub.info.calledOnce.should.be.true();
loggerStub.warn.calledOnce.should.be.true();
done();
});
});
});
});
});
});
@ -921,9 +995,9 @@ describe('Fixtures', function () {
clientOneStub.calledThrice.should.be.true();
clientAddStub.calledThrice.should.be.true();
permOneStub.callCount.should.eql(35);
permOneStub.callCount.should.eql(40);
permsAddStub.called.should.be.true();
permsAddStub.callCount.should.eql(35);
permsAddStub.callCount.should.eql(40);
permsAllStub.calledOnce.should.be.true();
rolesAllStub.calledOnce.should.be.true();
@ -932,8 +1006,8 @@ describe('Fixtures', function () {
// Relations
modelMethodStub.filter.called.should.be.true();
// 25 permissions, 1 tag
modelMethodStub.filter.callCount.should.eql(25 + 1);
// 26 permissions, 1 tag
modelMethodStub.filter.callCount.should.eql(28 + 1);
modelMethodStub.find.called.should.be.true();
// 3 roles, 1 post
modelMethodStub.find.callCount.should.eql(3 + 1);

View File

@ -152,21 +152,21 @@ describe('Utils', function () {
fixtureUtils.addFixturesForRelation(fixtures.relations[0]).then(function (result) {
should.exist(result);
result.should.be.an.Object();
result.should.have.property('expected', 25);
result.should.have.property('done', 25);
result.should.have.property('expected', 28);
result.should.have.property('done', 28);
// Permissions & Roles
permsAllStub.calledOnce.should.be.true();
rolesAllStub.calledOnce.should.be.true();
dataMethodStub.filter.callCount.should.eql(25);
dataMethodStub.filter.callCount.should.eql(28);
dataMethodStub.find.callCount.should.eql(3);
fromItem.related.callCount.should.eql(25);
fromItem.findWhere.callCount.should.eql(25);
toItem[0].get.callCount.should.eql(50);
fromItem.related.callCount.should.eql(28);
fromItem.findWhere.callCount.should.eql(28);
toItem[0].get.callCount.should.eql(56);
fromItem.permissions.callCount.should.eql(25);
fromItem.attach.callCount.should.eql(25);
fromItem.permissions.callCount.should.eql(28);
fromItem.attach.callCount.should.eql(28);
fromItem.attach.calledWith(toItem).should.be.true();
done();

View File

@ -32,8 +32,8 @@ var should = require('should'),
describe('DB version integrity', function () {
// Only these variables should need updating
var currentDbVersion = '005',
currentSchemaHash = 'be706cdbeb06103d90703ee733efc556',
currentFixturesHash = 'ba195b645386b019a69c4b79e6854138';
currentSchemaHash = 'f63f41ac97b5665a30c899409bbf9a83',
currentFixturesHash = '56f781fa3bba0fdbf98da5f232ec9b11';
// If this test is failing, then it is likely a change has been made that requires a DB version bump,
// and the values above will need updating as confirmation
@ -405,12 +405,14 @@ describe('Migrations', function () {
});
describe('01-add-tour-column-to-users', function () {
var addTourColumn = updates004[0];
it('does not try to add a new column if the table does not exist', function (done) {
// Setup
knexMock.schema.hasTable.withArgs('users').returns(new Promise.resolve(false));
// Execute
updates004[0](loggerStub).then(function () {
addTourColumn(loggerStub).then(function () {
knexMock.schema.hasTable.calledOnce.should.be.true();
knexMock.schema.hasTable.calledWith('users').should.be.true();
@ -431,7 +433,7 @@ describe('Migrations', function () {
knexMock.schema.hasColumn.withArgs('users', 'tour').returns(new Promise.resolve(true));
// Execute
updates004[0](loggerStub).then(function () {
addTourColumn(loggerStub).then(function () {
knexMock.schema.hasTable.calledOnce.should.be.true();
knexMock.schema.hasTable.calledWith('users').should.be.true();
@ -453,7 +455,7 @@ describe('Migrations', function () {
knexMock.schema.hasColumn.withArgs('users', 'tour').returns(new Promise.resolve(false));
// Execute
updates004[0](loggerStub).then(function () {
addTourColumn(loggerStub).then(function () {
knexMock.schema.hasTable.calledOnce.should.be.true();
knexMock.schema.hasTable.calledWith('users').should.be.true();
@ -472,12 +474,14 @@ describe('Migrations', function () {
});
describe('02-add-sortorder-column-to-poststags', function () {
var addSortOrderColumn = updates004[1];
it('does not try to add a new column if the table does not exist', function (done) {
// Setup
knexMock.schema.hasTable.withArgs('posts_tags').returns(new Promise.resolve(false));
// Execute
updates004[1](loggerStub).then(function () {
addSortOrderColumn(loggerStub).then(function () {
knexMock.schema.hasTable.calledOnce.should.be.true();
knexMock.schema.hasTable.calledWith('posts_tags').should.be.true();
@ -498,7 +502,7 @@ describe('Migrations', function () {
knexMock.schema.hasColumn.withArgs('posts_tags', 'sort_order').returns(new Promise.resolve(true));
// Execute
updates004[1](loggerStub).then(function () {
addSortOrderColumn(loggerStub).then(function () {
knexMock.schema.hasTable.calledOnce.should.be.true();
knexMock.schema.hasTable.calledWith('posts_tags').should.be.true();
@ -520,7 +524,7 @@ describe('Migrations', function () {
knexMock.schema.hasColumn.withArgs('posts_tags', 'sort_order').returns(new Promise.resolve(false));
// Execute
updates004[1](loggerStub).then(function () {
addSortOrderColumn(loggerStub).then(function () {
knexMock.schema.hasTable.calledOnce.should.be.true();
knexMock.schema.hasTable.calledWith('posts_tags').should.be.true();
@ -539,12 +543,14 @@ describe('Migrations', function () {
});
describe('03-add-many-columns-to-clients', function () {
var addClientColumns = updates004[2];
it('does not try to add new columns if the table does not exist', function (done) {
// Setup
knexMock.schema.hasTable.withArgs('clients').returns(new Promise.resolve(false));
// Execute
updates004[2](loggerStub).then(function () {
addClientColumns(loggerStub).then(function () {
knexMock.schema.hasTable.calledOnce.should.be.true();
knexMock.schema.hasTable.calledWith('clients').should.be.true();
@ -569,7 +575,7 @@ describe('Migrations', function () {
knexMock.schema.hasColumn.withArgs('clients', 'description').returns(new Promise.resolve(true));
// Execute
updates004[2](loggerStub).then(function () {
addClientColumns(loggerStub).then(function () {
knexMock.schema.hasTable.calledOnce.should.be.true();
knexMock.schema.hasTable.calledWith('clients').should.be.true();
@ -599,7 +605,7 @@ describe('Migrations', function () {
knexMock.schema.hasColumn.withArgs('clients', 'description').returns(new Promise.resolve(false));
// Execute
updates004[2](loggerStub).then(function () {
addClientColumns(loggerStub).then(function () {
knexMock.schema.hasTable.calledOnce.should.be.true();
knexMock.schema.hasTable.calledWith('clients').should.be.true();
@ -634,7 +640,7 @@ describe('Migrations', function () {
knexMock.schema.hasColumn.withArgs('clients', 'description').returns(new Promise.resolve(true));
// Execute
updates004[2](loggerStub).then(function () {
addClientColumns(loggerStub).then(function () {
knexMock.schema.hasTable.calledOnce.should.be.true();
knexMock.schema.hasTable.calledWith('clients').should.be.true();
@ -658,12 +664,14 @@ describe('Migrations', function () {
});
describe('04-add-clienttrusteddomains-table', function () {
var addTrustedDomains = updates004[3];
it('does not try to add a new table if the table already exists', function (done) {
// Setup
knexMock.schema.hasTable.withArgs('client_trusted_domains').returns(new Promise.resolve(true));
// Execute
updates004[3](loggerStub).then(function () {
addTrustedDomains(loggerStub).then(function () {
knexMock.schema.hasTable.calledOnce.should.be.true();
knexMock.schema.hasTable.calledWith('client_trusted_domains').should.be.true();
@ -681,7 +689,7 @@ describe('Migrations', function () {
knexMock.schema.hasTable.withArgs('client_trusted_domains').returns(new Promise.resolve(false));
// Execute
updates004[3](loggerStub).then(function () {
addTrustedDomains(loggerStub).then(function () {
knexMock.schema.hasTable.calledOnce.should.be.true();
knexMock.schema.hasTable.calledWith('client_trusted_domains').should.be.true();
@ -697,6 +705,8 @@ describe('Migrations', function () {
});
describe('05-drop-unique-on-clients-secret', function () {
var dropUnique = updates004[4];
it('does not try to drop unique if the table does not exist', function (done) {
// Setup
getIndexesStub.withArgs('clients').returns(new Promise.resolve(
@ -705,7 +715,7 @@ describe('Migrations', function () {
knexMock.schema.hasTable.withArgs('clients').returns(new Promise.resolve(false));
// Execute
updates004[4](loggerStub).then(function () {
dropUnique(loggerStub).then(function () {
knexMock.schema.hasTable.calledOnce.should.be.true();
knexMock.schema.hasTable.calledWith('clients').should.be.true();
@ -729,7 +739,7 @@ describe('Migrations', function () {
);
// Execute
updates004[4](loggerStub).then(function () {
dropUnique(loggerStub).then(function () {
knexMock.schema.hasTable.calledOnce.should.be.true();
knexMock.schema.hasTable.calledWith('clients').should.be.true();
@ -754,7 +764,7 @@ describe('Migrations', function () {
);
// Execute
updates004[4](loggerStub).then(function () {
dropUnique(loggerStub).then(function () {
knexMock.schema.hasTable.calledOnce.should.be.true();
knexMock.schema.hasTable.calledWith('clients').should.be.true();
@ -798,7 +808,7 @@ describe('Migrations', function () {
tasksSpy.calledOnce.should.be.true();
tasksSpy.calledWith('005', loggerStub).should.be.true();
tasksSpy.firstCall.returnValue.should.be.an.Array().with.lengthOf(4);
tasksSpy.firstCall.returnValue.should.be.an.Array().with.lengthOf(5);
sequenceStub.calledTwice.should.be.true();
@ -807,11 +817,12 @@ describe('Migrations', function () {
sequenceStub.firstCall.args[0][0].should.be.a.Function().with.property('name', 'runVersionTasks');
sequenceStub.secondCall.calledWith(sinon.match.array, loggerStub).should.be.true();
sequenceStub.secondCall.args[0].should.be.an.Array().with.lengthOf(4);
sequenceStub.secondCall.args[0].should.be.an.Array().with.lengthOf(5);
sequenceStub.secondCall.args[0][0].should.be.a.Function().with.property('name', 'dropHiddenColumnFromTags');
sequenceStub.secondCall.args[0][1].should.be.a.Function().with.property('name', 'addVisibilityColumnToKeyTables');
sequenceStub.secondCall.args[0][2].should.be.a.Function().with.property('name', 'addMobiledocColumnToPosts');
sequenceStub.secondCall.args[0][3].should.be.a.Function().with.property('name', 'addSocialMediaColumnsToUsers');
sequenceStub.secondCall.args[0][4].should.be.a.Function().with.property('name', 'addSubscribersTable');
// Reset sequence
sequenceReset();
@ -820,7 +831,7 @@ describe('Migrations', function () {
});
describe('Tasks:', function () {
var dropColumnStub, addColumnStub,
var dropColumnStub, addColumnStub, createTableStub,
knexStub, knexMock;
beforeEach(function () {
@ -834,6 +845,7 @@ describe('Migrations', function () {
dropColumnStub = sandbox.stub(schema.commands, 'dropColumn');
addColumnStub = sandbox.stub(schema.commands, 'addColumn');
createTableStub = sandbox.stub(schema.commands, 'createTable');
});
afterEach(function () {
@ -842,16 +854,18 @@ describe('Migrations', function () {
it('should have tasks for 005', function () {
should.exist(updates005);
updates005.should.be.an.Array().with.lengthOf(4);
updates005.should.be.an.Array().with.lengthOf(5);
});
describe('01-drop-hidden-column-from-tags', function () {
var dropHiddenColumn = updates005[0];
it('does not try to drop column if the table does not exist', function (done) {
// Setup
knexMock.schema.hasTable.withArgs('tags').returns(Promise.resolve(false));
// Execute
updates005[0](loggerStub).then(function () {
dropHiddenColumn(loggerStub).then(function () {
knexMock.schema.hasTable.calledOnce.should.be.true();
knexMock.schema.hasTable.calledWith('tags').should.be.true();
@ -872,7 +886,7 @@ describe('Migrations', function () {
knexMock.schema.hasColumn.withArgs('tags', 'hidden').returns(Promise.resolve(false));
// Execute
updates005[0](loggerStub).then(function () {
dropHiddenColumn(loggerStub).then(function () {
knexMock.schema.hasTable.calledOnce.should.be.true();
knexMock.schema.hasTable.calledWith('tags').should.be.true();
@ -894,7 +908,7 @@ describe('Migrations', function () {
knexMock.schema.hasColumn.withArgs('tags', 'hidden').returns(Promise.resolve(true));
// Execute
updates005[0](loggerStub).then(function () {
dropHiddenColumn(loggerStub).then(function () {
knexMock.schema.hasTable.calledOnce.should.be.true();
knexMock.schema.hasTable.calledWith('tags').should.be.true();
@ -913,6 +927,8 @@ describe('Migrations', function () {
});
describe('02-add-visibility-column-to-key-tables', function () {
var addVisibilityColumn = updates005[1];
it('does not try to add new column if the table does not exist', function (done) {
// Setup
knexMock.schema.hasTable.withArgs('posts').returns(Promise.resolve(false));
@ -920,7 +936,7 @@ describe('Migrations', function () {
knexMock.schema.hasTable.withArgs('users').returns(Promise.resolve(false));
// Execute
updates005[1](loggerStub).then(function () {
addVisibilityColumn(loggerStub).then(function () {
knexMock.schema.hasTable.calledThrice.should.be.true();
knexMock.schema.hasTable.calledWith('posts').should.be.true();
knexMock.schema.hasTable.calledWith('tags').should.be.true();
@ -948,7 +964,7 @@ describe('Migrations', function () {
knexMock.schema.hasColumn.withArgs('users', 'visibility').returns(Promise.resolve(true));
// Execute
updates005[1](loggerStub).then(function () {
addVisibilityColumn(loggerStub).then(function () {
knexMock.schema.hasTable.calledThrice.should.be.true();
knexMock.schema.hasTable.calledWith('posts').should.be.true();
knexMock.schema.hasTable.calledWith('tags').should.be.true();
@ -979,7 +995,7 @@ describe('Migrations', function () {
knexMock.schema.hasColumn.withArgs('users', 'visibility').returns(Promise.resolve(false));
// Execute
updates005[1](loggerStub).then(function () {
addVisibilityColumn(loggerStub).then(function () {
knexMock.schema.hasTable.calledThrice.should.be.true();
knexMock.schema.hasTable.calledWith('posts').should.be.true();
knexMock.schema.hasTable.calledWith('tags').should.be.true();
@ -1012,7 +1028,7 @@ describe('Migrations', function () {
knexMock.schema.hasColumn.withArgs('tags', 'visibility').returns(Promise.resolve(true));
knexMock.schema.hasColumn.withArgs('users', 'visibility').returns(Promise.resolve(false));
// Execute
updates005[1](loggerStub).then(function () {
addVisibilityColumn(loggerStub).then(function () {
knexMock.schema.hasTable.calledThrice.should.be.true();
knexMock.schema.hasTable.calledWith('posts').should.be.true();
knexMock.schema.hasTable.calledWith('tags').should.be.true();
@ -1037,12 +1053,14 @@ describe('Migrations', function () {
});
describe('03-add-mobiledoc-column-to-posts', function () {
var addMobiledocColumn = updates005[2];
it('does not try to add a new column if the table does not exist', function (done) {
// Setup
knexMock.schema.hasTable.withArgs('posts').returns(Promise.resolve(false));
// Execute
updates005[2](loggerStub).then(function () {
addMobiledocColumn(loggerStub).then(function () {
knexMock.schema.hasTable.calledOnce.should.be.true();
knexMock.schema.hasTable.calledWith('posts').should.be.true();
@ -1063,7 +1081,7 @@ describe('Migrations', function () {
knexMock.schema.hasColumn.withArgs('posts', 'mobiledoc').returns(Promise.resolve(true));
// Execute
updates005[2](loggerStub).then(function () {
addMobiledocColumn(loggerStub).then(function () {
knexMock.schema.hasTable.calledOnce.should.be.true();
knexMock.schema.hasTable.calledWith('posts').should.be.true();
@ -1085,7 +1103,7 @@ describe('Migrations', function () {
knexMock.schema.hasColumn.withArgs('posts', 'mobiledoc').returns(Promise.resolve(false));
// Execute
updates005[2](loggerStub).then(function () {
addMobiledocColumn(loggerStub).then(function () {
knexMock.schema.hasTable.calledOnce.should.be.true();
knexMock.schema.hasTable.calledWith('posts').should.be.true();
@ -1104,12 +1122,14 @@ describe('Migrations', function () {
});
describe('04-add-social-media-columns-to-users', function () {
var addSocialMediaColumns = updates005[3];
it('does not try to add new columns if the table does not exist', function (done) {
// Setup
knexMock.schema.hasTable.withArgs('users').returns(Promise.resolve(false));
// Execute
updates005[3](loggerStub).then(function () {
addSocialMediaColumns(loggerStub).then(function () {
knexMock.schema.hasTable.calledOnce.should.be.true();
knexMock.schema.hasTable.calledWith('users').should.be.true();
@ -1131,7 +1151,7 @@ describe('Migrations', function () {
knexMock.schema.hasColumn.withArgs('users', 'twitter').returns(Promise.resolve(true));
// Execute
updates005[3](loggerStub).then(function () {
addSocialMediaColumns(loggerStub).then(function () {
knexMock.schema.hasTable.calledOnce.should.be.true();
knexMock.schema.hasTable.calledWith('users').should.be.true();
@ -1155,7 +1175,7 @@ describe('Migrations', function () {
knexMock.schema.hasColumn.withArgs('users', 'twitter').returns(Promise.resolve(false));
// Execute
updates005[3](loggerStub).then(function () {
addSocialMediaColumns(loggerStub).then(function () {
knexMock.schema.hasTable.calledOnce.should.be.true();
knexMock.schema.hasTable.calledWith('users').should.be.true();
@ -1181,7 +1201,7 @@ describe('Migrations', function () {
knexMock.schema.hasColumn.withArgs('users', 'twitter').returns(Promise.resolve(true));
// Execute
updates005[3](loggerStub).then(function () {
addSocialMediaColumns(loggerStub).then(function () {
knexMock.schema.hasTable.calledOnce.should.be.true();
knexMock.schema.hasTable.calledWith('users').should.be.true();
@ -1200,6 +1220,47 @@ describe('Migrations', function () {
}).catch(done);
});
});
describe('05-add-subscribers-table', function () {
var addSubscribers = updates005[4];
it('does not try to add a new table if the table already exists', function (done) {
// Setup
knexMock.schema.hasTable.withArgs('subscribers').returns(new Promise.resolve(true));
// Execute
addSubscribers(loggerStub).then(function () {
knexMock.schema.hasTable.calledOnce.should.be.true();
knexMock.schema.hasTable.calledWith('subscribers').should.be.true();
createTableStub.called.should.be.false();
loggerStub.info.called.should.be.false();
loggerStub.warn.calledOnce.should.be.true();
done();
}).catch(done);
});
it('tries to add a new table if the table does not exist', function (done) {
// Setup
knexMock.schema.hasTable.withArgs('subscribers').returns(new Promise.resolve(false));
// Execute
addSubscribers(loggerStub).then(function () {
knexMock.schema.hasTable.calledOnce.should.be.true();
knexMock.schema.hasTable.calledWith('subscribers').should.be.true();
createTableStub.calledOnce.should.be.true();
createTableStub.calledWith('subscribers').should.be.true();
loggerStub.info.calledOnce.should.be.true();
loggerStub.warn.called.should.be.false();
done();
}).catch(done);
});
});
});
});
});