Migration messaging improvements

refs #6301

- fix messages that joined with comma and therefore missed outputting version no
- change `logInfo` to `logger` that has both an info and a warn method
- add new warn method to errors
- add a warn message everytime a migration (data or fixture) gets skipped over
- update logger everywhere, including tests
- update tests to check logger.warn gets called
This commit is contained in:
Hannah Wolfe 2016-03-21 12:44:23 +00:00
parent c2d8436437
commit 84f387785a
24 changed files with 539 additions and 408 deletions

View File

@ -2,17 +2,23 @@ var commands = require('../../schema').commands,
db = require('../../db'),
table = 'users',
column = 'tour';
column = 'tour',
message = 'Adding column: ' + table + '.' + column;
module.exports = function addTourColumnToUsers(logInfo) {
module.exports = function addTourColumnToUsers(logger) {
return db.knex.schema.hasTable(table).then(function (exists) {
if (exists) {
return db.knex.schema.hasColumn(table, column).then(function (exists) {
if (!exists) {
logInfo('Adding column: ' + table + '.' + column);
logger.info(message);
return commands.addColumn(table, column);
} else {
logger.warn(message);
}
});
} else {
// @TODO: this should probably be an error
logger.warn(message);
}
});
};

View File

@ -2,17 +2,23 @@ var commands = require('../../schema').commands,
db = require('../../db'),
table = 'posts_tags',
column = 'sort_order';
column = 'sort_order',
message = 'Adding column: ' + table + '.' + column;
module.exports = function addSortOrderColumnToPostsTags(logInfo) {
module.exports = function addSortOrderColumnToPostsTags(logger) {
return db.knex.schema.hasTable(table).then(function (exists) {
if (exists) {
return db.knex.schema.hasColumn(table, column).then(function (exists) {
if (!exists) {
logInfo('Adding column: ' + table + '.' + column);
logger.info(message);
return commands.addColumn(table, column);
} else {
logger.warn(message);
}
});
} else {
// @TODO: this should probably be an error
logger.warn(message);
}
});
};

View File

@ -5,17 +5,23 @@ var Promise = require('bluebird'),
table = 'clients',
columns = ['redirection_uri', 'logo', 'status', 'type', 'description'];
module.exports = function addManyColumnsToClients(logInfo) {
module.exports = function addManyColumnsToClients(logger) {
return db.knex.schema.hasTable(table).then(function (exists) {
if (exists) {
return Promise.mapSeries(columns, function (column) {
var message = 'Adding column: ' + table + '.' + column;
return db.knex.schema.hasColumn(table, column).then(function (exists) {
if (!exists) {
logInfo('Adding column: ' + table + '.' + column);
logger.info(message);
return commands.addColumn(table, column);
} else {
logger.warn(message);
}
});
});
} else {
// @TODO: this should probably be an error
logger.warn('Adding columns to table: ' + table);
}
});
};

View File

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

View File

@ -2,17 +2,23 @@ var commands = require('../../schema').commands,
db = require('../../db'),
table = 'clients',
column = 'secret';
column = 'secret',
message = 'Dropping unique on: ' + table + '.' + column;
module.exports = function dropUniqueOnClientsSecret(logInfo) {
module.exports = function dropUniqueOnClientsSecret(logger) {
return db.knex.schema.hasTable(table).then(function (exists) {
if (exists) {
return commands.getIndexes(table).then(function (indexes) {
if (indexes.indexOf(table + '_' + column + '_unique') > -1) {
logInfo('Dropping unique on: ' + table + '.' + column);
logger.info(message);
return commands.dropUnique(table, column);
} else {
logger.warn(message);
}
});
} else {
// @TODO: this should probably be an error
logger.warn(message);
}
});
};

View File

@ -20,14 +20,14 @@ writeExportFile = function writeExportFile(exportResult) {
* ## Backup
* does an export, and stores this in a local file
*
* @param {Function} [logInfo]
* @param {{info: logger.info, warn: logger.warn}} [logger]
* @returns {Promise<*>}
*/
backup = function backup(logInfo) {
// If we get passed a function, use it to output noticies, else don't do anything
logInfo = _.isFunction(logInfo) ? logInfo : _.noop;
backup = function backup(logger) {
// If we get passed a function, use it to output notices, else don't do anything
logger = logger && _.isFunction(logger.info) ? logger : {info: _.noop};
logInfo('Creating database backup');
logger.info('Creating database backup');
var props = {
data: exporter.doExport(),
@ -37,7 +37,7 @@ backup = function backup(logInfo) {
return Promise.props(props)
.then(writeExportFile)
.then(function successMessage(filename) {
logInfo('Database backup written to: ' + filename);
logger.info('Database backup written to: ' + filename);
});
};

View File

@ -15,9 +15,11 @@ var _ = require('lodash'),
privacyMessage = [
i18n.t('notices.data.fixtures.jQueryRemoved'),
i18n.t('notices.data.fixtures.canBeChanged')
];
],
module.exports = function moveJQuery(options, logInfo) {
message = 'Adding jQuery link to ghost_foot';
module.exports = function moveJQuery(options, logger) {
var value;
return models.Settings.findOne('ghost_foot').then(function (setting) {
@ -25,14 +27,14 @@ module.exports = function moveJQuery(options, logInfo) {
value = setting.attributes.value;
// Only add jQuery if it's not already in there
if (value.indexOf(jquery.join('')) === -1) {
logInfo('Adding jQuery link to ghost_foot');
logger.info(message);
value = jquery.join('') + value;
return models.Settings.edit({key: 'ghost_foot', value: value}, options).then(function () {
if (_.isEmpty(config.privacy)) {
return Promise.resolve();
}
logInfo(privacyMessage.join(' ').replace(/<\/?strong>/g, ''));
logger.info(privacyMessage.join(' ').replace(/<\/?strong>/g, ''));
return notifications.add({
notifications: [{
type: 'info',
@ -40,7 +42,11 @@ module.exports = function moveJQuery(options, logInfo) {
}]
}, options);
});
} else {
logger.warn(message);
}
} else {
logger.warn(message);
}
});
};

View File

@ -1,12 +1,16 @@
// Update the `isPrivate` setting, so that it has a type of `private` rather than `blog`
var models = require('../../../../models'),
Promise = require('bluebird');
Promise = require('bluebird'),
module.exports = function updatePrivateSetting(options, logInfo) {
message = 'Update isPrivate setting';
module.exports = function updatePrivateSetting(options, logger) {
return models.Settings.findOne('isPrivate').then(function (setting) {
if (setting && setting.get('type') !== 'private') {
logInfo('Update isPrivate setting');
logger.info(message);
return models.Settings.edit({key: 'isPrivate', type: 'private'}, options);
} else {
logger.warn(message);
}
return Promise.resolve();
});

View File

@ -1,12 +1,16 @@
// Update the `password` setting, so that it has a type of `private` rather than `blog`
var models = require('../../../../models'),
Promise = require('bluebird');
Promise = require('bluebird'),
module.exports = function updatePasswordSetting(options, logInfo) {
message = 'Update password setting';
module.exports = function updatePasswordSetting(options, logger) {
return models.Settings.findOne('password').then(function (setting) {
if (setting && setting.get('type') !== 'private') {
logInfo('Update password setting');
logger.info(message);
return models.Settings.edit({key: 'password', type: 'private'}, options);
} else {
logger.warn(message);
}
return Promise.resolve();
});

View File

@ -4,17 +4,20 @@ var models = require('../../../../models'),
Promise = require('bluebird'),
crypto = require('crypto'),
adminClient = require('../fixtures').models.Client[0];
adminClient = require('../fixtures').models.Client[0],
message = 'Update ghost-admin client fixture';
module.exports = function updateGhostAdminClient(options, logInfo) {
module.exports = function updateGhostAdminClient(options, logger) {
// ghost-admin should already exist from 003 version
return models.Client.findOne({slug: adminClient.slug}).then(function (client) {
if (client && (client.get('secret') === 'not_available' || client.get('status') !== 'enabled')) {
logInfo('Update ghost-admin client fixture');
logger.info(message);
return models.Client.edit(
_.extend({}, adminClient, {secret: crypto.randomBytes(6).toString('hex')}),
_.extend({}, options, {id: client.id})
);
} else {
logger.warn(message);
}
return Promise.resolve();
});

View File

@ -2,13 +2,16 @@
var models = require('../../../../models'),
Promise = require('bluebird'),
frontendClient = require('../fixtures').models.Client[1];
frontendClient = require('../fixtures').models.Client[1],
message = 'Add ghost-frontend client fixture';
module.exports = function addGhostFrontendClient(options, logInfo) {
module.exports = function addGhostFrontendClient(options, logger) {
return models.Client.findOne({slug: frontendClient.slug}).then(function (client) {
if (!client) {
logInfo('Add ghost-frontend client fixture');
logger.info(message);
return models.Client.add(frontendClient, options);
} else {
logger.warn(message);
}
return Promise.resolve();
});

View File

@ -1,8 +1,9 @@
// Clean tags which start with commas, the only illegal char in tags
var models = require('../../../../models'),
Promise = require('bluebird');
Promise = require('bluebird'),
message = 'Cleaning malformed tags';
module.exports = function cleanBrokenTags(options, logInfo) {
module.exports = function cleanBrokenTags(options, logger) {
return models.Tag.findAll(options).then(function (tags) {
var tagOps = [];
if (tags) {
@ -18,9 +19,13 @@ module.exports = function cleanBrokenTags(options, logInfo) {
}
});
if (tagOps.length > 0) {
logInfo('Cleaning ' + tagOps.length + ' malformed tags');
logger.info(message + '(' + tagOps.length + ')');
return Promise.all(tagOps);
} else {
logger.warn(message);
}
} else {
logger.warn(message);
}
return Promise.resolve();
});

View File

@ -43,20 +43,22 @@ function processPostsArray(postsArray) {
return postsArray.reduce(buildTagOpsArray, []);
}
module.exports = function addPostTagOrder(options, logInfo) {
module.exports = function addPostTagOrder(options, logger) {
modelOptions = options;
migrationHasRunFlag = false;
logInfo('Collecting data on tag order for posts...');
logger.info('Collecting data on tag order for posts...');
return models.Post.findAll(_.extend({}, modelOptions))
.then(loadTagsForEachPost)
.then(processPostsArray)
.then(function (tagOps) {
if (tagOps.length > 0 && !migrationHasRunFlag) {
logInfo('Updating order on ' + tagOps.length + ' tag relationships (could take a while)...');
logger.info('Updating order on ' + tagOps.length + ' tag relationships (could take a while)...');
return sequence(tagOps).then(function () {
logInfo('Tag order successfully updated');
logger.info('Tag order successfully updated');
});
} else {
logger.warn('Updating order on tag relationships');
}
});
};

View File

@ -1,5 +1,6 @@
// Adds a new draft post with information about the new design
var models = require('../../../../models'),
newPost = {
title: 'You\'ve been upgraded to the latest version of Ghost',
slug: 'ghost-0-7',
@ -11,17 +12,20 @@ var models = require('../../../../models'),
language: 'en_US',
meta_title: null,
meta_description: null
};
},
message = 'Adding 0.7 upgrade post fixture';
module.exports = function addNewPostFixture(options, logInfo) {
module.exports = function addNewPostFixture(options, logger) {
return models.Post.findOne({slug: newPost.slug, status: 'all'}, options).then(function (post) {
if (!post) {
logInfo('Adding 0.7 upgrade post fixture');
logger.info(message);
// Set the published_at timestamp, but keep the post as a draft so doesn't appear on the frontend
// This is a hack to ensure that this post appears at the very top of the drafts list, because
// unpublished posts always appear first
newPost.published_at = Date.now();
return models.Post.add(newPost, options);
} else {
logger.warn(message);
}
});
};

View File

@ -125,10 +125,10 @@ addAllRelations = function addAllRelations() {
* Creates the user fixture and gives it the owner role.
* By default, users are given the Author role, making it hard to do this using the fixture system
*
* @param {Function} logInfo
* @param {{info: logger.info, warn: logger.warn}} logger
* @returns {Promise<*>}
*/
createOwner = function createOwner(logInfo) {
createOwner = function createOwner(logger) {
var user = {
name: 'Ghost Owner',
email: 'ghost@ghost.org',
@ -140,7 +140,7 @@ createOwner = function createOwner(logInfo) {
if (ownerRole) {
user.roles = [ownerRole.id];
logInfo('Creating owner');
logger.info('Creating owner');
return models.User.add(user, modelOptions);
}
});
@ -151,18 +151,18 @@ createOwner = function createOwner(logInfo) {
* Sequentially creates all models, in the order they are specified, and then
* creates all the relationships, also maintaining order.
*
* @param {Function} logInfo
* @param {{info: logger.info, warn: logger.warn}} logger
* @returns {Promise<*>}
*/
populate = function populate(logInfo) {
logInfo('Populating fixtures');
populate = function populate(logger) {
logger.info('Running fixture populations');
// ### Ensure all models are added
return addAllModels().then(function () {
// ### Ensure all relations are added
return addAllRelations();
}).then(function () {
return createOwner(logInfo);
return createOwner(logger);
});
};

View File

@ -1,12 +1,16 @@
var models = require('../../../models'),
ensureDefaultSettings;
ensureDefaultSettings = function ensureDefaultSettings(logInfo) {
/**
* ## Ensure Default Settings
* Wrapper around model.Settings.populateDefault, with logger
* @param {{info: logger.info, warn: logger.warn}} logger
* @returns {*}
*/
ensureDefaultSettings = function ensureDefaultSettings(logger) {
// Initialise the default settings
logInfo('Populating default settings');
return models.Settings.populateDefaults().then(function () {
logInfo('Complete');
});
logger.info('Ensuring default settings');
return models.Settings.populateDefaults();
};
module.exports = ensureDefaultSettings;

View File

@ -17,26 +17,26 @@ var sequence = require('../../../utils/sequence'),
* Handles doing subsequent updates for versions
*
* @param {Array} versions
* @param {Function} logInfo
* @param {{info: logger.info, warn: logger.warn}} logger
* @returns {Promise<*>}
*/
update = function update(versions, logInfo) {
logInfo('Updating fixtures');
update = function update(versions, logger) {
logger.info('Running fixture updates');
var ops = versions.reduce(function updateToVersion(ops, version) {
var tasks = versioning.getUpdateFixturesTasks(version, logInfo);
var tasks = versioning.getUpdateFixturesTasks(version, logger);
if (tasks && tasks.length > 0) {
ops.push(function runVersionTasks() {
logInfo('Updating fixtures to ', version);
return sequence(tasks, modelOptions, logInfo);
logger.info('Updating fixtures to ' + version);
return sequence(tasks, modelOptions, logger);
});
}
return ops;
}, []);
return sequence(ops, modelOptions, logInfo);
return sequence(ops, modelOptions, logger);
};
module.exports = update;

View File

@ -5,7 +5,7 @@ var Promise = require('bluebird'),
models = require('../../models'),
// private
logInfo,
logger,
fixClientSecret,
populate = require('./populate'),
update = require('./update'),
@ -15,8 +15,17 @@ var Promise = require('bluebird'),
reset = require('./reset'),
backup = require('./backup');
logInfo = function logInfo(message) {
errors.logInfo('Migrations', message);
/**
*
* @type {{info: logger.info, warn: logger.warn}}
*/
logger = {
info: function info(message) {
errors.logComponentInfo('Migrations', message);
},
warn: function warn(message) {
errors.logComponentWarn('Skipping Migrations', message);
}
};
// TODO: move to migration.to005() for next DB version
@ -24,7 +33,7 @@ fixClientSecret = function () {
return models.Clients.forge().query('where', 'secret', '=', 'not_available').fetch().then(function updateClients(results) {
return Promise.map(results.models, function mapper(client) {
if (process.env.NODE_ENV.indexOf('testing') !== 0) {
logInfo('Updating client secret');
logger.info('Updating client secret');
client.secret = crypto.randomBytes(6).toString('hex');
}
return models.Client.edit(client, {context: {internal: true}, id: client.id});
@ -48,12 +57,12 @@ init = function (tablesOnly) {
// 2. The database exists but is out of date
if (databaseVersion < defaultVersion || process.env.FORCE_MIGRATION) {
// Migrate to latest version
logInfo('Database upgrade required from version ' + databaseVersion + ' to ' + defaultVersion);
return update(databaseVersion, defaultVersion, logInfo);
logger.info('Database upgrade required from version ' + databaseVersion + ' to ' + defaultVersion);
return update(databaseVersion, defaultVersion, logger);
// 1. The database exists and is up-to-date
} else if (databaseVersion === defaultVersion) {
logInfo('Up to date at version ' + databaseVersion);
logger.info('Up-to-date at version ' + databaseVersion);
// TODO: temporary fix for missing client.secret
return fixClientSecret();
@ -69,8 +78,8 @@ init = function (tablesOnly) {
if (err && err.message === 'Settings table does not exist') {
// 4. The database has not yet been created
// Bring everything up from initial version.
logInfo('Database initialisation required for version ' + versioning.getDefaultDatabaseVersion());
return populate(logInfo, tablesOnly);
logger.info('Database initialisation required for version ' + versioning.getDefaultDatabaseVersion());
return populate(logger, tablesOnly);
}
// 3. The database exists but the currentVersion setting does not or cannot be understood
// In this case the setting was missing or there was some other problem

View File

@ -13,15 +13,15 @@ var Promise = require('bluebird'),
* Uses the schema to determine table structures, and automatically creates each table in order
* TODO: use this directly in tests, so migration.init() can forget about tablesOnly as an option
*
* @param {Function} logInfo
* @param {{info: logger.info, warn: logger.warn}} logger
* @param {Boolean} [tablesOnly] - used by tests
* @returns {Promise<*>}
*/
populate = function populate(logInfo, tablesOnly) {
logInfo('Creating tables...');
populate = function populate(logger, tablesOnly) {
logger.info('Creating tables...');
var tableSequence = Promise.mapSeries(schemaTables, function createTable(table) {
logInfo('Creating table: ' + table);
logger.info('Creating table: ' + table);
return commands.createTable(table);
});
@ -31,9 +31,9 @@ populate = function populate(logInfo, tablesOnly) {
return tableSequence.then(function () {
// Load the fixtures
return fixtures.populate(logInfo);
return fixtures.populate(logger);
}).then(function () {
return fixtures.ensureDefaultSettings(logInfo);
return fixtures.ensureDefaultSettings(logger);
});
};

View File

@ -16,17 +16,17 @@ var _ = require('lodash'),
* Fetch the update tasks for each version, and iterate through them in order
*
* @param {Array} versions
* @param {Function} logInfo
* @param {{info: logger.info, warn: logger.warn}} logger
* @returns {Promise<*>}
*/
updateDatabaseSchema = function updateDatabaseSchema(versions, logInfo) {
updateDatabaseSchema = function updateDatabaseSchema(versions, logger) {
var migrateOps = versions.reduce(function updateToVersion(migrateOps, version) {
var tasks = versioning.getUpdateDatabaseTasks(version, logInfo);
var tasks = versioning.getUpdateDatabaseTasks(version, logger);
if (tasks && tasks.length > 0) {
migrateOps.push(function runVersionTasks() {
logInfo('Updating database to ', version);
return sequence(tasks, logInfo);
logger.info('Updating database to ' + version);
return sequence(tasks, logger);
});
}
@ -35,10 +35,10 @@ updateDatabaseSchema = function updateDatabaseSchema(versions, logInfo) {
// execute the commands in sequence
if (!_.isEmpty(migrateOps)) {
logInfo('Running migrations');
logger.info('Running migrations');
}
return sequence(migrateOps, logInfo);
return sequence(migrateOps, logger);
};
/**
@ -47,10 +47,10 @@ updateDatabaseSchema = function updateDatabaseSchema(versions, logInfo) {
*
* @param {String} fromVersion
* @param {String} toVersion
* @param {Function} logInfo
* @param {{info: logger.info, warn: logger.warn}} logger
* @returns {Promise<*>}
*/
update = function update(fromVersion, toVersion, logInfo) {
update = function update(fromVersion, toVersion, logger) {
// Is the current version lower than the version we can migrate from?
// E.g. is this blog's DB older than 003?
if (fromVersion < versioning.canMigrateFromVersion) {
@ -63,14 +63,14 @@ update = function update(fromVersion, toVersion, logInfo) {
// This shouldn't include the from/current version (which we're already on)
var versionsToUpdate = versioning.getMigrationVersions(fromVersion, toVersion).slice(1);
return backup(logInfo).then(function () {
return updateDatabaseSchema(versionsToUpdate, logInfo);
return backup(logger).then(function () {
return updateDatabaseSchema(versionsToUpdate, logger);
}).then(function () {
// Ensure all of the current default settings are created (these are fixtures, so should be inserted first)
return fixtures.ensureDefaultSettings(logInfo);
return fixtures.ensureDefaultSettings(logger);
}).then(function () {
// Next, run any updates to the fixtures, including default settings, that are required
return fixtures.update(versionsToUpdate, logInfo);
return fixtures.update(versionsToUpdate, logger);
}).then(function () {
// Finally update the database's current version
return versioning.setDatabaseVersion();

View File

@ -84,7 +84,7 @@ errors = {
return Promise.reject(err);
},
logInfo: function (component, info) {
logComponentInfo: function (component, info) {
if ((process.env.NODE_ENV === 'development' ||
process.env.NODE_ENV === 'staging' ||
process.env.NODE_ENV === 'production')) {
@ -92,6 +92,14 @@ errors = {
}
},
logComponentWarn: function (component, warning) {
if ((process.env.NODE_ENV === 'development' ||
process.env.NODE_ENV === 'staging' ||
process.env.NODE_ENV === 'production')) {
console.info(chalk.yellow(component + ':', warning));
}
},
logWarn: function (warn, context, help) {
if ((process.env.NODE_ENV === 'development' ||
process.env.NODE_ENV === 'staging' ||
@ -401,7 +409,8 @@ errors = {
// using Function#bind for expressjs
_.each([
'logWarn',
'logInfo',
'logComponentInfo',
'logComponentWarn',
'rejectError',
'throwError',
'logError',

View File

@ -122,9 +122,12 @@ describe('Database Migration (special functions)', function () {
});
it('should populate all fixtures correctly', function (done) {
var logStub = sandbox.stub();
var loggerStub = {
info: sandbox.stub(),
warn: sandbox.stub()
};
fixtures.populate(logStub).then(function () {
fixtures.populate(loggerStub).then(function () {
var props = {
posts: Models.Post.findAll({include: ['tags']}),
tags: Models.Tag.findAll(),
@ -134,7 +137,8 @@ describe('Database Migration (special functions)', function () {
permissions: Models.Permission.findAll({include: ['roles']})
};
logStub.called.should.be.true();
loggerStub.info.called.should.be.true();
loggerStub.warn.called.should.be.false();
return Promise.props(props).then(function (result) {
should.exist(result);

View File

@ -17,10 +17,17 @@ var should = require('should'),
sandbox = sinon.sandbox.create();
describe('Fixtures', function () {
var loggerStub;
beforeEach(function (done) {
loggerStub = {
info: sandbox.stub(),
warn: sandbox.stub()
};
models.init().then(function () {
done();
});
}).catch(done);
});
afterEach(function () {
@ -30,35 +37,35 @@ describe('Fixtures', function () {
describe('Update fixtures', function () {
it('should call `getUpdateFixturesTasks` when upgrading from 003 -> 004', function (done) {
var logStub = sandbox.stub(),
getVersionTasksStub = sandbox.stub(versioning, 'getUpdateFixturesTasks').returns([]);
var getVersionTasksStub = sandbox.stub(versioning, 'getUpdateFixturesTasks').returns([]);
update(['004'], logStub).then(function () {
logStub.calledOnce.should.be.true();
update(['004'], loggerStub).then(function () {
loggerStub.info.calledOnce.should.be.true();
loggerStub.warn.called.should.be.false();
getVersionTasksStub.calledOnce.should.be.true();
done();
}).catch(done);
});
it('should NOT call `getUpdateFixturesTasks` when upgrading from 004 -> 004', function (done) {
var logStub = sandbox.stub(),
getVersionTasksStub = sandbox.stub(versioning, 'getUpdateFixturesTasks').returns([]);
var getVersionTasksStub = sandbox.stub(versioning, 'getUpdateFixturesTasks').returns([]);
update([], logStub).then(function () {
logStub.calledOnce.should.be.true();
update([], loggerStub).then(function () {
loggerStub.info.calledOnce.should.be.true();
loggerStub.warn.called.should.be.false();
getVersionTasksStub.calledOnce.should.be.false();
done();
}).catch(done);
});
it('should call tasks in correct order if provided', function (done) {
var logStub = sandbox.stub(),
task1Stub = sandbox.stub().returns(Promise.resolve()),
var task1Stub = sandbox.stub().returns(Promise.resolve()),
task2Stub = sandbox.stub().returns(Promise.resolve()),
getVersionTasksStub = sandbox.stub(versioning, 'getUpdateFixturesTasks').returns([task1Stub, task2Stub]);
update(['000'], logStub).then(function () {
logStub.calledTwice.should.be.true();
update(['000'], loggerStub).then(function () {
loggerStub.info.calledTwice.should.be.true();
loggerStub.warn.called.should.be.false();
getVersionTasksStub.calledOnce.should.be.true();
task1Stub.calledOnce.should.be.true();
task2Stub.calledOnce.should.be.true();
@ -69,8 +76,7 @@ describe('Fixtures', function () {
describe('Update to 004', function () {
it('should call all the 004 fixture upgrades', function (done) {
// Stub all the model methods so that nothing happens
var logStub = sandbox.stub(),
settingsOneStub = sandbox.stub(models.Settings, 'findOne').returns(Promise.resolve()),
var settingsOneStub = sandbox.stub(models.Settings, 'findOne').returns(Promise.resolve()),
settingsEditStub = sandbox.stub(models.Settings, 'edit').returns(Promise.resolve()),
clientOneStub = sandbox.stub(models.Client, 'findOne'),
clientEditStub = sandbox.stub(models.Client, 'edit').returns(Promise.resolve()),
@ -83,10 +89,16 @@ describe('Fixtures', function () {
clientOneStub.withArgs({slug: 'ghost-admin'}).returns(Promise.resolve());
clientOneStub.withArgs({slug: 'ghost-frontend'}).returns(Promise.resolve({}));
update(['004'], logStub).then(function (result) {
update(['004'], loggerStub).then(function (result) {
should.exist(result);
logStub.called.should.be.true();
// Gets called 3 times to output peripheral info
loggerStub.info.called.should.be.true();
loggerStub.info.callCount.should.eql(3);
// Should be called 8 times, once for each skipped migration
loggerStub.warn.called.should.be.true();
loggerStub.warn.callCount.should.eql(8);
settingsOneStub.calledThrice.should.be.true();
settingsEditStub.called.should.be.false();
clientOneStub.calledTwice.should.be.true();
@ -109,25 +121,24 @@ describe('Fixtures', function () {
describe('Tasks:', function () {
describe('01-move-jquery-with-alert', function () {
it('tries to move jQuery to ghost_foot', function (done) {
var logStub = sandbox.stub(),
settingsOneStub = sandbox.stub(models.Settings, 'findOne').returns(Promise.resolve({
attributes: {value: ''}
})),
var settingsOneStub = sandbox.stub(models.Settings, 'findOne').returns(Promise.resolve({
attributes: {value: ''}
})),
settingsEditStub = sandbox.stub(models.Settings, 'edit').returns(Promise.resolve());
fixtures004[0]({}, logStub).then(function () {
fixtures004[0]({}, loggerStub).then(function () {
settingsOneStub.calledOnce.should.be.true();
settingsOneStub.calledWith('ghost_foot').should.be.true();
settingsEditStub.calledOnce.should.be.true();
logStub.calledOnce.should.be.true();
loggerStub.info.calledOnce.should.be.true();
loggerStub.warn.called.should.be.false();
done();
});
}).catch(done);
});
it('does not move jQuery to ghost_foot if it is already there', function (done) {
var logStub = sandbox.stub(),
settingsOneStub = sandbox.stub(models.Settings, 'findOne').returns(Promise.resolve({
var settingsOneStub = sandbox.stub(models.Settings, 'findOne').returns(Promise.resolve({
attributes: {
value: '<!-- You can safely delete this line if your theme does not require jQuery -->\n'
+ '<script type="text/javascript" src="https://code.jquery.com/jquery-1.11.3.min.js"></script>\n\n'
@ -135,11 +146,12 @@ describe('Fixtures', function () {
})),
settingsEditStub = sandbox.stub(models.Settings, 'edit').returns(Promise.resolve());
fixtures004[0]({}, logStub).then(function () {
fixtures004[0]({}, loggerStub).then(function () {
settingsOneStub.calledOnce.should.be.true();
settingsOneStub.calledWith('ghost_foot').should.be.true();
settingsEditStub.calledOnce.should.be.false();
logStub.called.should.be.false();
loggerStub.info.called.should.be.false();
loggerStub.warn.calledOnce.should.be.true();
done();
}).catch(done);
@ -147,19 +159,19 @@ describe('Fixtures', function () {
it('tried to move jQuery AND add a privacy message if any privacy settings are on', function (done) {
configUtils.set({privacy: {useGoogleFonts: false}});
var logStub = sandbox.stub(),
settingsOneStub = sandbox.stub(models.Settings, 'findOne').returns(Promise.resolve({
var settingsOneStub = sandbox.stub(models.Settings, 'findOne').returns(Promise.resolve({
attributes: {value: ''}
})),
settingsEditStub = sandbox.stub(models.Settings, 'edit').returns(Promise.resolve()),
notificationsAddStub = sandbox.stub(notifications, 'add').returns(Promise.resolve());
fixtures004[0]({}, logStub).then(function () {
fixtures004[0]({}, loggerStub).then(function () {
settingsOneStub.calledOnce.should.be.true();
settingsOneStub.calledWith('ghost_foot').should.be.true();
settingsEditStub.calledOnce.should.be.true();
notificationsAddStub.calledOnce.should.be.true();
logStub.calledTwice.should.be.true();
loggerStub.info.calledTwice.should.be.true();
loggerStub.warn.called.should.be.false();
done();
}).catch(done);
@ -168,45 +180,45 @@ describe('Fixtures', function () {
describe('02-update-private-setting-type', function () {
it('tries to update setting type correctly', function (done) {
var logStub = sandbox.stub(),
settingObjStub = {get: sandbox.stub()},
var settingObjStub = {get: sandbox.stub()},
settingsOneStub = sandbox.stub(models.Settings, 'findOne').returns(
Promise.resolve(settingObjStub)
),
settingsEditStub = sandbox.stub(models.Settings, 'edit').returns(Promise.resolve());
fixtures004[1]({}, logStub).then(function () {
fixtures004[1]({}, loggerStub).then(function () {
settingsOneStub.calledOnce.should.be.true();
settingsOneStub.calledWith('isPrivate').should.be.true();
settingObjStub.get.calledOnce.should.be.true();
settingObjStub.get.calledWith('type').should.be.true();
settingsEditStub.calledOnce.should.be.true();
settingsEditStub.calledWith({key: 'isPrivate', type: 'private'}).should.be.true();
logStub.calledOnce.should.be.true();
sinon.assert.callOrder(settingsOneStub, settingObjStub.get, logStub, settingsEditStub);
loggerStub.info.calledOnce.should.be.true();
loggerStub.warn.called.should.be.false();
sinon.assert.callOrder(settingsOneStub, settingObjStub.get, loggerStub.info, settingsEditStub);
done();
}).catch(done);
});
it('does not try to update setting type if it is already set', function (done) {
var logStub = sandbox.stub(),
settingObjStub = {get: sandbox.stub().returns('private')},
var settingObjStub = {get: sandbox.stub().returns('private')},
settingsOneStub = sandbox.stub(models.Settings, 'findOne').returns(
Promise.resolve(settingObjStub)
),
settingsEditStub = sandbox.stub(models.Settings, 'edit').returns(Promise.resolve());
fixtures004[1]({}, logStub).then(function () {
fixtures004[1]({}, loggerStub).then(function () {
settingsOneStub.calledOnce.should.be.true();
settingsOneStub.calledWith('isPrivate').should.be.true();
settingObjStub.get.calledOnce.should.be.true();
settingObjStub.get.calledWith('type').should.be.true();
settingsEditStub.called.should.be.false();
logStub.calledOnce.should.be.false();
loggerStub.info.called.should.be.false();
loggerStub.warn.calledOnce.should.be.true();
sinon.assert.callOrder(settingsOneStub, settingObjStub.get);
sinon.assert.callOrder(settingsOneStub, settingObjStub.get, loggerStub.warn);
done();
}).catch(done);
@ -215,41 +227,41 @@ describe('Fixtures', function () {
describe('03-update-password-setting-type', function () {
it('tries to update setting type correctly', function (done) {
var logStub = sandbox.stub(),
settingObjStub = {get: sandbox.stub()},
var settingObjStub = {get: sandbox.stub()},
settingsOneStub = sandbox.stub(models.Settings, 'findOne').returns(
Promise.resolve(settingObjStub)
),
settingsEditStub = sandbox.stub(models.Settings, 'edit').returns(Promise.resolve());
fixtures004[2]({}, logStub).then(function () {
fixtures004[2]({}, loggerStub).then(function () {
settingsOneStub.calledOnce.should.be.true();
settingsOneStub.calledWith('password').should.be.true();
settingsEditStub.calledOnce.should.be.true();
settingsEditStub.calledWith({key: 'password', type: 'private'}).should.be.true();
logStub.calledOnce.should.be.true();
sinon.assert.callOrder(settingsOneStub, logStub, settingsEditStub);
loggerStub.info.calledOnce.should.be.true();
loggerStub.warn.called.should.be.false();
sinon.assert.callOrder(settingsOneStub, loggerStub.info, settingsEditStub);
done();
}).catch(done);
});
it('does not try to update setting type if it is already set', function (done) {
var logStub = sandbox.stub(),
settingObjStub = {get: sandbox.stub().returns('private')},
var settingObjStub = {get: sandbox.stub().returns('private')},
settingsOneStub = sandbox.stub(models.Settings, 'findOne').returns(
Promise.resolve(settingObjStub)
),
settingsEditStub = sandbox.stub(models.Settings, 'edit').returns(Promise.resolve());
fixtures004[2]({}, logStub).then(function () {
fixtures004[2]({}, loggerStub).then(function () {
settingsOneStub.calledOnce.should.be.true();
settingsOneStub.calledWith('password').should.be.true();
settingObjStub.get.calledOnce.should.be.true();
settingObjStub.get.calledWith('type').should.be.true();
settingsEditStub.called.should.be.false();
logStub.calledOnce.should.be.false();
loggerStub.info.called.should.be.false();
loggerStub.warn.calledOnce.should.be.true();
sinon.assert.callOrder(settingsOneStub, settingObjStub.get);
@ -260,21 +272,21 @@ describe('Fixtures', function () {
describe('04-update-ghost-admin-client', function () {
it('tries to update client correctly', function (done) {
var logStub = sandbox.stub(),
clientObjStub = {get: sandbox.stub()},
var clientObjStub = {get: sandbox.stub()},
clientOneStub = sandbox.stub(models.Client, 'findOne').returns(Promise.resolve(clientObjStub)),
clientEditStub = sandbox.stub(models.Client, 'edit').returns(Promise.resolve());
fixtures004[3]({}, logStub).then(function () {
fixtures004[3]({}, loggerStub).then(function () {
clientOneStub.calledOnce.should.be.true();
clientOneStub.calledWith({slug: 'ghost-admin'}).should.be.true();
clientObjStub.get.calledTwice.should.be.true();
clientObjStub.get.calledWith('secret').should.be.true();
clientObjStub.get.calledWith('status').should.be.true();
clientEditStub.calledOnce.should.be.true();
logStub.calledOnce.should.be.true();
loggerStub.info.calledOnce.should.be.true();
loggerStub.warn.called.should.be.false();
sinon.assert.callOrder(
clientOneStub, clientObjStub.get, clientObjStub.get, logStub, clientEditStub
clientOneStub, clientObjStub.get, clientObjStub.get, loggerStub.info, clientEditStub
);
done();
@ -282,38 +294,37 @@ describe('Fixtures', function () {
});
it('does not try to update client if the secret and status are already correct', function (done) {
var logStub = sandbox.stub(),
clientObjStub = {get: sandbox.stub()},
var clientObjStub = {get: sandbox.stub()},
clientOneStub = sandbox.stub(models.Client, 'findOne').returns(Promise.resolve(clientObjStub)),
clientEditStub = sandbox.stub(models.Client, 'edit').returns(Promise.resolve());
clientObjStub.get.withArgs('secret').returns('abc');
clientObjStub.get.withArgs('status').returns('enabled');
fixtures004[3]({}, logStub).then(function () {
fixtures004[3]({}, loggerStub).then(function () {
clientOneStub.calledOnce.should.be.true();
clientOneStub.calledWith({slug: 'ghost-admin'}).should.be.true();
clientObjStub.get.calledTwice.should.be.true();
clientObjStub.get.calledWith('secret').should.be.true();
clientObjStub.get.calledWith('status').should.be.true();
clientEditStub.called.should.be.false();
logStub.called.should.be.false();
sinon.assert.callOrder(clientOneStub, clientObjStub.get, clientObjStub.get);
loggerStub.info.called.should.be.false();
loggerStub.warn.calledOnce.should.be.true();
sinon.assert.callOrder(clientOneStub, clientObjStub.get, clientObjStub.get, loggerStub.warn);
done();
}).catch(done);
});
it('tries to update client if secret is correct but status is wrong', function (done) {
var logStub = sandbox.stub(),
clientObjStub = {get: sandbox.stub()},
var clientObjStub = {get: sandbox.stub()},
clientOneStub = sandbox.stub(models.Client, 'findOne').returns(Promise.resolve(clientObjStub)),
clientEditStub = sandbox.stub(models.Client, 'edit').returns(Promise.resolve());
clientObjStub.get.withArgs('secret').returns('abc');
clientObjStub.get.withArgs('status').returns('development');
fixtures004[3]({}, logStub).then(function () {
fixtures004[3]({}, loggerStub).then(function () {
clientOneStub.calledOnce.should.be.true();
clientOneStub.calledWith({slug: 'ghost-admin'}).should.be.true();
clientObjStub.get.calledTwice.should.be.true();
@ -321,9 +332,10 @@ describe('Fixtures', function () {
clientObjStub.get.calledWith('status').should.be.true();
clientEditStub.calledOnce.should.be.true();
logStub.calledOnce.should.be.true();
loggerStub.info.calledOnce.should.be.true();
loggerStub.warn.called.should.be.false();
sinon.assert.callOrder(
clientOneStub, clientObjStub.get, clientObjStub.get, logStub, clientEditStub
clientOneStub, clientObjStub.get, clientObjStub.get, loggerStub.info, clientEditStub
);
done();
@ -331,24 +343,24 @@ describe('Fixtures', function () {
});
it('tries to update client if status is correct but secret is wrong', function (done) {
var logStub = sandbox.stub(),
clientObjStub = {get: sandbox.stub()},
var clientObjStub = {get: sandbox.stub()},
clientOneStub = sandbox.stub(models.Client, 'findOne').returns(Promise.resolve(clientObjStub)),
clientEditStub = sandbox.stub(models.Client, 'edit').returns(Promise.resolve());
clientObjStub.get.withArgs('secret').returns('not_available');
clientObjStub.get.withArgs('status').returns('enabled');
fixtures004[3]({}, logStub).then(function () {
fixtures004[3]({}, loggerStub).then(function () {
clientOneStub.calledOnce.should.be.true();
clientOneStub.calledWith({slug: 'ghost-admin'}).should.be.true();
clientObjStub.get.calledOnce.should.be.true();
clientObjStub.get.calledWith('secret').should.be.true();
clientEditStub.calledOnce.should.be.true();
logStub.calledOnce.should.be.true();
loggerStub.info.calledOnce.should.be.true();
loggerStub.warn.called.should.be.false();
sinon.assert.callOrder(
clientOneStub, clientObjStub.get, logStub, clientEditStub
clientOneStub, clientObjStub.get, loggerStub.info, clientEditStub
);
done();
@ -358,31 +370,31 @@ describe('Fixtures', function () {
describe('05-add-ghost-frontend-client', function () {
it('tries to add client correctly', function (done) {
var logStub = sandbox.stub(),
clientOneStub = sandbox.stub(models.Client, 'findOne').returns(Promise.resolve()),
var clientOneStub = sandbox.stub(models.Client, 'findOne').returns(Promise.resolve()),
clientAddStub = sandbox.stub(models.Client, 'add').returns(Promise.resolve());
fixtures004[4]({}, logStub).then(function () {
fixtures004[4]({}, loggerStub).then(function () {
clientOneStub.calledOnce.should.be.true();
clientOneStub.calledWith({slug: 'ghost-frontend'}).should.be.true();
clientAddStub.calledOnce.should.be.true();
logStub.calledOnce.should.be.true();
sinon.assert.callOrder(clientOneStub, logStub, clientAddStub);
loggerStub.info.calledOnce.should.be.true();
loggerStub.warn.called.should.be.false();
sinon.assert.callOrder(clientOneStub, loggerStub.info, clientAddStub);
done();
}).catch(done);
});
it('does not try to add client if it already exists', function (done) {
var logStub = sandbox.stub(),
clientOneStub = sandbox.stub(models.Client, 'findOne').returns(Promise.resolve({})),
var clientOneStub = sandbox.stub(models.Client, 'findOne').returns(Promise.resolve({})),
clientAddStub = sandbox.stub(models.Client, 'add').returns(Promise.resolve());
fixtures004[4]({}, logStub).then(function () {
fixtures004[4]({}, loggerStub).then(function () {
clientOneStub.calledOnce.should.be.true();
clientOneStub.calledWith({slug: 'ghost-frontend'}).should.be.true();
clientAddStub.called.should.be.false();
logStub.called.should.be.false();
loggerStub.info.called.should.be.false();
loggerStub.warn.calledOnce.should.be.true();
done();
}).catch(done);
@ -391,67 +403,67 @@ describe('Fixtures', function () {
describe('06-clean-broken-tags', function () {
it('tries to clean broken tags correctly', function (done) {
var logStub = sandbox.stub(),
tagObjStub = {
var tagObjStub = {
get: sandbox.stub().returns(',hello'),
save: sandbox.stub().returns(Promise.resolve)
},
tagCollStub = {each: sandbox.stub().callsArgWith(0, tagObjStub)},
tagAllStub = sandbox.stub(models.Tag, 'findAll').returns(Promise.resolve(tagCollStub));
fixtures004[5]({}, logStub).then(function () {
fixtures004[5]({}, loggerStub).then(function () {
tagAllStub.calledOnce.should.be.true();
tagCollStub.each.calledOnce.should.be.true();
tagObjStub.get.calledOnce.should.be.true();
tagObjStub.get.calledWith('name').should.be.true();
tagObjStub.save.calledOnce.should.be.true();
tagObjStub.save.calledWith({name: 'hello'}).should.be.true();
logStub.calledOnce.should.be.true();
sinon.assert.callOrder(tagAllStub, tagCollStub.each, tagObjStub.get, tagObjStub.save, logStub);
loggerStub.info.calledOnce.should.be.true();
loggerStub.warn.called.should.be.false();
sinon.assert.callOrder(tagAllStub, tagCollStub.each, tagObjStub.get, tagObjStub.save, loggerStub.info);
done();
}).catch(done);
});
it('tries can handle tags which end up empty', function (done) {
var logStub = sandbox.stub(),
tagObjStub = {
var tagObjStub = {
get: sandbox.stub().returns(','),
save: sandbox.stub().returns(Promise.resolve)
},
tagCollStub = {each: sandbox.stub().callsArgWith(0, tagObjStub)},
tagAllStub = sandbox.stub(models.Tag, 'findAll').returns(Promise.resolve(tagCollStub));
fixtures004[5]({}, logStub).then(function () {
fixtures004[5]({}, loggerStub).then(function () {
tagAllStub.calledOnce.should.be.true();
tagCollStub.each.calledOnce.should.be.true();
tagObjStub.get.calledOnce.should.be.true();
tagObjStub.get.calledWith('name').should.be.true();
tagObjStub.save.calledOnce.should.be.true();
tagObjStub.save.calledWith({name: 'tag'}).should.be.true();
logStub.calledOnce.should.be.true();
sinon.assert.callOrder(tagAllStub, tagCollStub.each, tagObjStub.get, tagObjStub.save, logStub);
loggerStub.info.calledOnce.should.be.true();
loggerStub.warn.called.should.be.false();
sinon.assert.callOrder(tagAllStub, tagCollStub.each, tagObjStub.get, tagObjStub.save, loggerStub.info);
done();
}).catch(done);
});
it('does not change tags if not necessary', function (done) {
var logStub = sandbox.stub(),
tagObjStub = {
var tagObjStub = {
get: sandbox.stub().returns('hello'),
save: sandbox.stub().returns(Promise.resolve)
},
tagCollStub = {each: sandbox.stub().callsArgWith(0, tagObjStub)},
tagAllStub = sandbox.stub(models.Tag, 'findAll').returns(Promise.resolve(tagCollStub));
fixtures004[5]({}, logStub).then(function () {
fixtures004[5]({}, loggerStub).then(function () {
tagAllStub.calledOnce.should.be.true();
tagCollStub.each.calledOnce.should.be.true();
tagObjStub.get.calledOnce.should.be.true();
tagObjStub.get.calledWith('name').should.be.true();
tagObjStub.save.called.should.be.false();
logStub.calledOnce.should.be.false();
loggerStub.info.called.should.be.false();
loggerStub.warn.calledOnce.should.be.true();
sinon.assert.callOrder(tagAllStub, tagCollStub.each, tagObjStub.get);
done();
@ -465,29 +477,30 @@ describe('Fixtures', function () {
load: sandbox.stub()
},
postCollStub = {mapThen: sandbox.stub().callsArgWith(0, postObjStub).returns([])},
postAllStub = sandbox.stub(models.Post, 'findAll').returns(Promise.resolve(postCollStub)),
logStub = sandbox.stub();
postAllStub = sandbox.stub(models.Post, 'findAll').returns(Promise.resolve(postCollStub));
fixtures004[6]({}, logStub).then(function () {
fixtures004[6]({}, loggerStub).then(function () {
postAllStub.calledOnce.should.be.true();
postCollStub.mapThen.calledOnce.should.be.true();
postObjStub.load.calledOnce.should.be.true();
postObjStub.load.calledWith(['tags']).should.be.true();
logStub.calledOnce.should.be.true();
sinon.assert.callOrder(logStub, postAllStub, postCollStub.mapThen, postObjStub.load);
loggerStub.info.calledOnce.should.be.true();
// gets called because we're stubbing to return an empty array
loggerStub.warn.calledOnce.should.be.true();
sinon.assert.callOrder(loggerStub.info, postAllStub, postCollStub.mapThen, postObjStub.load);
done();
}).catch(done);
});
it('returns early, if no posts are found', function (done) {
var postAllStub = sandbox.stub(models.Post, 'findAll').returns(Promise.resolve()),
logStub = sandbox.stub();
var postAllStub = sandbox.stub(models.Post, 'findAll').returns(Promise.resolve());
fixtures004[6]({}, logStub).then(function () {
logStub.calledOnce.should.be.true();
fixtures004[6]({}, loggerStub).then(function () {
loggerStub.info.calledOnce.should.be.true();
loggerStub.warn.calledOnce.should.be.true();
postAllStub.calledOnce.should.be.true();
sinon.assert.callOrder(logStub, postAllStub);
sinon.assert.callOrder(loggerStub.info, postAllStub, loggerStub.warn);
done();
}).catch(done);
@ -502,19 +515,19 @@ describe('Fixtures', function () {
},
// By returning from mapThen, we can skip doing tag.load in this test
postCollStub = {mapThen: sandbox.stub().returns(postArrayReduceStub)},
postAllStub = sandbox.stub(models.Post, 'findAll').returns(Promise.resolve(postCollStub)),
logStub = sandbox.stub();
postAllStub = sandbox.stub(models.Post, 'findAll').returns(Promise.resolve(postCollStub));
fixtures004[6]({}, logStub).then(function () {
logStub.calledThrice.should.be.true();
fixtures004[6]({}, loggerStub).then(function () {
loggerStub.info.calledThrice.should.be.true();
loggerStub.warn.called.should.be.false();
postAllStub.calledOnce.should.be.true();
postCollStub.mapThen.calledOnce.should.be.true();
postArrayReduceStub.reduce.calledOnce.should.be.true();
tagOpStub.calledOnce.should.be.true();
sinon.assert.callOrder(
logStub, postAllStub, postCollStub.mapThen, postArrayReduceStub.reduce,
logStub, tagOpStub, logStub
loggerStub.info, postAllStub, postCollStub.mapThen, postArrayReduceStub.reduce,
loggerStub.info, tagOpStub, loggerStub.info
);
done();
@ -531,11 +544,11 @@ describe('Fixtures', function () {
},
// By returning from mapThen, we can skip doing tag.load in this test
postCollStub = {mapThen: sandbox.stub().returns(postArrayReduceStub)},
postAllStub = sandbox.stub(models.Post, 'findAll').returns(Promise.resolve(postCollStub)),
logStub = sandbox.stub();
postAllStub = sandbox.stub(models.Post, 'findAll').returns(Promise.resolve(postCollStub));
fixtures004[6]({}, logStub).then(function () {
logStub.calledThrice.should.be.true();
fixtures004[6]({}, loggerStub).then(function () {
loggerStub.info.calledThrice.should.be.true();
loggerStub.warn.called.should.be.false();
postAllStub.calledOnce.should.be.true();
postCollStub.mapThen.calledOnce.should.be.true();
postArrayReduceStub.reduce.calledOnce.should.be.true();
@ -543,8 +556,8 @@ describe('Fixtures', function () {
tagOp2Stub.calledOnce.should.be.true();
sinon.assert.callOrder(
logStub, postAllStub, postCollStub.mapThen, postArrayReduceStub.reduce,
logStub, tagOp1Stub, tagOp2Stub, logStub
loggerStub.info, postAllStub, postCollStub.mapThen, postArrayReduceStub.reduce,
loggerStub.info, tagOp1Stub, tagOp2Stub, loggerStub.info
);
done();
@ -564,18 +577,19 @@ describe('Fixtures', function () {
},
// By returning from mapThen, we can skip doing tag.load in this test
postCollStub = {mapThen: sandbox.stub().returns([postObjStub])},
postAllStub = sandbox.stub(models.Post, 'findAll').returns(Promise.resolve(postCollStub)),
logStub = sandbox.stub();
postAllStub = sandbox.stub(models.Post, 'findAll').returns(Promise.resolve(postCollStub));
fixtures004[6]({}, logStub).then(function () {
logStub.calledOnce.should.be.true();
fixtures004[6]({}, loggerStub).then(function () {
loggerStub.info.calledOnce.should.be.true();
loggerStub.warn.calledOnce.should.be.true();
postAllStub.calledOnce.should.be.true();
postCollStub.mapThen.calledOnce.should.be.true();
postObjStub.related.calledOnce.should.be.true();
tagObjStub.pivot.get.calledOnce.should.be.true();
tagObjStub.pivot.get.calledWith('sort_order').should.be.true();
sinon.assert.callOrder(
logStub, postAllStub, postCollStub.mapThen, postObjStub.related, tagObjStub.pivot.get
loggerStub.info, postAllStub, postCollStub.mapThen, postObjStub.related,
tagObjStub.pivot.get, loggerStub.warn
);
done();
@ -599,11 +613,11 @@ describe('Fixtures', function () {
},
// By returning from mapThen, we can skip doing tag.load in this test
postCollStub = {mapThen: sandbox.stub().returns([postObjStub])},
postAllStub = sandbox.stub(models.Post, 'findAll').returns(Promise.resolve(postCollStub)),
logStub = sandbox.stub();
postAllStub = sandbox.stub(models.Post, 'findAll').returns(Promise.resolve(postCollStub));
fixtures004[6]({}, logStub).then(function () {
logStub.calledThrice.should.be.true();
fixtures004[6]({}, loggerStub).then(function () {
loggerStub.info.calledThrice.should.be.true();
loggerStub.warn.called.should.be.false();
postAllStub.calledOnce.should.be.true();
postCollStub.mapThen.calledOnce.should.be.true();
postObjStub.related.calledOnce.should.be.true();
@ -613,8 +627,8 @@ describe('Fixtures', function () {
postObjStub.tags.calledOnce.should.be.true();
postObjStub.updatePivot.calledOnce.should.be.true();
sinon.assert.callOrder(
logStub, postAllStub, postCollStub.mapThen, postObjStub.related, tagObjStub.pivot.get,
logStub, postObjStub.tags, postObjStub.updatePivot, logStub
loggerStub.info, postAllStub, postCollStub.mapThen, postObjStub.related, tagObjStub.pivot.get,
loggerStub.info, postObjStub.tags, postObjStub.updatePivot, loggerStub.info
);
done();
@ -638,11 +652,11 @@ describe('Fixtures', function () {
},
// By returning from mapThen, we can skip doing tag.load in this test
postCollStub = {mapThen: sandbox.stub().returns([postObjStub])},
postAllStub = sandbox.stub(models.Post, 'findAll').returns(Promise.resolve(postCollStub)),
logStub = sandbox.stub();
postAllStub = sandbox.stub(models.Post, 'findAll').returns(Promise.resolve(postCollStub));
fixtures004[6]({}, logStub).then(function () {
logStub.calledThrice.should.be.true();
fixtures004[6]({}, loggerStub).then(function () {
loggerStub.info.calledThrice.should.be.true();
loggerStub.warn.called.should.be.false();
postAllStub.calledOnce.should.be.true();
postCollStub.mapThen.calledOnce.should.be.true();
postObjStub.related.calledOnce.should.be.true();
@ -656,13 +670,13 @@ describe('Fixtures', function () {
postObjStub.updatePivot.thirdCall.args[0].should.eql({sort_order: 2});
sinon.assert.callOrder(
logStub, postAllStub, postCollStub.mapThen, postObjStub.related,
loggerStub.info, postAllStub, postCollStub.mapThen, postObjStub.related,
tagObjStub.pivot.get, tagObjStub.pivot.get, tagObjStub.pivot.get,
logStub,
loggerStub.info,
postObjStub.tags, postObjStub.updatePivot,
postObjStub.tags, postObjStub.updatePivot,
postObjStub.tags, postObjStub.updatePivot,
logStub
loggerStub.info
);
done();
@ -672,33 +686,35 @@ describe('Fixtures', function () {
describe('08-add-post-fixture', function () {
it('tries to add a new post fixture correctly', function (done) {
var logStub = sandbox.stub(),
postOneStub = sandbox.stub(models.Post, 'findOne').returns(Promise.resolve()),
var postOneStub = sandbox.stub(models.Post, 'findOne').returns(Promise.resolve()),
postAddStub = sandbox.stub(models.Post, 'add').returns(Promise.resolve());
fixtures004[7]({}, logStub).then(function () {
fixtures004[7]({}, loggerStub).then(function () {
postOneStub.calledOnce.should.be.true();
logStub.calledOnce.should.be.true();
loggerStub.info.calledOnce.should.be.true();
loggerStub.warn.called.should.be.false();
postAddStub.calledOnce.should.be.true();
sinon.assert.callOrder(postOneStub, logStub, postAddStub);
sinon.assert.callOrder(postOneStub, loggerStub.info, postAddStub);
done();
}).catch(done);
});
});
it('does not try to add new post fixture if it already exists', function (done) {
var logStub = sandbox.stub(),
postOneStub = sandbox.stub(models.Post, 'findOne').returns(Promise.resolve({})),
postAddStub = sandbox.stub(models.Post, 'add').returns(Promise.resolve());
it('does not try to add new post fixture if it already exists', function (done) {
var postOneStub = sandbox.stub(models.Post, 'findOne').returns(Promise.resolve({})),
postAddStub = sandbox.stub(models.Post, 'add').returns(Promise.resolve());
fixtures004[7]({}, logStub).then(function () {
postOneStub.calledOnce.should.be.true();
logStub.called.should.be.false();
postAddStub.called.should.be.false();
fixtures004[7]({}, loggerStub).then(function () {
postOneStub.calledOnce.should.be.true();
loggerStub.info.called.should.be.false();
loggerStub.warn.calledOnce.should.be.true();
postAddStub.called.should.be.false();
done();
}).catch(done);
sinon.assert.callOrder(postOneStub, loggerStub.warn);
done();
}).catch(done);
});
});
});
});
@ -708,8 +724,7 @@ describe('Fixtures', function () {
// This tests that all the models & relations get called correctly
it('should call all the fixture populations', function (done) {
// Stub all the model methods so that nothing happens
var logStub = sandbox.stub(),
postAddStub = sandbox.stub(models.Post, 'add').returns(Promise.resolve()),
var postAddStub = sandbox.stub(models.Post, 'add').returns(Promise.resolve()),
tagAddStub = sandbox.stub(models.Tag, 'add').returns(Promise.resolve()),
roleAddStub = sandbox.stub(models.Role, 'add').returns(Promise.resolve()),
clientAddStub = sandbox.stub(models.Client, 'add').returns(Promise.resolve()),
@ -726,8 +741,9 @@ describe('Fixtures', function () {
roleOneStub = sandbox.stub(models.Role, 'findOne').returns(Promise.resolve({id: 1})),
userAddStub = sandbox.stub(models.User, 'add').returns(Promise.resolve({}));
populate(logStub).then(function () {
logStub.called.should.be.true();
populate(loggerStub).then(function () {
loggerStub.info.calledTwice.should.be.true();
loggerStub.warn.called.should.be.false();
postAddStub.calledOnce.should.be.true();
tagAddStub.calledOnce.should.be.true();
@ -801,12 +817,12 @@ describe('Fixtures', function () {
describe('Create Owner', function () {
it('createOwner will add user if owner role is present', function (done) {
var createOwner = populate.__get__('createOwner'),
logStub = sandbox.stub(),
roleOneStub = sandbox.stub(models.Role, 'findOne').returns(Promise.resolve({id: 1})),
userAddStub = sandbox.stub(models.User, 'add').returns(Promise.resolve({}));
createOwner(logStub).then(function () {
logStub.called.should.be.true();
createOwner(loggerStub).then(function () {
loggerStub.info.called.should.be.true();
loggerStub.warn.called.should.be.false();
roleOneStub.calledOnce.should.be.true();
userAddStub.called.should.be.true();
@ -916,15 +932,14 @@ describe('Fixtures', function () {
describe('Ensure default settings', function () {
it('should call populate settings and provide messaging', function (done) {
var settingsStub = sandbox.stub(models.Settings, 'populateDefaults').returns(new Promise.resolve()),
logStub = sandbox.stub();
var settingsStub = sandbox.stub(models.Settings, 'populateDefaults').returns(new Promise.resolve());
ensureDefaultSettings(logStub).then(function () {
ensureDefaultSettings(loggerStub).then(function () {
settingsStub.calledOnce.should.be.true();
logStub.calledTwice.should.be.true();
loggerStub.info.calledOnce.should.be.true();
done();
});
}).catch(done);
});
});
});

View File

@ -27,57 +27,65 @@ var should = require('should'),
sandbox = sinon.sandbox.create();
// Check version integrity
// These tests exist to ensure that developers are not able to modify the database schema, or permissions fixtures
// without knowing that they also need to update the default database version,
// both of which are required for migrations to work properly.
describe('DB version integrity', function () {
// Only these variables should need updating
var currentDbVersion = '004',
currentSchemaHash = 'a195562bf4915e3f3f610f6d178aba01',
currentFixturesHash = '17d6aa36a6ba904adca90279eb929381';
// 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
it('should not change without fixing this test', function () {
var tablesNoValidation = _.cloneDeep(schema.tables),
schemaHash,
fixturesHash;
_.each(tablesNoValidation, function (table) {
return _.each(table, function (column, name) {
table[name] = _.omit(column, 'validations');
});
});
schemaHash = crypto.createHash('md5').update(JSON.stringify(tablesNoValidation)).digest('hex');
fixturesHash = crypto.createHash('md5').update(JSON.stringify(fixtures.fixtures)).digest('hex');
// Test!
defaultSettings.core.databaseVersion.defaultValue.should.eql(currentDbVersion);
schemaHash.should.eql(currentSchemaHash);
fixturesHash.should.eql(currentFixturesHash);
schema.versioning.canMigrateFromVersion.should.eql('003');
});
});
describe('Migrations', function () {
var loggerStub;
afterEach(function () {
sandbox.restore();
});
// Check version integrity
// These tests exist to ensure that developers are not able to modify the database schema, or permissions fixtures
// without knowing that they also need to update the default database version,
// both of which are required for migrations to work properly.
describe('DB version integrity', function () {
// Only these variables should need updating
var currentDbVersion = '004',
currentSchemaHash = 'a195562bf4915e3f3f610f6d178aba01',
currentFixturesHash = '17d6aa36a6ba904adca90279eb929381';
// 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
it('should not change without fixing this test', function () {
var tablesNoValidation = _.cloneDeep(schema.tables),
schemaHash,
fixturesHash;
_.each(tablesNoValidation, function (table) {
return _.each(table, function (column, name) {
table[name] = _.omit(column, 'validations');
});
});
schemaHash = crypto.createHash('md5').update(JSON.stringify(tablesNoValidation)).digest('hex');
fixturesHash = crypto.createHash('md5').update(JSON.stringify(fixtures.fixtures)).digest('hex');
// Test!
defaultSettings.core.databaseVersion.defaultValue.should.eql(currentDbVersion);
schemaHash.should.eql(currentSchemaHash);
fixturesHash.should.eql(currentFixturesHash);
schema.versioning.canMigrateFromVersion.should.eql('003');
});
beforeEach(function () {
loggerStub = {
info: sandbox.stub(),
warn: sandbox.stub()
};
});
describe('Backup', function () {
it('should create a backup JSON file', function (done) {
var exportStub = sandbox.stub(exporter, 'doExport').returns(new Promise.resolve()),
filenameStub = sandbox.stub(exporter, 'fileName').returns(new Promise.resolve('test')),
logStub = sandbox.stub(),
fsStub = sandbox.stub(fs, 'writeFile').yields();
migration.backupDatabase(logStub).then(function () {
migration.backupDatabase(loggerStub).then(function () {
exportStub.calledOnce.should.be.true();
filenameStub.calledOnce.should.be.true();
fsStub.calledOnce.should.be.true();
logStub.calledTwice.should.be.true();
loggerStub.info.calledTwice.should.be.true();
done();
}).catch(done);
@ -161,10 +169,9 @@ describe('Migrations', function () {
// Setup
var createStub = sandbox.stub(schema.commands, 'createTable').returns(new Promise.resolve()),
fixturesStub = sandbox.stub(fixtures, 'populate').returns(new Promise.resolve()),
settingsStub = sandbox.stub(fixtures, 'ensureDefaultSettings').returns(new Promise.resolve()),
logStub = sandbox.stub();
settingsStub = sandbox.stub(fixtures, 'ensureDefaultSettings').returns(new Promise.resolve());
populate(logStub).then(function (result) {
populate(loggerStub).then(function (result) {
should.not.exist(result);
createStub.called.should.be.true();
@ -175,6 +182,9 @@ describe('Migrations', function () {
fixturesStub.calledOnce.should.be.true();
settingsStub.calledOnce.should.be.true();
loggerStub.info.called.should.be.true();
loggerStub.warn.called.should.be.false();
done();
}).catch(done);
});
@ -183,10 +193,9 @@ describe('Migrations', function () {
// Setup
var createStub = sandbox.stub(schema.commands, 'createTable').returns(new Promise.resolve()),
fixturesStub = sandbox.stub(fixtures, 'populate').returns(new Promise.resolve()),
settingsStub = sandbox.stub(fixtures, 'ensureDefaultSettings').returns(new Promise.resolve()),
logStub = sandbox.stub();
settingsStub = sandbox.stub(fixtures, 'ensureDefaultSettings').returns(new Promise.resolve());
populate(logStub, true).then(function (result) {
populate(loggerStub, true).then(function (result) {
should.exist(result);
result.should.be.an.Array().with.lengthOf(schemaTables.length);
@ -198,6 +207,9 @@ describe('Migrations', function () {
fixturesStub.called.should.be.false();
settingsStub.called.should.be.false();
loggerStub.info.called.should.be.true();
loggerStub.warn.called.should.be.false();
done();
}).catch(done);
});
@ -205,7 +217,7 @@ describe('Migrations', function () {
describe('Update', function () {
describe('Update function', function () {
var reset, backupStub, settingsStub, fixturesStub, setDbStub, errorStub, logStub, versionsSpy;
var reset, backupStub, settingsStub, fixturesStub, setDbStub, errorStub, versionsSpy;
beforeEach(function () {
// Stubs
@ -214,8 +226,6 @@ describe('Migrations', function () {
fixturesStub = sandbox.stub(fixtures, 'update').returns(new Promise.resolve());
setDbStub = sandbox.stub(schema.versioning, 'setDatabaseVersion').returns(new Promise.resolve());
errorStub = sandbox.stub(schema.versioning, 'showCannotMigrateError').returns(new Promise.resolve());
logStub = sandbox.stub();
// Spys
versionsSpy = sandbox.spy(schema.versioning, 'getMigrationVersions');
@ -242,7 +252,7 @@ describe('Migrations', function () {
it('should attempt to run the pre & post update tasks correctly', function (done) {
// Execute
update('100', '102', logStub).then(function () {
update('100', '102', loggerStub).then(function () {
// Before the update, it does some tasks...
// It should not show an error for these versions
errorStub.called.should.be.false();
@ -254,7 +264,7 @@ describe('Migrations', function () {
// Now it's going to try to actually do the update...
updateStub.calledOnce.should.be.true();
updateStub.calledWith(['101', '102'], logStub).should.be.true();
updateStub.calledWith(['101', '102'], loggerStub).should.be.true();
// And now there are some final tasks to wrap up...
// First, the ensure default settings task
@ -264,8 +274,9 @@ describe('Migrations', function () {
// And finally, set the new DB version
setDbStub.calledOnce.should.be.true();
// Because we stubbed everything, logStub didn't get called
logStub.called.should.be.false();
// Because we stubbed everything, loggerStub didn't get called
loggerStub.info.called.should.be.false();
loggerStub.warn.called.should.be.false();
// Just to be sure, lets assert the call order
sinon.assert.callOrder(
@ -278,15 +289,16 @@ describe('Migrations', function () {
it('should throw error if versions are too old', function (done) {
// Execute
update('000', '002', logStub).then(function () {
update('000', '002', loggerStub).then(function () {
// It should show an error for these versions
errorStub.called.should.be.true();
// And so should not do the update...
updateStub.calledOnce.should.be.false();
// Because we stubbed everything, logStub didn't get called
logStub.called.should.be.false();
// Because we stubbed everything, loggerStub didn't get called
loggerStub.info.called.should.be.false();
loggerStub.warn.called.should.be.false();
done();
}).catch(done);
@ -297,7 +309,7 @@ describe('Migrations', function () {
process.env.FORCE_MIGRATION = true;
// Execute
update('005', '006', logStub).then(function () {
update('005', '006', loggerStub).then(function () {
// It should not show an error for these versions
errorStub.called.should.be.false();
@ -310,8 +322,9 @@ describe('Migrations', function () {
updateStub.calledOnce.should.be.true();
updateStub.calledWith(['004', '005', '006']).should.be.true();
// Because we stubbed everything, logStub didn't get called
logStub.called.should.be.false();
// Because we stubbed everything, loggerStub didn't get called
loggerStub.info.called.should.be.false();
loggerStub.warn.called.should.be.false();
// Restore
delete process.env.FORCE_MIGRATION;
@ -340,7 +353,6 @@ describe('Migrations', function () {
it('should call all the 004 database upgrades', function (done) {
// Setup
var logStub = sandbox.stub();
// stub has table, so that the next action won't happen
knexMock.schema.hasTable.withArgs('users').returns(new Promise.resolve(false));
knexMock.schema.hasTable.withArgs('posts_tags').returns(new Promise.resolve(false));
@ -348,9 +360,9 @@ describe('Migrations', function () {
knexMock.schema.hasTable.withArgs('client_trusted_domains').returns(new Promise.resolve(true));
// Execute
update('003', '004', logStub).then(function () {
update('003', '004', loggerStub).then(function () {
errorStub.called.should.be.false();
logStub.calledTwice.should.be.true();
loggerStub.info.calledTwice.should.be.true();
versionsSpy.calledOnce.should.be.true();
versionsSpy.calledWith('003', '004').should.be.true();
@ -368,13 +380,12 @@ describe('Migrations', function () {
describe('01-add-tour-column-to-users', function () {
it('does not try to add a new column if the column already exists', function (done) {
// Setup
var logStub = sandbox.stub(),
addColumnStub = sandbox.stub(schema.commands, 'addColumn');
var addColumnStub = sandbox.stub(schema.commands, 'addColumn');
knexMock.schema.hasTable.withArgs('users').returns(new Promise.resolve(true));
knexMock.schema.hasColumn.withArgs('users', 'tour').returns(new Promise.resolve(true));
// Execute
updates004[0](logStub).then(function () {
updates004[0](loggerStub).then(function () {
knexMock.schema.hasTable.calledOnce.should.be.true();
knexMock.schema.hasTable.calledWith('users').should.be.true();
@ -383,21 +394,21 @@ describe('Migrations', function () {
addColumnStub.called.should.be.false();
logStub.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 column if table is present but column is not', function (done) {
// Setup
var logStub = sandbox.stub(),
addColumnStub = sandbox.stub(schema.commands, 'addColumn');
var addColumnStub = sandbox.stub(schema.commands, 'addColumn');
knexMock.schema.hasTable.withArgs('users').returns(new Promise.resolve(true));
knexMock.schema.hasColumn.withArgs('users', 'tour').returns(new Promise.resolve(false));
// Execute
updates004[0](logStub).then(function () {
updates004[0](loggerStub).then(function () {
knexMock.schema.hasTable.calledOnce.should.be.true();
knexMock.schema.hasTable.calledWith('users').should.be.true();
@ -407,23 +418,23 @@ describe('Migrations', function () {
addColumnStub.calledOnce.should.be.true();
addColumnStub.calledWith('users', 'tour').should.be.true();
logStub.calledOnce.should.be.true();
loggerStub.info.calledOnce.should.be.true();
loggerStub.warn.called.should.be.false();
done();
});
}).catch(done);
});
});
describe('02-add-sortorder-column-to-poststags', function () {
it('does not try to add a new column if the column already exists', function (done) {
// Setup
var logStub = sandbox.stub(),
addColumnStub = sandbox.stub(schema.commands, 'addColumn');
var addColumnStub = sandbox.stub(schema.commands, 'addColumn');
knexMock.schema.hasTable.withArgs('posts_tags').returns(new Promise.resolve(true));
knexMock.schema.hasColumn.withArgs('posts_tags', 'sort_order').returns(new Promise.resolve(true));
// Execute
updates004[1](logStub).then(function () {
updates004[1](loggerStub).then(function () {
knexMock.schema.hasTable.calledOnce.should.be.true();
knexMock.schema.hasTable.calledWith('posts_tags').should.be.true();
@ -432,21 +443,21 @@ describe('Migrations', function () {
addColumnStub.called.should.be.false();
logStub.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 column if table is present but column is not', function (done) {
// Setup
var logStub = sandbox.stub(),
addColumnStub = sandbox.stub(schema.commands, 'addColumn');
var addColumnStub = sandbox.stub(schema.commands, 'addColumn');
knexMock.schema.hasTable.withArgs('posts_tags').returns(new Promise.resolve(true));
knexMock.schema.hasColumn.withArgs('posts_tags', 'sort_order').returns(new Promise.resolve(false));
// Execute
updates004[1](logStub).then(function () {
updates004[1](loggerStub).then(function () {
knexMock.schema.hasTable.calledOnce.should.be.true();
knexMock.schema.hasTable.calledWith('posts_tags').should.be.true();
@ -456,18 +467,18 @@ describe('Migrations', function () {
addColumnStub.calledOnce.should.be.true();
addColumnStub.calledWith('posts_tags', 'sort_order').should.be.true();
logStub.calledOnce.should.be.true();
loggerStub.info.calledOnce.should.be.true();
loggerStub.warn.called.should.be.false();
done();
});
}).catch(done);
});
});
describe('03-add-many-columns-to-clients', function () {
it('does not try to add new columns if the columns already exist', function (done) {
// Setup
var logStub = sandbox.stub(),
addColumnStub = sandbox.stub(schema.commands, 'addColumn');
var addColumnStub = sandbox.stub(schema.commands, 'addColumn');
knexMock.schema.hasTable.withArgs('clients').returns(new Promise.resolve(true));
knexMock.schema.hasColumn.withArgs('clients', 'redirection_uri').returns(new Promise.resolve(true));
knexMock.schema.hasColumn.withArgs('clients', 'logo').returns(new Promise.resolve(true));
@ -476,7 +487,7 @@ describe('Migrations', function () {
knexMock.schema.hasColumn.withArgs('clients', 'description').returns(new Promise.resolve(true));
// Execute
updates004[2](logStub).then(function () {
updates004[2](loggerStub).then(function () {
knexMock.schema.hasTable.calledOnce.should.be.true();
knexMock.schema.hasTable.calledWith('clients').should.be.true();
@ -489,16 +500,16 @@ describe('Migrations', function () {
addColumnStub.called.should.be.false();
logStub.called.should.be.false();
loggerStub.info.called.should.be.false();
loggerStub.warn.callCount.should.eql(5);
done();
});
}).catch(done);
});
it('tries to add new columns if table is present but columns are not', function (done) {
// Setup
var logStub = sandbox.stub(),
addColumnStub = sandbox.stub(schema.commands, 'addColumn');
var addColumnStub = sandbox.stub(schema.commands, 'addColumn');
knexMock.schema.hasTable.withArgs('clients').returns(new Promise.resolve(true));
knexMock.schema.hasColumn.withArgs('clients', 'redirection_uri').returns(new Promise.resolve(false));
knexMock.schema.hasColumn.withArgs('clients', 'logo').returns(new Promise.resolve(false));
@ -507,7 +518,7 @@ describe('Migrations', function () {
knexMock.schema.hasColumn.withArgs('clients', 'description').returns(new Promise.resolve(false));
// Execute
updates004[2](logStub).then(function () {
updates004[2](loggerStub).then(function () {
knexMock.schema.hasTable.calledOnce.should.be.true();
knexMock.schema.hasTable.calledWith('clients').should.be.true();
@ -525,16 +536,16 @@ describe('Migrations', function () {
addColumnStub.calledWith('clients', 'type').should.be.true();
addColumnStub.calledWith('clients', 'description').should.be.true();
logStub.callCount.should.eql(5);
loggerStub.info.callCount.should.eql(5);
loggerStub.warn.called.should.be.false();
done();
});
}).catch(done);
});
it('will only try to add columns that do not exist', function (done) {
// Setup
var logStub = sandbox.stub(),
addColumnStub = sandbox.stub(schema.commands, 'addColumn');
var addColumnStub = sandbox.stub(schema.commands, 'addColumn');
knexMock.schema.hasTable.withArgs('clients').returns(new Promise.resolve(true));
knexMock.schema.hasColumn.withArgs('clients', 'redirection_uri').returns(new Promise.resolve(true));
knexMock.schema.hasColumn.withArgs('clients', 'logo').returns(new Promise.resolve(false));
@ -543,7 +554,7 @@ describe('Migrations', function () {
knexMock.schema.hasColumn.withArgs('clients', 'description').returns(new Promise.resolve(true));
// Execute
updates004[2](logStub).then(function () {
updates004[2](loggerStub).then(function () {
knexMock.schema.hasTable.calledOnce.should.be.true();
knexMock.schema.hasTable.calledWith('clients').should.be.true();
@ -558,61 +569,61 @@ describe('Migrations', function () {
addColumnStub.calledWith('clients', 'logo').should.be.true();
addColumnStub.calledWith('clients', 'type').should.be.true();
logStub.callCount.should.eql(2);
loggerStub.info.callCount.should.eql(2);
loggerStub.warn.callCount.should.eql(3);
done();
});
}).catch(done);
});
});
describe('04-add-clienttrusteddomains-table', function () {
it('does not try to add a new table if the table already exists', function (done) {
// Setup
var logStub = sandbox.stub(),
createTableStub = sandbox.stub(schema.commands, 'createTable');
var createTableStub = sandbox.stub(schema.commands, 'createTable');
knexMock.schema.hasTable.withArgs('client_trusted_domains').returns(new Promise.resolve(true));
// Execute
updates004[3](logStub).then(function () {
updates004[3](loggerStub).then(function () {
knexMock.schema.hasTable.calledOnce.should.be.true();
knexMock.schema.hasTable.calledWith('client_trusted_domains').should.be.true();
createTableStub.called.should.be.false();
logStub.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
var logStub = sandbox.stub(),
createTableStub = sandbox.stub(schema.commands, 'createTable');
var createTableStub = sandbox.stub(schema.commands, 'createTable');
knexMock.schema.hasTable.withArgs('client_trusted_domains').returns(new Promise.resolve(false));
// Execute
updates004[3](logStub).then(function () {
updates004[3](loggerStub).then(function () {
knexMock.schema.hasTable.calledOnce.should.be.true();
knexMock.schema.hasTable.calledWith('client_trusted_domains').should.be.true();
createTableStub.calledOnce.should.be.true();
createTableStub.calledWith('client_trusted_domains').should.be.true();
logStub.calledOnce.should.be.true();
loggerStub.info.calledOnce.should.be.true();
loggerStub.warn.called.should.be.false();
done();
});
}).catch(done);
});
});
describe('05-drop-unique-on-clients-secret', function () {
it('does not try to drop unique if the table does not exist', function (done) {
// Setup
var logStub = sandbox.stub(),
getIndexesStub = sandbox.stub(schema.commands, 'getIndexes'),
var getIndexesStub = sandbox.stub(schema.commands, 'getIndexes'),
dropUniqueStub = sandbox.stub(schema.commands, 'dropUnique');
getIndexesStub.withArgs('clients').returns(new Promise.resolve(
@ -621,7 +632,7 @@ describe('Migrations', function () {
knexMock.schema.hasTable.withArgs('clients').returns(new Promise.resolve(false));
// Execute
updates004[4](logStub).then(function () {
updates004[4](loggerStub).then(function () {
knexMock.schema.hasTable.calledOnce.should.be.true();
knexMock.schema.hasTable.calledWith('clients').should.be.true();
@ -629,16 +640,16 @@ describe('Migrations', function () {
dropUniqueStub.called.should.be.false();
logStub.called.should.be.false();
loggerStub.info.called.should.be.false();
loggerStub.warn.calledOnce.should.be.true();
done();
});
}).catch(done);
});
it('does not try to drop unique if the index does not exist', function (done) {
// Setup
var logStub = sandbox.stub(),
getIndexesStub = sandbox.stub(schema.commands, 'getIndexes'),
var getIndexesStub = sandbox.stub(schema.commands, 'getIndexes'),
dropUniqueStub = sandbox.stub(schema.commands, 'dropUnique');
knexMock.schema.hasTable.withArgs('clients').returns(new Promise.resolve(true));
@ -648,7 +659,7 @@ describe('Migrations', function () {
);
// Execute
updates004[4](logStub).then(function () {
updates004[4](loggerStub).then(function () {
knexMock.schema.hasTable.calledOnce.should.be.true();
knexMock.schema.hasTable.calledWith('clients').should.be.true();
@ -657,16 +668,16 @@ describe('Migrations', function () {
dropUniqueStub.called.should.be.false();
logStub.called.should.be.false();
loggerStub.info.called.should.be.false();
loggerStub.warn.calledOnce.should.be.true();
done();
});
}).catch(done);
});
it('tries to add a drop unique if table and index both exist', function (done) {
// Setup
var logStub = sandbox.stub(),
getIndexesStub = sandbox.stub(schema.commands, 'getIndexes'),
var getIndexesStub = sandbox.stub(schema.commands, 'getIndexes'),
dropUniqueStub = sandbox.stub(schema.commands, 'dropUnique');
knexMock.schema.hasTable.withArgs('clients').returns(new Promise.resolve(true));
@ -676,7 +687,7 @@ describe('Migrations', function () {
);
// Execute
updates004[4](logStub).then(function () {
updates004[4](loggerStub).then(function () {
knexMock.schema.hasTable.calledOnce.should.be.true();
knexMock.schema.hasTable.calledWith('clients').should.be.true();
@ -686,10 +697,11 @@ describe('Migrations', function () {
dropUniqueStub.calledOnce.should.be.true();
dropUniqueStub.calledWith('clients', 'secret').should.be.true();
logStub.calledOnce.should.be.true();
loggerStub.info.calledOnce.should.be.true();
loggerStub.warn.called.should.be.false();
done();
});
}).catch(done);
});
});
});
@ -699,12 +711,12 @@ describe('Migrations', function () {
describe('Update Database Schema', function () {
it('should not do anything if there are no tasks', function (done) {
var updateDatabaseSchema = update.__get__('updateDatabaseSchema'),
getVersionTasksStub = sandbox.stub(schema.versioning, 'getUpdateDatabaseTasks').returns([]),
logStub = sandbox.stub();
getVersionTasksStub = sandbox.stub(schema.versioning, 'getUpdateDatabaseTasks').returns([]);
updateDatabaseSchema(['001'], logStub).then(function () {
updateDatabaseSchema(['001'], loggerStub).then(function () {
getVersionTasksStub.calledOnce.should.be.true();
logStub.called.should.be.false();
loggerStub.info.called.should.be.false();
loggerStub.warn.called.should.be.false();
done();
}).catch(done);
});
@ -713,14 +725,13 @@ describe('Migrations', function () {
var updateDatabaseSchema = update.__get__('updateDatabaseSchema'),
task1Stub = sandbox.stub().returns(new Promise.resolve()),
task2Stub = sandbox.stub().returns(new Promise.resolve()),
getVersionTasksStub = sandbox.stub(schema.versioning, 'getUpdateDatabaseTasks').returns([task1Stub, task2Stub]),
logStub = sandbox.stub();
getVersionTasksStub = sandbox.stub(schema.versioning, 'getUpdateDatabaseTasks').returns([task1Stub, task2Stub]);
updateDatabaseSchema(['001'], logStub).then(function () {
updateDatabaseSchema(['001'], loggerStub).then(function () {
getVersionTasksStub.calledOnce.should.be.true();
task1Stub.calledOnce.should.be.true();
task2Stub.calledOnce.should.be.true();
logStub.calledTwice.should.be.true();
loggerStub.info.calledTwice.should.be.true();
done();
}).catch(done);
@ -729,7 +740,7 @@ describe('Migrations', function () {
});
describe('Init', function () {
var defaultVersionStub, databaseVersionStub, logStub, errorStub, updateStub, populateStub, fixSecretStub,
var defaultVersionStub, databaseVersionStub, errorStub, updateStub, populateStub, fixSecretStub,
resetLog, resetUpdate, resetPopulate, resetFixSecret;
beforeEach(function () {
@ -739,9 +750,8 @@ describe('Migrations', function () {
updateStub = sandbox.stub();
populateStub = sandbox.stub();
fixSecretStub = sandbox.stub();
logStub = sandbox.stub();
resetLog = migration.__set__('logInfo', logStub);
resetLog = migration.__set__('logger', loggerStub);
resetUpdate = migration.__set__('update', updateStub);
resetPopulate = migration.__set__('populate', populateStub);
resetFixSecret = migration.__set__('fixClientSecret', fixSecretStub);
@ -763,10 +773,11 @@ describe('Migrations', function () {
migration.init().then(function () {
defaultVersionStub.calledOnce.should.be.true();
databaseVersionStub.calledOnce.should.be.true();
logStub.calledOnce.should.be.true();
loggerStub.info.calledOnce.should.be.true();
loggerStub.warn.called.should.be.false();
updateStub.calledOnce.should.be.true();
updateStub.calledWith('004', '005', logStub).should.be.true();
updateStub.calledWith('004', '005', loggerStub).should.be.true();
errorStub.called.should.be.false();
populateStub.called.should.be.false();
@ -785,10 +796,11 @@ describe('Migrations', function () {
migration.init().then(function () {
defaultVersionStub.calledOnce.should.be.true();
databaseVersionStub.calledOnce.should.be.true();
logStub.calledOnce.should.be.true();
loggerStub.info.calledOnce.should.be.true();
loggerStub.warn.called.should.be.false();
updateStub.calledOnce.should.be.true();
updateStub.calledWith('004', '010', logStub).should.be.true();
updateStub.calledWith('004', '010', loggerStub).should.be.true();
errorStub.called.should.be.false();
populateStub.called.should.be.false();
@ -807,7 +819,8 @@ describe('Migrations', function () {
migration.init().then(function () {
defaultVersionStub.calledOnce.should.be.true();
databaseVersionStub.calledOnce.should.be.true();
logStub.calledOnce.should.be.true();
loggerStub.info.calledOnce.should.be.true();
loggerStub.warn.called.should.be.false();
fixSecretStub.called.should.be.true();
@ -829,10 +842,11 @@ describe('Migrations', function () {
migration.init().then(function () {
defaultVersionStub.calledOnce.should.be.true();
databaseVersionStub.calledOnce.should.be.true();
logStub.calledOnce.should.be.true();
loggerStub.info.calledOnce.should.be.true();
loggerStub.warn.called.should.be.false();
updateStub.calledOnce.should.be.true();
updateStub.calledWith('004', '004', logStub).should.be.true();
updateStub.calledWith('004', '004', loggerStub).should.be.true();
errorStub.called.should.be.false();
populateStub.called.should.be.false();
@ -852,10 +866,11 @@ describe('Migrations', function () {
migration.init().then(function () {
defaultVersionStub.calledOnce.should.be.true();
databaseVersionStub.calledOnce.should.be.true();
logStub.calledOnce.should.be.true();
loggerStub.info.calledOnce.should.be.true();
loggerStub.warn.called.should.be.false();
populateStub.called.should.be.true();
populateStub.calledWith(logStub, false).should.be.true();
populateStub.calledWith(loggerStub, false).should.be.true();
errorStub.called.should.be.false();
updateStub.called.should.be.false();
@ -874,10 +889,11 @@ describe('Migrations', function () {
migration.init(true).then(function () {
defaultVersionStub.calledOnce.should.be.true();
databaseVersionStub.calledOnce.should.be.true();
logStub.calledOnce.should.be.true();
loggerStub.info.calledOnce.should.be.true();
loggerStub.warn.called.should.be.false();
populateStub.called.should.be.true();
populateStub.calledWith(logStub, true).should.be.true();
populateStub.calledWith(loggerStub, true).should.be.true();
errorStub.called.should.be.false();
updateStub.called.should.be.false();
@ -896,7 +912,8 @@ describe('Migrations', function () {
migration.init().then(function () {
defaultVersionStub.calledOnce.should.be.true();
databaseVersionStub.calledOnce.should.be.true();
logStub.calledOnce.should.be.false();
loggerStub.info.called.should.be.false();
loggerStub.warn.called.should.be.false();
errorStub.calledOnce.should.be.true();
populateStub.called.should.be.false();
@ -915,7 +932,8 @@ describe('Migrations', function () {
// Execute
migration.init().then(function () {
databaseVersionStub.calledOnce.should.be.true();
logStub.calledOnce.should.be.false();
loggerStub.info.called.should.be.false();
loggerStub.warn.called.should.be.false();
errorStub.calledOnce.should.be.true();
defaultVersionStub.calledOnce.should.be.false();
@ -928,15 +946,29 @@ describe('Migrations', function () {
});
});
describe('LogInfo', function () {
describe('Logger', function () {
it('should output an info message prefixed with "Migrations"', function () {
var logInfo = migration.__get__('logInfo'),
errorsStub = sandbox.stub(errors, 'logInfo');
var logger = migration.__get__('logger'),
errorsInfoStub = sandbox.stub(errors, 'logComponentInfo'),
errorsWarnStub = sandbox.stub(errors, 'logComponentWarn');
logInfo('Stuff');
logger.info('Stuff');
errorsStub.calledOnce.should.be.true();
errorsStub.calledWith('Migrations', 'Stuff').should.be.true();
errorsInfoStub.calledOnce.should.be.true();
errorsInfoStub.calledWith('Migrations', 'Stuff').should.be.true();
errorsWarnStub.called.should.be.false();
});
it('should output a warn message prefixed with "Skipped Migrations"', function () {
var logger = migration.__get__('logger'),
errorsInfoStub = sandbox.stub(errors, 'logComponentInfo'),
errorsWarnStub = sandbox.stub(errors, 'logComponentWarn');
logger.warn('Stuff');
errorsWarnStub.calledOnce.should.be.true();
errorsWarnStub.calledWith('Skipping Migrations', 'Stuff').should.be.true();
errorsInfoStub.called.should.be.false();
});
});
@ -957,7 +989,7 @@ describe('Migrations', function () {
clientForgeStub = sandbox.stub(models.Clients, 'forge').returns(queryStub);
clientEditStub = sandbox.stub(models.Client, 'edit');
done();
});
}).catch(done);
});
it('should do nothing if there are no incorrect secrets', function (done) {