From 32700a0e5aac787de0b56d272570e45498670fb4 Mon Sep 17 00:00:00 2001 From: Katharina Irrgang Date: Wed, 5 Oct 2016 20:57:32 +0200 Subject: [PATCH] =?UTF-8?q?=F0=9F=94=A5=20=20remove=20all=20migration=20fi?= =?UTF-8?q?les=20(#7498)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit refs #7489 - a simple PR to remove all the old migration files - remove related tests --- .../004/01-add-tour-column-to-users.js | 26 - .../02-add-sortorder-column-to-poststags.js | 26 - .../004/03-add-many-columns-to-clients.js | 29 - .../004/04-add-clienttrusteddomains-table.js | 17 - .../004/05-drop-unique-on-clients-secret.js | 26 - core/server/data/migration/004/index.js | 12 - .../005/01-drop-hidden-column-from-tags.js | 26 - .../02-add-visibility-column-to-key-tables.js | 29 - .../005/03-add-mobiledoc-column-to-posts.js | 26 - .../04-add-social-media-columns-to-users.js | 28 - .../migration/005/05-add-subscribers-table.js | 16 - core/server/data/migration/005/index.js | 12 - core/server/data/migration/006/index.js | 1 - .../008/01-add-amp-column-to-posts.js | 26 - core/server/data/migration/008/index.js | 4 - .../fixtures/004/01-move-jquery-with-alert.js | 57 - .../004/02-update-private-setting-type.js | 15 - .../004/03-update-password-setting-type.js | 14 - .../004/04-update-ghost-admin-client.js | 27 - .../004/05-add-ghost-frontend-client.js | 16 - .../fixtures/004/06-clean-broken-tags.js | 32 - .../fixtures/004/07-add-post-tag-order.js | 65 - .../fixtures/004/08-add-post-fixture.js | 31 - .../data/migration/fixtures/004/index.js | 25 - .../005/01-update-ghost-client-secrets.js | 26 - .../005/02-add-ghost-scheduler-client.js | 16 - .../fixtures/005/03-add-client-permissions.js | 31 - .../005/04-add-subscriber-permissions.js | 31 - .../data/migration/fixtures/005/index.js | 10 - .../006/01-transform-dates-into-utc.js | 211 --- .../data/migration/fixtures/006/index.js | 3 - .../fixtures/007/01-add-themes-permissions.js | 33 - .../data/migration/fixtures/007/index.js | 3 - .../fixtures/008/01-fix-sqlite-pg-format.js | 62 - .../data/migration/fixtures/008/index.js | 3 - core/test/integration/migration_spec.js | 57 - core/test/unit/migration_fixture_spec.js | 1427 ----------------- core/test/unit/migration_spec.js | 1317 --------------- core/test/unit/versioning_spec.js | 31 - 39 files changed, 3847 deletions(-) delete mode 100644 core/server/data/migration/004/01-add-tour-column-to-users.js delete mode 100644 core/server/data/migration/004/02-add-sortorder-column-to-poststags.js delete mode 100644 core/server/data/migration/004/03-add-many-columns-to-clients.js delete mode 100644 core/server/data/migration/004/04-add-clienttrusteddomains-table.js delete mode 100644 core/server/data/migration/004/05-drop-unique-on-clients-secret.js delete mode 100644 core/server/data/migration/004/index.js delete mode 100644 core/server/data/migration/005/01-drop-hidden-column-from-tags.js delete mode 100644 core/server/data/migration/005/02-add-visibility-column-to-key-tables.js delete mode 100644 core/server/data/migration/005/03-add-mobiledoc-column-to-posts.js delete mode 100644 core/server/data/migration/005/04-add-social-media-columns-to-users.js delete mode 100644 core/server/data/migration/005/05-add-subscribers-table.js delete mode 100644 core/server/data/migration/005/index.js delete mode 100644 core/server/data/migration/006/index.js delete mode 100644 core/server/data/migration/008/01-add-amp-column-to-posts.js delete mode 100644 core/server/data/migration/008/index.js delete mode 100644 core/server/data/migration/fixtures/004/01-move-jquery-with-alert.js delete mode 100644 core/server/data/migration/fixtures/004/02-update-private-setting-type.js delete mode 100644 core/server/data/migration/fixtures/004/03-update-password-setting-type.js delete mode 100644 core/server/data/migration/fixtures/004/04-update-ghost-admin-client.js delete mode 100644 core/server/data/migration/fixtures/004/05-add-ghost-frontend-client.js delete mode 100644 core/server/data/migration/fixtures/004/06-clean-broken-tags.js delete mode 100644 core/server/data/migration/fixtures/004/07-add-post-tag-order.js delete mode 100644 core/server/data/migration/fixtures/004/08-add-post-fixture.js delete mode 100644 core/server/data/migration/fixtures/004/index.js delete mode 100644 core/server/data/migration/fixtures/005/01-update-ghost-client-secrets.js delete mode 100644 core/server/data/migration/fixtures/005/02-add-ghost-scheduler-client.js delete mode 100644 core/server/data/migration/fixtures/005/03-add-client-permissions.js delete mode 100644 core/server/data/migration/fixtures/005/04-add-subscriber-permissions.js delete mode 100644 core/server/data/migration/fixtures/005/index.js delete mode 100644 core/server/data/migration/fixtures/006/01-transform-dates-into-utc.js delete mode 100644 core/server/data/migration/fixtures/006/index.js delete mode 100644 core/server/data/migration/fixtures/007/01-add-themes-permissions.js delete mode 100644 core/server/data/migration/fixtures/007/index.js delete mode 100644 core/server/data/migration/fixtures/008/01-fix-sqlite-pg-format.js delete mode 100644 core/server/data/migration/fixtures/008/index.js delete mode 100644 core/test/unit/migration_fixture_spec.js diff --git a/core/server/data/migration/004/01-add-tour-column-to-users.js b/core/server/data/migration/004/01-add-tour-column-to-users.js deleted file mode 100644 index 3e16671219..0000000000 --- a/core/server/data/migration/004/01-add-tour-column-to-users.js +++ /dev/null @@ -1,26 +0,0 @@ -var Promise = require('bluebird'), - commands = require('../../schema').commands, - table = 'users', - column = 'tour', - message = 'Adding column: ' + table + '.' + column; - -module.exports = function addTourColumnToUsers(options, logger) { - var transaction = options.transacting; - - return transaction.schema.hasTable(table) - .then(function (exists) { - if (!exists) { - return Promise.reject(new Error('Table does not exist!')); - } - - return transaction.schema.hasColumn(table, column); - }) - .then(function (exists) { - if (!exists) { - logger.info(message); - return commands.addColumn(table, column, transaction); - } else { - logger.warn(message); - } - }); -}; diff --git a/core/server/data/migration/004/02-add-sortorder-column-to-poststags.js b/core/server/data/migration/004/02-add-sortorder-column-to-poststags.js deleted file mode 100644 index 564192483f..0000000000 --- a/core/server/data/migration/004/02-add-sortorder-column-to-poststags.js +++ /dev/null @@ -1,26 +0,0 @@ -var Promise = require('bluebird'), - commands = require('../../schema').commands, - table = 'posts_tags', - column = 'sort_order', - message = 'Adding column: ' + table + '.' + column; - -module.exports = function addSortOrderColumnToPostsTags(options, logger) { - var transaction = options.transacting; - - return transaction.schema.hasTable(table) - .then(function (exists) { - if (!exists) { - return Promise.reject(new Error('Table does not exist!')); - } - - return transaction.schema.hasColumn(table, column); - }) - .then(function (exists) { - if (!exists) { - logger.info(message); - return commands.addColumn(table, column, transaction); - } else { - logger.warn(message); - } - }); -}; diff --git a/core/server/data/migration/004/03-add-many-columns-to-clients.js b/core/server/data/migration/004/03-add-many-columns-to-clients.js deleted file mode 100644 index 107e3b73fb..0000000000 --- a/core/server/data/migration/004/03-add-many-columns-to-clients.js +++ /dev/null @@ -1,29 +0,0 @@ -var Promise = require('bluebird'), - commands = require('../../schema').commands, - table = 'clients', - columns = ['redirection_uri', 'logo', 'status', 'type', 'description']; - -module.exports = function addManyColumnsToClients(options, logger) { - var transaction = options.transacting; - - return transaction.schema.hasTable(table) - .then(function (exists) { - if (!exists) { - return Promise.reject(new Error('Table does not exist!')); - } - - return Promise.mapSeries(columns, function (column) { - var message = 'Adding column: ' + table + '.' + column; - - return transaction.schema.hasColumn(table, column) - .then(function (exists) { - if (!exists) { - logger.info(message); - return commands.addColumn(table, column, transaction); - } else { - logger.warn(message); - } - }); - }); - }); -}; diff --git a/core/server/data/migration/004/04-add-clienttrusteddomains-table.js b/core/server/data/migration/004/04-add-clienttrusteddomains-table.js deleted file mode 100644 index 1167dc13fe..0000000000 --- a/core/server/data/migration/004/04-add-clienttrusteddomains-table.js +++ /dev/null @@ -1,17 +0,0 @@ -var commands = require('../../schema').commands, - table = 'client_trusted_domains', - message = 'Creating table: ' + table; - -module.exports = function addClientTrustedDomainsTable(options, logger) { - var transaction = options.transacting; - - return transaction.schema.hasTable(table) - .then(function (exists) { - if (!exists) { - logger.info(message); - return commands.createTable(table, transaction); - } else { - logger.warn(message); - } - }); -}; diff --git a/core/server/data/migration/004/05-drop-unique-on-clients-secret.js b/core/server/data/migration/004/05-drop-unique-on-clients-secret.js deleted file mode 100644 index 9329986902..0000000000 --- a/core/server/data/migration/004/05-drop-unique-on-clients-secret.js +++ /dev/null @@ -1,26 +0,0 @@ -var Promise = require('bluebird'), - commands = require('../../schema').commands, - table = 'clients', - column = 'secret', - message = 'Dropping unique on: ' + table + '.' + column; - -module.exports = function dropUniqueOnClientsSecret(options, logger) { - var transaction = options.transacting; - - return transaction.schema.hasTable(table) - .then(function (exists) { - if (!exists) { - return Promise.reject(new Error('Table does not exist!')); - } - - return commands.getIndexes(table, transaction); - }) - .then(function (indexes) { - if (indexes.indexOf(table + '_' + column + '_unique') > -1) { - logger.info(message); - return commands.dropUnique(table, column, transaction); - } else { - logger.warn(message); - } - }); -}; diff --git a/core/server/data/migration/004/index.js b/core/server/data/migration/004/index.js deleted file mode 100644 index 72970d5801..0000000000 --- a/core/server/data/migration/004/index.js +++ /dev/null @@ -1,12 +0,0 @@ -module.exports = [ - // Added tour column to users - require('./01-add-tour-column-to-users'), - // Added sort_order to posts_tags - require('./02-add-sortorder-column-to-poststags'), - // Added redirection_uri, logo, status, type & description columns to clients - require('./03-add-many-columns-to-clients'), - // Added client_trusted_domains table - require('./04-add-clienttrusteddomains-table'), - // Dropped unique index on client secret - require('./05-drop-unique-on-clients-secret') -]; diff --git a/core/server/data/migration/005/01-drop-hidden-column-from-tags.js b/core/server/data/migration/005/01-drop-hidden-column-from-tags.js deleted file mode 100644 index 3932ae48a0..0000000000 --- a/core/server/data/migration/005/01-drop-hidden-column-from-tags.js +++ /dev/null @@ -1,26 +0,0 @@ -var Promise = require('bluebird'), - commands = require('../../schema').commands, - table = 'tags', - column = 'hidden', - message = 'Removing column: ' + table + '.' + column; - -module.exports = function dropHiddenColumnFromTags(options, logger) { - var transaction = options.transacting; - - return transaction.schema.hasTable(table) - .then(function (exists) { - if (!exists) { - return Promise.reject(new Error('Table does not exist!')); - } - - return transaction.schema.hasColumn(table, column); - }) - .then(function (exists) { - if (exists) { - logger.info(message); - return commands.dropColumn(table, column, transaction); - } else { - logger.warn(message); - } - }); -}; diff --git a/core/server/data/migration/005/02-add-visibility-column-to-key-tables.js b/core/server/data/migration/005/02-add-visibility-column-to-key-tables.js deleted file mode 100644 index 8ea99183f5..0000000000 --- a/core/server/data/migration/005/02-add-visibility-column-to-key-tables.js +++ /dev/null @@ -1,29 +0,0 @@ -var Promise = require('bluebird'), - commands = require('../../schema').commands, - tables = ['posts', 'tags', 'users'], - column = 'visibility'; - -module.exports = function addVisibilityColumnToKeyTables(options, logger) { - var transaction = options.transacting; - - return Promise.mapSeries(tables, function (table) { - var message = 'Adding column: ' + table + '.' + column; - - return transaction.schema.hasTable(table) - .then(function (exists) { - if (!exists) { - return Promise.reject(new Error('Table does not exist!')); - } - - return transaction.schema.hasColumn(table, column); - }) - .then(function (exists) { - if (!exists) { - logger.info(message); - return commands.addColumn(table, column, transaction); - } else { - logger.warn(message); - } - }); - }); -}; diff --git a/core/server/data/migration/005/03-add-mobiledoc-column-to-posts.js b/core/server/data/migration/005/03-add-mobiledoc-column-to-posts.js deleted file mode 100644 index b6a6849da8..0000000000 --- a/core/server/data/migration/005/03-add-mobiledoc-column-to-posts.js +++ /dev/null @@ -1,26 +0,0 @@ -var Promise = require('bluebird'), - commands = require('../../schema').commands, - table = 'posts', - column = 'mobiledoc', - message = 'Adding column: ' + table + '.' + column; - -module.exports = function addMobiledocColumnToPosts(options, logger) { - var transaction = options.transacting; - - return transaction.schema.hasTable(table) - .then(function (exists) { - if (!exists) { - return Promise.reject(new Error('Table does not exist!')); - } - - return transaction.schema.hasColumn(table, column); - }) - .then(function (exists) { - if (!exists) { - logger.info(message); - return commands.addColumn(table, column, transaction); - } else { - logger.warn(message); - } - }); -}; diff --git a/core/server/data/migration/005/04-add-social-media-columns-to-users.js b/core/server/data/migration/005/04-add-social-media-columns-to-users.js deleted file mode 100644 index 849f5a9224..0000000000 --- a/core/server/data/migration/005/04-add-social-media-columns-to-users.js +++ /dev/null @@ -1,28 +0,0 @@ -var Promise = require('bluebird'), - commands = require('../../schema').commands, - table = 'users', - columns = ['facebook', 'twitter']; - -module.exports = function addSocialMediaColumnsToUsers(options, logger) { - var transaction = options.transacting; - - return transaction.schema.hasTable(table) - .then(function (exists) { - if (!exists) { - return Promise.reject(new Error('Table does not exist!')); - } - - return Promise.mapSeries(columns, function (column) { - var message = 'Adding column: ' + table + '.' + column; - - return transaction.schema.hasColumn(table, column).then(function (exists) { - if (!exists) { - logger.info(message); - return commands.addColumn(table, column, transaction); - } else { - logger.warn(message); - } - }); - }); - }); -}; diff --git a/core/server/data/migration/005/05-add-subscribers-table.js b/core/server/data/migration/005/05-add-subscribers-table.js deleted file mode 100644 index 31a85ca235..0000000000 --- a/core/server/data/migration/005/05-add-subscribers-table.js +++ /dev/null @@ -1,16 +0,0 @@ -var commands = require('../../schema').commands, - table = 'subscribers', - message = 'Creating table: ' + table; - -module.exports = function addSubscribersTable(options, logger) { - var transaction = options.transacting; - - return transaction.schema.hasTable(table).then(function (exists) { - if (!exists) { - logger.info(message); - return commands.createTable(table, transaction); - } else { - logger.warn(message); - } - }); -}; diff --git a/core/server/data/migration/005/index.js b/core/server/data/migration/005/index.js deleted file mode 100644 index 7fc04945dc..0000000000 --- a/core/server/data/migration/005/index.js +++ /dev/null @@ -1,12 +0,0 @@ -module.exports = [ - // Drop hidden column from tags table - require('./01-drop-hidden-column-from-tags'), - // Add visibility column to posts, tags, and users tables - 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 users - require('./04-add-social-media-columns-to-users'), - // Add subscribers table - require('./05-add-subscribers-table') -]; diff --git a/core/server/data/migration/006/index.js b/core/server/data/migration/006/index.js deleted file mode 100644 index e0a30c5dfa..0000000000 --- a/core/server/data/migration/006/index.js +++ /dev/null @@ -1 +0,0 @@ -module.exports = []; diff --git a/core/server/data/migration/008/01-add-amp-column-to-posts.js b/core/server/data/migration/008/01-add-amp-column-to-posts.js deleted file mode 100644 index 8ce293d1e1..0000000000 --- a/core/server/data/migration/008/01-add-amp-column-to-posts.js +++ /dev/null @@ -1,26 +0,0 @@ -var Promise = require('bluebird'), - commands = require('../../schema').commands, - table = 'posts', - column = 'amp', - message = 'Adding column: ' + table + '.' + column; - -module.exports = function addAmpColumnToPosts(options, logger) { - var transaction = options.transacting; - - return transaction.schema.hasTable(table) - .then(function (exists) { - if (!exists) { - return Promise.reject(new Error('Table does not exist!')); - } - - return transaction.schema.hasColumn(table, column); - }) - .then(function (exists) { - if (!exists) { - logger.info(message); - return commands.addColumn(table, column, transaction); - } else { - logger.warn(message); - } - }); -}; diff --git a/core/server/data/migration/008/index.js b/core/server/data/migration/008/index.js deleted file mode 100644 index 5c3de05757..0000000000 --- a/core/server/data/migration/008/index.js +++ /dev/null @@ -1,4 +0,0 @@ -module.exports = [ - // Add amp column to posts - require('./01-add-amp-column-to-posts') -]; diff --git a/core/server/data/migration/fixtures/004/01-move-jquery-with-alert.js b/core/server/data/migration/fixtures/004/01-move-jquery-with-alert.js deleted file mode 100644 index b121b66e0b..0000000000 --- a/core/server/data/migration/fixtures/004/01-move-jquery-with-alert.js +++ /dev/null @@ -1,57 +0,0 @@ -// Moves jQuery inclusion to code injection via ghost_foot -var _ = require('lodash'), - Promise = require('bluebird'), - serverPath = '../../../../', - config = require(serverPath + 'config'), - models = require(serverPath + 'models'), - notifications = require(serverPath + 'api/notifications'), - i18n = require(serverPath + 'i18n'), - - // These messages are shown in the admin UI, not the console, and should therefore be translated - jquery = [ - i18n.t('notices.data.fixtures.canSafelyDelete'), - '\n\n' - ], - privacyMessage = [ - i18n.t('notices.data.fixtures.jQueryRemoved'), - i18n.t('notices.data.fixtures.canBeChanged') - ], - - message = 'Adding jQuery link to ghost_foot'; - -module.exports = function moveJQuery(options, logger) { - var value; - - return models.Settings.findOne('ghost_foot', options) - .then(function (setting) { - if (setting) { - value = setting.get('value'); - - // Only add jQuery if it's not already in there - if (value.indexOf(jquery.join('')) === -1) { - logger.info(message); - value = jquery.join('') + value; - - return models.Settings.edit({key: 'ghost_foot', value: value}, options); - } else { - logger.warn(message); - } - } else { - logger.warn(message); - } - }) - .then(function () { - if (_.isEmpty(config.get('privacy'))) { - return Promise.resolve(); - } - - logger.info(privacyMessage.join(' ').replace(/<\/?strong>/g, '')); - - return notifications.add({ - notifications: [{ - type: 'info', - message: privacyMessage.join(' ') - }] - }, options); - }); -}; diff --git a/core/server/data/migration/fixtures/004/02-update-private-setting-type.js b/core/server/data/migration/fixtures/004/02-update-private-setting-type.js deleted file mode 100644 index 38d6705d97..0000000000 --- a/core/server/data/migration/fixtures/004/02-update-private-setting-type.js +++ /dev/null @@ -1,15 +0,0 @@ -// Update the `isPrivate` setting, so that it has a type of `private` rather than `blog` -var models = require('../../../../models'), - - message = 'Update isPrivate setting'; - -module.exports = function updatePrivateSetting(options, logger) { - return models.Settings.findOne('isPrivate', options).then(function (setting) { - if (setting && setting.get('type') !== 'private') { - logger.info(message); - return models.Settings.edit({key: 'isPrivate', type: 'private'}, options); - } else { - logger.warn(message); - } - }); -}; diff --git a/core/server/data/migration/fixtures/004/03-update-password-setting-type.js b/core/server/data/migration/fixtures/004/03-update-password-setting-type.js deleted file mode 100644 index 9f374f2382..0000000000 --- a/core/server/data/migration/fixtures/004/03-update-password-setting-type.js +++ /dev/null @@ -1,14 +0,0 @@ -// Update the `password` setting, so that it has a type of `private` rather than `blog` -var models = require('../../../../models'), - message = 'Update password setting'; - -module.exports = function updatePasswordSetting(options, logger) { - return models.Settings.findOne('password', options).then(function (setting) { - if (setting && setting.get('type') !== 'private') { - logger.info(message); - return models.Settings.edit({key: 'password', type: 'private'}, options); - } else { - logger.warn(message); - } - }); -}; diff --git a/core/server/data/migration/fixtures/004/04-update-ghost-admin-client.js b/core/server/data/migration/fixtures/004/04-update-ghost-admin-client.js deleted file mode 100644 index 67ce681c25..0000000000 --- a/core/server/data/migration/fixtures/004/04-update-ghost-admin-client.js +++ /dev/null @@ -1,27 +0,0 @@ -// Update the `ghost-admin` client so that it has a proper secret -var _ = require('lodash'), - Promise = require('bluebird'), - crypto = require('crypto'), - models = require('../../../../models'), - adminClient = require('../utils').findModelFixtureEntry('Client', {slug: 'ghost-admin'}), - message = 'Update ghost-admin client fixture'; - -module.exports = function updateGhostAdminClient(options, logger) { - // ghost-admin should already exist from 003 version - return models.Client.findOne({slug: adminClient.slug}, options) - .then(function (client) { - if (!client) { - return Promise.reject(new Error('Admin client does not exist!')); - } - - if (client.get('secret') === 'not_available' || client.get('status') !== 'enabled') { - logger.info(message); - return models.Client.edit( - _.extend({}, adminClient, {secret: crypto.randomBytes(6).toString('hex')}), - _.extend({}, options, {id: client.id}) - ); - } else { - logger.warn(message); - } - }); -}; diff --git a/core/server/data/migration/fixtures/004/05-add-ghost-frontend-client.js b/core/server/data/migration/fixtures/004/05-add-ghost-frontend-client.js deleted file mode 100644 index 4ab7025d02..0000000000 --- a/core/server/data/migration/fixtures/004/05-add-ghost-frontend-client.js +++ /dev/null @@ -1,16 +0,0 @@ -// Create a new `ghost-frontend` client for use in themes -var models = require('../../../../models'), - frontendClient = require('../utils').findModelFixtureEntry('Client', {slug: 'ghost-frontend'}), - message = 'Add ghost-frontend client fixture'; - -module.exports = function addGhostFrontendClient(options, logger) { - return models.Client.findOne({slug: frontendClient.slug}, options) - .then(function (client) { - if (!client) { - logger.info(message); - return models.Client.add(frontendClient, options); - } else { - logger.warn(message); - } - }); -}; diff --git a/core/server/data/migration/fixtures/004/06-clean-broken-tags.js b/core/server/data/migration/fixtures/004/06-clean-broken-tags.js deleted file mode 100644 index 741c28a242..0000000000 --- a/core/server/data/migration/fixtures/004/06-clean-broken-tags.js +++ /dev/null @@ -1,32 +0,0 @@ -// Clean tags which start with commas, the only illegal char in tags -var models = require('../../../../models'), - Promise = require('bluebird'), - message = 'Cleaning malformed tags'; - -module.exports = function cleanBrokenTags(options, logger) { - return models.Tag.findAll(options).then(function (tags) { - var tagOps = []; - - if (tags) { - tags.each(function (tag) { - var name = tag.get('name'), - updated = name.replace(/^(,+)/, '').trim(); - - // If we've ended up with an empty string, default to just 'tag' - updated = updated === '' ? 'tag' : updated; - - if (name !== updated) { - tagOps.push(tag.save({name: updated}, options)); - } - }); - if (tagOps.length > 0) { - logger.info(message + '(' + tagOps.length + ')'); - return Promise.all(tagOps); - } else { - logger.warn(message); - } - } else { - logger.warn(message); - } - }); -}; diff --git a/core/server/data/migration/fixtures/004/07-add-post-tag-order.js b/core/server/data/migration/fixtures/004/07-add-post-tag-order.js deleted file mode 100644 index 1b8d73b244..0000000000 --- a/core/server/data/migration/fixtures/004/07-add-post-tag-order.js +++ /dev/null @@ -1,65 +0,0 @@ -// Add a new order value to posts_tags based on the existing info -var models = require('../../../../models'), - _ = require('lodash'), - sequence = require('../../../../utils/sequence'), - migrationHasRunFlag, - modelOptions; - -function loadTagsForEachPost(posts) { - if (!posts) { - return []; - } - - return posts.mapThen(function loadTagsForPost(post) { - return post.load(['tags'], modelOptions); - }); -} - -function updatePostTagsSortOrder(post, tagId, order) { - var sortOrder = order; - return function doUpdatePivot() { - return post.tags().updatePivot( - {sort_order: sortOrder}, _.extend({}, modelOptions, {query: {where: {tag_id: tagId}}}) - ); - }; -} - -function buildTagOpsArray(tagOps, post) { - var order = 0; - - return post.related('tags').reduce(function processTag(tagOps, tag) { - if (tag.pivot.get('sort_order') > 0) { - // if any entry in the posts_tags table has already run, we shouldn't run this again - migrationHasRunFlag = true; - } - - tagOps.push(updatePostTagsSortOrder(post, tag.id, order)); - order += 1; - - return tagOps; - }, tagOps); -} - -function processPostsArray(postsArray) { - return postsArray.reduce(buildTagOpsArray, []); -} - -module.exports = function addPostTagOrder(options, logger) { - modelOptions = options; - migrationHasRunFlag = false; - - 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) { - logger.info('Updating order on ' + tagOps.length + ' tag relationships (could take a while)...'); - return sequence(tagOps).then(function () { - logger.info('Tag order successfully updated'); - }); - } else { - logger.warn('Updating order on tag relationships'); - } - }); -}; diff --git a/core/server/data/migration/fixtures/004/08-add-post-fixture.js b/core/server/data/migration/fixtures/004/08-add-post-fixture.js deleted file mode 100644 index dae463c09a..0000000000 --- a/core/server/data/migration/fixtures/004/08-add-post-fixture.js +++ /dev/null @@ -1,31 +0,0 @@ -// 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', - markdown: 'You\'ve just upgraded to the latest version of Ghost and we\'ve made a few changes that you should probably know about!\n\n## Woah, why does everything look different?\n\nAfter two years and hundreds of thousands of users, we learned a great deal about what was (and wasn\'t) working in the old Ghost admin user interface. What you\'re looking at is Ghost\'s first major UI refresh, with a strong focus on being more usable and robust all round.\n\n![New Design](https://ghost.org/images/zelda.png)\n\nThe main navigation menu, previously located at the top of your screen, has now moved over to the left. This makes it way easier to work with on mobile devices, and has the added benefit of providing ample space for upcoming features!\n\n## Lost and found: Your old posts\n\nFrom talking to many of you we understand that finding old posts in the admin area was a real pain; so we\'ve added a new magical search bar which lets you quickly find posts for editing, without having to scroll endlessly. Take it for a spin!\n\n![Search](https://ghost.org/images/search.gif)\n\nQuestions? Comments? Send us a tweet [@TryGhost](https://twitter.com/tryghost)\n\nOh, and yes – you can safely delete this draft post!', - image: null, - featured: false, - page: false, - status: 'draft', - language: 'en_US', - meta_title: null, - meta_description: null - }, - message = 'Adding 0.7 upgrade post fixture'; - -module.exports = function addNewPostFixture(options, logger) { - return models.Post.findOne({slug: newPost.slug, status: 'all'}, options).then(function (post) { - if (!post) { - 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); - } - }); -}; diff --git a/core/server/data/migration/fixtures/004/index.js b/core/server/data/migration/fixtures/004/index.js deleted file mode 100644 index 8c1341139e..0000000000 --- a/core/server/data/migration/fixtures/004/index.js +++ /dev/null @@ -1,25 +0,0 @@ -module.exports = [ - // add jquery setting and privacy info - require('./01-move-jquery-with-alert'), - - // change `type` for protected blog `isPrivate` setting - require('./02-update-private-setting-type'), - - // change `type` for protected blog `password` setting - require('./03-update-password-setting-type'), - - // Update ghost-admin client fixture - require('./04-update-ghost-admin-client'), - - // add ghost-frontend client if missing - require('./05-add-ghost-frontend-client'), - - // clean up broken tags - require('./06-clean-broken-tags'), - - // Add post_tag order - require('./07-add-post-tag-order'), - - // Add a new draft post - require('./08-add-post-fixture') -]; diff --git a/core/server/data/migration/fixtures/005/01-update-ghost-client-secrets.js b/core/server/data/migration/fixtures/005/01-update-ghost-client-secrets.js deleted file mode 100644 index e4f1368cb1..0000000000 --- a/core/server/data/migration/fixtures/005/01-update-ghost-client-secrets.js +++ /dev/null @@ -1,26 +0,0 @@ -// Update the `ghost-*` clients so that they definitely have a proper secret -var models = require('../../../../models'), - _ = require('lodash'), - Promise = require('bluebird'), - crypto = require('crypto'), - - message = 'Updating client secret'; - -module.exports = function updateGhostClientsSecrets(options, logger) { - return models.Clients.forge().query('where', 'secret', '=', 'not_available').fetch(options).then(function (results) { - if (results.models.length === 0) { - logger.warn(message); - return; - } - - return Promise.map(results.models, function mapper(client) { - logger.info(message + ' (' + client.slug + ')'); - client.secret = crypto.randomBytes(6).toString('hex'); - - return models.Client.edit( - _.extend({}, client, {secret: crypto.randomBytes(6).toString('hex')}), - _.extend({}, options, {id: client.id}) - ); - }); - }); -}; diff --git a/core/server/data/migration/fixtures/005/02-add-ghost-scheduler-client.js b/core/server/data/migration/fixtures/005/02-add-ghost-scheduler-client.js deleted file mode 100644 index c30e200937..0000000000 --- a/core/server/data/migration/fixtures/005/02-add-ghost-scheduler-client.js +++ /dev/null @@ -1,16 +0,0 @@ -// Create a new `ghost-scheduler` client for use in themes -var models = require('../../../../models'), - - schedulerClient = require('../utils').findModelFixtureEntry('Client', {slug: 'ghost-scheduler'}), - message = 'Add ghost-scheduler client fixture'; - -module.exports = function addGhostFrontendClient(options, logger) { - return models.Client.findOne({slug: schedulerClient.slug}, options).then(function (client) { - if (!client) { - logger.info(message); - return models.Client.add(schedulerClient, options); - } else { - logger.warn(message); - } - }); -}; diff --git a/core/server/data/migration/fixtures/005/03-add-client-permissions.js b/core/server/data/migration/fixtures/005/03-add-client-permissions.js deleted file mode 100644 index bf6d8121fb..0000000000 --- a/core/server/data/migration/fixtures/005/03-add-client-permissions.js +++ /dev/null @@ -1,31 +0,0 @@ -// Update the permissions & permissions_roles tables to add entries for clients -var utils = require('../utils'), - resource = 'client'; - -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 addClientPermissions(options, logger) { - var modelToAdd = getPermissions(), - relationToAdd = getRelations(); - - return utils.addFixturesForModel(modelToAdd, options).then(function (result) { - printResult(logger, result, 'Adding permissions fixtures for ' + resource + 's'); - return utils.addFixturesForRelation(relationToAdd, options); - }).then(function (result) { - printResult(logger, result, 'Adding permissions_roles fixtures for ' + resource + 's'); - }); -}; diff --git a/core/server/data/migration/fixtures/005/04-add-subscriber-permissions.js b/core/server/data/migration/fixtures/005/04-add-subscriber-permissions.js deleted file mode 100644 index 89e2fda407..0000000000 --- a/core/server/data/migration/fixtures/005/04-add-subscriber-permissions.js +++ /dev/null @@ -1,31 +0,0 @@ -// 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, options).then(function (result) { - printResult(logger, result, 'Adding permissions fixtures for ' + resource + 's'); - return utils.addFixturesForRelation(relationToAdd, options); - }).then(function (result) { - printResult(logger, result, 'Adding permissions_roles fixtures for ' + resource + 's'); - }); -}; diff --git a/core/server/data/migration/fixtures/005/index.js b/core/server/data/migration/fixtures/005/index.js deleted file mode 100644 index eb89fb214e..0000000000 --- a/core/server/data/migration/fixtures/005/index.js +++ /dev/null @@ -1,10 +0,0 @@ -module.exports = [ - // add jquery setting and privacy info - require('./01-update-ghost-client-secrets'), - // add ghost-scheduler client - require('./02-add-ghost-scheduler-client'), - // add client permissions and permission_role relations - require('./03-add-client-permissions'), - // add subscriber permissions and permission_role relations - require('./04-add-subscriber-permissions') -]; diff --git a/core/server/data/migration/fixtures/006/01-transform-dates-into-utc.js b/core/server/data/migration/fixtures/006/01-transform-dates-into-utc.js deleted file mode 100644 index b37b4fc66b..0000000000 --- a/core/server/data/migration/fixtures/006/01-transform-dates-into-utc.js +++ /dev/null @@ -1,211 +0,0 @@ -var config = require('../../../../config'), - models = require(config.get('paths').corePath + '/server/models'), - api = require(config.get('paths').corePath + '/server/api'), - sequence = require(config.get('paths').corePath + '/server/utils/sequence'), - moment = require('moment'), - _ = require('lodash'), - Promise = require('bluebird'), - messagePrefix = 'Transforming dates to UTC: ', - settingsKey = '006/01', - _private = {}; - -_private.getTZOffset = function getTZOffset(date) { - return date.getTimezoneOffset(); -}; - -_private.getTZOffsetMax = function getTZOffsetMax() { - return Math.max(Math.abs(new Date('2015-07-01').getTimezoneOffset()), Math.abs(new Date('2015-01-01').getTimezoneOffset())); -}; - -_private.addOffset = function addOffset(date) { - if (_private.noOffset) { - return moment(date).toDate(); - } - - return moment(date).add(_private.getTZOffset(date), 'minutes').toDate(); -}; - -/** - * sqlite: stores UTC timestamps, but we will normalize the format to YYYY-MM-DD HH:mm:ss - */ -module.exports = function transformDatesIntoUTC(options, logger) { - var ServerTimezoneOffset = _private.getTZOffsetMax(), - settingsMigrations = null; - - // will ensure updated_at fields will not be updated, we take them from the original models - options.importing = true; - - return sequence([ - function databaseCheck() { - // we have to change the sqlite format, because it stores dates as integer - if (ServerTimezoneOffset === 0 && config.get('database').client === 'mysql') { - return Promise.reject(new Error('skip')); - } - - if (config.get('database').client === 'mysql') { - _private.noOffset = false; - } else if (config.get('database').client === 'sqlite3') { - _private.noOffset = true; - } - - logger.info(messagePrefix + '(could take a while)...'); - return Promise.resolve(); - }, - function checkIfMigrationAlreadyRan() { - return models.Settings.findOne({key: 'migrations'}, options) - .then(function (result) { - try { - settingsMigrations = JSON.parse(result.attributes.value) || {}; - } catch (err) { - return Promise.reject(err); - } - - // CASE: migration ran already - if (settingsMigrations.hasOwnProperty(settingsKey)) { - return Promise.reject(new Error('skip')); - } - - return Promise.resolve(); - }); - }, - function updatePosts() { - return models.Post.findAll(options).then(function (result) { - if (result.models.length === 0) { - logger.warn(messagePrefix + 'No Posts found'); - return; - } - - return Promise.mapSeries(result.models, function mapper(post) { - if (post.get('published_at')) { - post.set('published_at', _private.addOffset(post.get('published_at'))); - } - - if (post.get('updated_at')) { - post.set('updated_at', _private.addOffset(post.get('updated_at'))); - } - - post.set('created_at', _private.addOffset(post.get('created_at'))); - return models.Post.edit(post.toJSON(), _.merge({}, options, {id: post.get('id')})); - }).then(function () { - logger.info(messagePrefix + 'Updated datetime fields for Posts'); - }); - }); - }, - function updateUsers() { - return models.User.findAll(options).then(function (result) { - if (result.models.length === 0) { - logger.warn(messagePrefix + 'No Users found'); - return; - } - - return Promise.mapSeries(result.models, function mapper(user) { - if (user.get('last_login')) { - user.set('last_login', _private.addOffset(user.get('last_login'))); - } - - if (user.get('updated_at')) { - user.set('updated_at', _private.addOffset(user.get('updated_at'))); - } - - user.set('created_at', _private.addOffset(user.get('created_at'))); - return models.User.edit(user.toJSON(), _.merge({}, options, {id: user.get('id')})); - }).then(function () { - logger.info(messagePrefix + 'Updated datetime fields for Users'); - }); - }); - }, - function updateSubscribers() { - return models.Subscriber.findAll(options).then(function (result) { - if (result.models.length === 0) { - logger.warn(messagePrefix + 'No Subscribers found'); - return; - } - - return Promise.mapSeries(result.models, function mapper(subscriber) { - if (subscriber.get('unsubscribed_at')) { - subscriber.set('unsubscribed_at', _private.addOffset(subscriber.get('unsubscribed_at'))); - } - - if (subscriber.get('updated_at')) { - subscriber.set('updated_at', _private.addOffset(subscriber.get('updated_at'))); - } - - subscriber.set('created_at', _private.addOffset(subscriber.get('created_at'))); - return models.Subscriber.edit(subscriber.toJSON(), _.merge({}, options, {id: subscriber.get('id')})); - }).then(function () { - logger.info(messagePrefix + 'Updated datetime fields for Subscribers'); - }); - }); - }, - function updateSettings() { - return models.Settings.findAll(options).then(function (result) { - if (result.models.length === 0) { - logger.warn(messagePrefix + 'No Settings found'); - return; - } - - return Promise.mapSeries(result.models, function mapper(settings) { - // migrations was new created, so it already is in UTC - if (settings.get('key') === 'migrations') { - return Promise.resolve(); - } - - if (settings.get('updated_at')) { - settings.set('updated_at', _private.addOffset(settings.get('updated_at'))); - } - - settings.set('created_at', _private.addOffset(settings.get('created_at'))); - return models.Settings.edit(settings.toJSON(), _.merge({}, options, {id: settings.get('id')})); - }).then(function () { - logger.info(messagePrefix + 'Updated datetime fields for Settings'); - }); - }); - }, - function updateAllOtherModels() { - return Promise.mapSeries(['Role', 'Permission', 'Tag', 'App', 'AppSetting', 'AppField', 'Client'], function (model) { - return models[model].findAll(options).then(function (result) { - if (result.models.length === 0) { - logger.warn(messagePrefix + 'No {model} found'.replace('{model}', model)); - return; - } - - return Promise.mapSeries(result.models, function mapper(object) { - object.set('created_at', _private.addOffset(object.get('created_at'))); - - if (object.get('updated_at')) { - object.set('updated_at', _private.addOffset(object.get('updated_at'))); - } - - return models[model].edit(object.toJSON(), _.merge({}, options, {id: object.get('id')})); - }).then(function () { - logger.info(messagePrefix + 'Updated datetime fields for {model}'.replace('{model}', model)); - }); - }); - }); - }, - function setActiveTimezone() { - var timezone = config.get('forceTimezoneOnMigration') || moment.tz.guess(); - return models.Settings.edit({ - key: 'activeTimezone', - value: timezone - }, options); - }, - function addMigrationSettingsEntry() { - settingsMigrations[settingsKey] = moment().format(); - return models.Settings.edit({ - key: 'migrations', - value: JSON.stringify(settingsMigrations) - }, options); - }, - function updateSettingsCache() { - return api.settings.updateSettingsCache(null, options); - }] - ).catch(function (err) { - if (err.message === 'skip') { - logger.warn(messagePrefix + 'Your databases uses UTC datetimes, skip!'); - return Promise.resolve(); - } - - return Promise.reject(err); - }); -}; diff --git a/core/server/data/migration/fixtures/006/index.js b/core/server/data/migration/fixtures/006/index.js deleted file mode 100644 index 52b386f2c1..0000000000 --- a/core/server/data/migration/fixtures/006/index.js +++ /dev/null @@ -1,3 +0,0 @@ -module.exports = [ - require('./01-transform-dates-into-utc') -]; diff --git a/core/server/data/migration/fixtures/007/01-add-themes-permissions.js b/core/server/data/migration/fixtures/007/01-add-themes-permissions.js deleted file mode 100644 index 9d9df659e2..0000000000 --- a/core/server/data/migration/fixtures/007/01-add-themes-permissions.js +++ /dev/null @@ -1,33 +0,0 @@ -var utils = require('../utils'), - permissions = require('../../../../permissions'), - resource = 'theme'; - -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 addThemePermissions(options, logger) { - var modelToAdd = getPermissions(), - relationToAdd = getRelations(); - - return utils.addFixturesForModel(modelToAdd, options).then(function (result) { - printResult(logger, result, 'Adding permissions fixtures for ' + resource + 's'); - return utils.addFixturesForRelation(relationToAdd, options); - }).then(function (result) { - printResult(logger, result, 'Adding permissions_roles fixtures for ' + resource + 's'); - }).then(function () { - return permissions.init(options); - }); -}; diff --git a/core/server/data/migration/fixtures/007/index.js b/core/server/data/migration/fixtures/007/index.js deleted file mode 100644 index b75de826f6..0000000000 --- a/core/server/data/migration/fixtures/007/index.js +++ /dev/null @@ -1,3 +0,0 @@ -module.exports = [ - require('./01-add-themes-permissions') -]; diff --git a/core/server/data/migration/fixtures/008/01-fix-sqlite-pg-format.js b/core/server/data/migration/fixtures/008/01-fix-sqlite-pg-format.js deleted file mode 100644 index ba77e5d9d2..0000000000 --- a/core/server/data/migration/fixtures/008/01-fix-sqlite-pg-format.js +++ /dev/null @@ -1,62 +0,0 @@ -var config = require('../../../../config'), - _ = require('lodash'), - models = require(config.get('paths').corePath + '/server/models'), - transfomDatesIntoUTC = require(config.get('paths').corePath + '/server/data/migration/fixtures/006/01-transform-dates-into-utc'), - Promise = require('bluebird'), - messagePrefix = 'Fix sqlite format: ', - _private = {}; - -_private.rerunDateMigration = function rerunDateMigration(options, logger) { - var settingsMigrations, settingsKey = '006/01'; - - return models.Settings.findOne({key: 'migrations'}, options) - .then(function removeMigrationSettings(result) { - try { - settingsMigrations = JSON.parse(result.attributes.value) || {}; - } catch (err) { - return Promise.reject(err); - } - - // CASE: migration ran already - if (settingsMigrations.hasOwnProperty(settingsKey)) { - delete settingsMigrations[settingsKey]; - - return models.Settings.edit({ - key: 'migrations', - value: JSON.stringify(settingsMigrations) - }, options); - } - }) - .then(function () { - return transfomDatesIntoUTC(options, logger); - }); -}; - -/** - * this migration script is a very special one for people who run their server in UTC and use sqlite3 - * 006/01-transform-dates-into-utc had a bug for this case, see what happen because of this bug https://github.com/TryGhost/Ghost/issues/7192 - */ -module.exports = function fixSqliteFormat(options, logger) { - // CASE: skip this script when using mysql - if (config.get('database').client === 'mysql') { - logger.warn(messagePrefix + 'This script only runs, when using sqlite as database.'); - return Promise.resolve(); - } - - // CASE: sqlite3 and server is UTC, we check if the date migration was already running - return options.transacting.raw('select created_at from users') - .then(function (users) { - // safety measure - if (!users || !users.length) { - return; - } - - // CASE: if type is string and sqlite, then it already has the correct date format - if (!_.isNumber(users[0].created_at)) { - logger.warn(messagePrefix + 'Your dates are in correct format.'); - return; - } - - return _private.rerunDateMigration(options, logger); - }); -}; diff --git a/core/server/data/migration/fixtures/008/index.js b/core/server/data/migration/fixtures/008/index.js deleted file mode 100644 index aaae3bb281..0000000000 --- a/core/server/data/migration/fixtures/008/index.js +++ /dev/null @@ -1,3 +0,0 @@ -module.exports = [ - require('./01-fix-sqlite-pg-format') -]; diff --git a/core/test/integration/migration_spec.js b/core/test/integration/migration_spec.js index b6063393f5..2b3c02ea29 100644 --- a/core/test/integration/migration_spec.js +++ b/core/test/integration/migration_spec.js @@ -3,11 +3,8 @@ var testUtils = require('../utils'), sinon = require('sinon'), _ = require('lodash'), Promise = require('bluebird'), - fixtures = require('../../server/data/migration/fixtures'), - fixtures005 = require('../../server/data/migration/fixtures/005'), Models = require('../../server/models'), - sandbox = sinon.sandbox.create(); describe('Database Migration (special functions)', function () { @@ -220,59 +217,5 @@ describe('Database Migration (special functions)', function () { }).catch(done); }); }); - - describe('Update', function () { - // We need the roles, and lets add some other perms to simulate the "Update" environment - beforeEach(testUtils.setup('users:roles', 'perms:db', 'perms:init')); - - it('should update client permissions correctly', function (done) { - fixtures005[2]({context:{internal:true}}, loggerStub).then(function () { - var props = { - roles: Models.Role.findAll(), - permissions: Models.Permission.findAll({include: ['roles']}) - }, permissions; - - loggerStub.info.called.should.be.true(); - loggerStub.warn.called.should.be.false(); - - return Promise.props(props).then(function (result) { - should.exist(result); - - should.exist(result.roles); - result.roles.length.should.eql(4); - result.roles.at(0).get('name').should.eql('Administrator'); - result.roles.at(1).get('name').should.eql('Editor'); - result.roles.at(2).get('name').should.eql('Author'); - result.roles.at(3).get('name').should.eql('Owner'); - - // Permissions - result.permissions.length.should.eql(8); - permissions = result.permissions.toJSON(); - - // DB Perms - permissions[0].name.should.eql('Export database'); - permissions[0].should.be.AssignedToRoles(['Administrator']); - permissions[1].name.should.eql('Import database'); - permissions[1].should.be.AssignedToRoles(['Administrator']); - permissions[2].name.should.eql('Delete all content'); - permissions[2].should.be.AssignedToRoles(['Administrator']); - - // Client Perms - permissions[3].name.should.eql('Browse clients'); - permissions[3].should.be.AssignedToRoles(['Administrator', 'Editor', 'Author']); - permissions[4].name.should.eql('Read clients'); - permissions[4].should.be.AssignedToRoles(['Administrator', 'Editor', 'Author']); - permissions[5].name.should.eql('Edit clients'); - permissions[5].should.be.AssignedToRoles(['Administrator', 'Editor', 'Author']); - permissions[6].name.should.eql('Add clients'); - permissions[6].should.be.AssignedToRoles(['Administrator', 'Editor', 'Author']); - permissions[7].name.should.eql('Delete clients'); - permissions[7].should.be.AssignedToRoles(['Administrator', 'Editor', 'Author']); - - done(); - }).catch(done); - }); - }); - }); }); }); diff --git a/core/test/unit/migration_fixture_spec.js b/core/test/unit/migration_fixture_spec.js deleted file mode 100644 index 8c2c2ab75d..0000000000 --- a/core/test/unit/migration_fixture_spec.js +++ /dev/null @@ -1,1427 +0,0 @@ -var should = require('should'), - sinon = require('sinon'), - _ = require('lodash'), - moment = require('moment'), - rewire = require('rewire'), - Promise = require('bluebird'), - - // Stuff we are testing - configUtils = require('../utils/configUtils'), - models = require('../../server/models'), - api = require('../../server/api'), - permissions = require('../../server/permissions'), - notifications = require('../../server/api/notifications'), - versioning = require('../../server/data/schema/versioning'), - update = rewire('../../server/data/migration/fixtures/update'), - populate = rewire('../../server/data/migration/fixtures/populate'), - fixtureUtils = require('../../server/data/migration/fixtures/utils'), - fixtures004 = require('../../server/data/migration/fixtures/004'), - fixtures005 = require('../../server/data/migration/fixtures/005'), - fixtures006 = require('../../server/data/migration/fixtures/006'), - fixtures007 = require('../../server/data/migration/fixtures/007'), - fixtures008 = require('../../server/data/migration/fixtures/008'), - - sandbox = sinon.sandbox.create(); - -describe('Fixtures', function () { - var loggerStub, transactionStub; - - beforeEach(function () { - loggerStub = { - info: sandbox.stub(), - warn: sandbox.stub() - }; - - transactionStub = sandbox.stub(); - - models.init(); - }); - - afterEach(function () { - sandbox.restore(); - configUtils.restore(); - }); - - describe('Update fixtures', function () { - it('should call tasks in correct order if provided', function (done) { - var sequenceStub = sandbox.stub(), - sequenceReset = update.__set__('sequence', sequenceStub), - tasks = [ - sandbox.stub(), - sandbox.stub() - ]; - - sequenceStub.returns(Promise.resolve([])); - - update(tasks, loggerStub, {transacting: transactionStub}).then(function () { - loggerStub.info.calledOnce.should.be.true(); - loggerStub.warn.called.should.be.false(); - - sequenceStub.firstCall.args[0].should.be.an.Array().with.lengthOf(2); - sequenceStub.firstCall.args[1].should.eql({transacting: transactionStub}); - sequenceStub.firstCall.args[2].should.eql(loggerStub); - sequenceReset(); - done(); - }).catch(done); - }); - - describe('Update to 004', function () { - it('should call all the 004 fixture upgrade tasks', function (done) { - // Setup - // Create a new stub, this will replace sequence, so that db calls don't actually get run - var sequenceStub = sandbox.stub(), - sequenceReset = update.__set__('sequence', sequenceStub), - tasks = versioning.getUpdateFixturesTasks('004', loggerStub); - - sequenceStub.returns(Promise.resolve([])); - - update(tasks, loggerStub, {transacting: transactionStub}).then(function (result) { - should.exist(result); - - loggerStub.info.calledOnce.should.be.true(); - loggerStub.warn.called.should.be.false(); - - sequenceStub.calledOnce.should.be.true(); - sequenceStub.firstCall.calledWith(sinon.match.array, sinon.match.object, loggerStub).should.be.true(); - sequenceStub.firstCall.args[0].should.be.an.Array().with.lengthOf(8); - sequenceStub.firstCall.args[0][0].should.be.a.Function().with.property('name', 'moveJQuery'); - sequenceStub.firstCall.args[0][1].should.be.a.Function().with.property('name', 'updatePrivateSetting'); - sequenceStub.firstCall.args[0][2].should.be.a.Function().with.property('name', 'updatePasswordSetting'); - sequenceStub.firstCall.args[0][3].should.be.a.Function().with.property('name', 'updateGhostAdminClient'); - sequenceStub.firstCall.args[0][4].should.be.a.Function().with.property('name', 'addGhostFrontendClient'); - sequenceStub.firstCall.args[0][5].should.be.a.Function().with.property('name', 'cleanBrokenTags'); - sequenceStub.firstCall.args[0][6].should.be.a.Function().with.property('name', 'addPostTagOrder'); - sequenceStub.firstCall.args[0][7].should.be.a.Function().with.property('name', 'addNewPostFixture'); - - // Reset - sequenceReset(); - done(); - }).catch(done); - }); - - describe('Tasks:', function () { - var getObjStub, settingsOneStub, settingsEditStub, clientOneStub, clientEditStub; - - beforeEach(function () { - getObjStub = {get: sandbox.stub()}; - settingsOneStub = sandbox.stub(models.Settings, 'findOne').returns(Promise.resolve(getObjStub)); - settingsEditStub = sandbox.stub(models.Settings, 'edit').returns(Promise.resolve()); - clientOneStub = sandbox.stub(models.Client, 'findOne').returns(Promise.resolve(getObjStub)); - clientEditStub = sandbox.stub(models.Client, 'edit').returns(Promise.resolve()); - }); - - it('should have tasks for 004', function () { - should.exist(fixtures004); - fixtures004.should.be.an.Array().with.lengthOf(8); - }); - - describe('01-move-jquery-with-alert', function () { - var moveJquery = fixtures004[0]; - - it('tries to move jQuery to ghost_foot', function (done) { - getObjStub.get.returns(''); - - moveJquery({}, loggerStub).then(function () { - settingsOneStub.calledOnce.should.be.true(); - settingsOneStub.calledWith('ghost_foot').should.be.true(); - settingsEditStub.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) { - getObjStub.get.returns( - '\n' - + '\n\n' - ); - - moveJquery({}, loggerStub).then(function () { - settingsOneStub.calledOnce.should.be.true(); - settingsOneStub.calledWith('ghost_foot').should.be.true(); - settingsEditStub.calledOnce.should.be.false(); - loggerStub.info.called.should.be.false(); - loggerStub.warn.calledOnce.should.be.true(); - - done(); - }).catch(done); - }); - - it('does not move jQuery to ghost_foot if the setting is missing', function (done) { - settingsOneStub.returns(Promise.resolve()); - - moveJquery({}, loggerStub).then(function () { - settingsOneStub.calledOnce.should.be.true(); - settingsOneStub.calledWith('ghost_foot').should.be.true(); - settingsEditStub.called.should.be.false(); - loggerStub.info.called.should.be.false(); - loggerStub.warn.calledOnce.should.be.true(); - - done(); - }).catch(done); - }); - - it('tried to move jQuery AND add a privacy message if any privacy settings are on', function (done) { - var notificationsAddStub = sandbox.stub(notifications, 'add').returns(Promise.resolve()); - configUtils.set({privacy: {useGravatar: false}}); - getObjStub.get.returns(''); - - moveJquery({}, 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(); - loggerStub.info.calledTwice.should.be.true(); - loggerStub.warn.called.should.be.false(); - - done(); - }).catch(done); - }); - }); - - describe('02-update-private-setting-type', function () { - var updateSettingType = fixtures004[1]; - - it('tries to update setting type correctly', function (done) { - updateSettingType({}, loggerStub).then(function () { - settingsOneStub.calledOnce.should.be.true(); - settingsOneStub.calledWith('isPrivate').should.be.true(); - getObjStub.get.calledOnce.should.be.true(); - getObjStub.get.calledWith('type').should.be.true(); - settingsEditStub.calledOnce.should.be.true(); - settingsEditStub.calledWith({key: 'isPrivate', type: 'private'}).should.be.true(); - loggerStub.info.calledOnce.should.be.true(); - loggerStub.warn.called.should.be.false(); - sinon.assert.callOrder(settingsOneStub, getObjStub.get, loggerStub.info, settingsEditStub); - - done(); - }).catch(done); - }); - - it('does not try to update setting type if it is already set', function (done) { - getObjStub.get.returns('private'); - - updateSettingType({}, loggerStub).then(function () { - settingsOneStub.calledOnce.should.be.true(); - settingsOneStub.calledWith('isPrivate').should.be.true(); - getObjStub.get.calledOnce.should.be.true(); - getObjStub.get.calledWith('type').should.be.true(); - - settingsEditStub.called.should.be.false(); - loggerStub.info.called.should.be.false(); - loggerStub.warn.calledOnce.should.be.true(); - - sinon.assert.callOrder(settingsOneStub, getObjStub.get, loggerStub.warn); - - done(); - }).catch(done); - }); - }); - - describe('03-update-password-setting-type', function () { - var updateSettingType = fixtures004[2]; - - it('tries to update setting type correctly', function (done) { - updateSettingType({}, 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(); - 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) { - getObjStub.get.returns('private'); - - updateSettingType({}, loggerStub).then(function () { - settingsOneStub.calledOnce.should.be.true(); - settingsOneStub.calledWith('password').should.be.true(); - getObjStub.get.calledOnce.should.be.true(); - getObjStub.get.calledWith('type').should.be.true(); - - settingsEditStub.called.should.be.false(); - loggerStub.info.called.should.be.false(); - loggerStub.warn.calledOnce.should.be.true(); - - sinon.assert.callOrder(settingsOneStub, getObjStub.get); - - done(); - }).catch(done); - }); - }); - - describe('04-update-ghost-admin-client', function () { - var updateClient = fixtures004[3]; - - it('tries to update client correctly', function (done) { - updateClient({}, loggerStub).then(function () { - clientOneStub.calledOnce.should.be.true(); - clientOneStub.calledWith({slug: 'ghost-admin'}).should.be.true(); - getObjStub.get.calledTwice.should.be.true(); - getObjStub.get.calledWith('secret').should.be.true(); - getObjStub.get.calledWith('status').should.be.true(); - clientEditStub.calledOnce.should.be.true(); - loggerStub.info.calledOnce.should.be.true(); - loggerStub.warn.called.should.be.false(); - sinon.assert.callOrder( - clientOneStub, getObjStub.get, getObjStub.get, loggerStub.info, clientEditStub - ); - - done(); - }).catch(done); - }); - - it('does not try to update client if the secret and status are already correct', function (done) { - getObjStub.get.withArgs('secret').returns('abc'); - getObjStub.get.withArgs('status').returns('enabled'); - - updateClient({}, loggerStub).then(function () { - clientOneStub.calledOnce.should.be.true(); - clientOneStub.calledWith({slug: 'ghost-admin'}).should.be.true(); - getObjStub.get.calledTwice.should.be.true(); - getObjStub.get.calledWith('secret').should.be.true(); - getObjStub.get.calledWith('status').should.be.true(); - clientEditStub.called.should.be.false(); - loggerStub.info.called.should.be.false(); - loggerStub.warn.calledOnce.should.be.true(); - sinon.assert.callOrder(clientOneStub, getObjStub.get, getObjStub.get, loggerStub.warn); - - done(); - }).catch(done); - }); - - it('tries to update client if secret is correct but status is wrong', function (done) { - getObjStub.get.withArgs('secret').returns('abc'); - getObjStub.get.withArgs('status').returns('development'); - - updateClient({}, loggerStub).then(function () { - clientOneStub.calledOnce.should.be.true(); - clientOneStub.calledWith({slug: 'ghost-admin'}).should.be.true(); - getObjStub.get.calledTwice.should.be.true(); - getObjStub.get.calledWith('secret').should.be.true(); - getObjStub.get.calledWith('status').should.be.true(); - - clientEditStub.calledOnce.should.be.true(); - loggerStub.info.calledOnce.should.be.true(); - loggerStub.warn.called.should.be.false(); - sinon.assert.callOrder( - clientOneStub, getObjStub.get, getObjStub.get, loggerStub.info, clientEditStub - ); - - done(); - }).catch(done); - }); - - it('tries to update client if status is correct but secret is wrong', function (done) { - getObjStub.get.withArgs('secret').returns('not_available'); - getObjStub.get.withArgs('status').returns('enabled'); - - updateClient({}, loggerStub).then(function () { - clientOneStub.calledOnce.should.be.true(); - clientOneStub.calledWith({slug: 'ghost-admin'}).should.be.true(); - getObjStub.get.calledOnce.should.be.true(); - getObjStub.get.calledWith('secret').should.be.true(); - - clientEditStub.calledOnce.should.be.true(); - loggerStub.info.calledOnce.should.be.true(); - loggerStub.warn.called.should.be.false(); - sinon.assert.callOrder( - clientOneStub, getObjStub.get, loggerStub.info, clientEditStub - ); - - done(); - }).catch(done); - }); - }); - - 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()); - - addClient({}, loggerStub).then(function () { - clientOneStub.calledOnce.should.be.true(); - clientOneStub.calledWith({slug: 'ghost-frontend'}).should.be.true(); - clientAddStub.calledOnce.should.be.true(); - 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 clientAddStub = sandbox.stub(models.Client, 'add').returns(Promise.resolve()); - - addClient({}, loggerStub).then(function () { - clientOneStub.calledOnce.should.be.true(); - clientOneStub.calledWith({slug: 'ghost-frontend'}).should.be.true(); - clientAddStub.called.should.be.false(); - loggerStub.info.called.should.be.false(); - loggerStub.warn.calledOnce.should.be.true(); - - done(); - }).catch(done); - }); - }); - - describe('06-clean-broken-tags', function () { - var tagObjStub, tagCollStub, tagAllStub, - cleanBrokenTags = fixtures004[5]; - - beforeEach(function () { - tagObjStub = { - get: sandbox.stub(), - save: sandbox.stub().returns(Promise.resolve) - }; - tagCollStub = {each: sandbox.stub().callsArgWith(0, tagObjStub)}; - tagAllStub = sandbox.stub(models.Tag, 'findAll').returns(Promise.resolve(tagCollStub)); - }); - - it('tries to clean broken tags correctly', function (done) { - tagObjStub.get.returns(',hello'); - - cleanBrokenTags({}, 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(); - 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) { - tagObjStub.get.returns(','); - - cleanBrokenTags({}, 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(); - 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) { - tagObjStub.get.returns('hello'); - - cleanBrokenTags({}, 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(); - loggerStub.info.called.should.be.false(); - loggerStub.warn.calledOnce.should.be.true(); - sinon.assert.callOrder(tagAllStub, tagCollStub.each, tagObjStub.get, loggerStub.warn); - - done(); - }).catch(done); - }); - - it('does nothing if there are no tags', function (done) { - tagAllStub.returns(Promise.resolve()); - - cleanBrokenTags({}, loggerStub).then(function () { - tagAllStub.calledOnce.should.be.true(); - tagCollStub.each.called.should.be.false(); - tagObjStub.get.called.should.be.false(); - tagObjStub.save.called.should.be.false(); - loggerStub.info.called.should.be.false(); - loggerStub.warn.calledOnce.should.be.true(); - sinon.assert.callOrder(tagAllStub, loggerStub.warn); - - done(); - }).catch(done); - }); - }); - - describe('07-add-post-tag-order', function () { - var tagOp1Stub, tagOp2Stub, tagObjStub, postObjStub, postCollStub, postAllStub, - addPostTagOrder = fixtures004[6]; - - beforeEach(function () { - tagOp1Stub = sandbox.stub().returns(Promise.resolve()); - tagOp2Stub = sandbox.stub().returns(Promise.resolve()); - tagObjStub = { - pivot: {get: sandbox.stub()} - }; - postCollStub = {mapThen: sandbox.stub()}; - postAllStub = sandbox.stub(models.Post, 'findAll').returns(Promise.resolve(postCollStub)); - - postObjStub = { - load: sandbox.stub(), - reduce: sandbox.stub(), - // By returning an array from related, we can use native reduce to simulate a result - related: sandbox.stub().returns([tagObjStub]), - // Get called when executing sequence - tags: sandbox.stub().returnsThis(), - updatePivot: sandbox.stub().returns(Promise.resolve()) - }; - }); - - it('calls load on each post', function (done) { - // Fake mapThen behaviour - postCollStub.mapThen.callsArgWith(0, postObjStub).returns([]); - addPostTagOrder({}, 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(); - 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) { - // Fake mapThen behaviour - postCollStub.mapThen.returns([]); - postAllStub.returns(Promise.resolve()); - - addPostTagOrder({}, loggerStub).then(function () { - loggerStub.info.calledOnce.should.be.true(); - loggerStub.warn.calledOnce.should.be.true(); - postAllStub.calledOnce.should.be.true(); - sinon.assert.callOrder(loggerStub.info, postAllStub, loggerStub.warn); - - done(); - }).catch(done); - }); - - it('executes sequence, if at least one tag is found', function (done) { - var tagOpStub = sandbox.stub().returns(Promise.resolve()), - tagOpsArr = [tagOpStub]; - - // By stubbing reduce, we can return an array directly without pretending to process tags - postObjStub.reduce.returns(tagOpsArr); - // By returning from mapThen, we can skip doing tag.load in this test - postCollStub.mapThen.returns(postObjStub); - - addPostTagOrder({}, 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.reduce.calledOnce.should.be.true(); - tagOpStub.calledOnce.should.be.true(); - - sinon.assert.callOrder( - loggerStub.info, postAllStub, postCollStub.mapThen, postObjStub.reduce, - loggerStub.info, tagOpStub, loggerStub.info - ); - - done(); - }).catch(done); - }); - - it('executes sequence, if more than one tag is found', function (done) { - var tagOpsArr = [tagOp1Stub, tagOp2Stub]; - // By stubbing reduce, we can return an array directly without pretending to process tags - postObjStub.reduce.returns(tagOpsArr); - // By returning from mapThen, we can skip doing tag.load in this test - postCollStub.mapThen.returns(postObjStub); - - addPostTagOrder({}, 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.reduce.calledOnce.should.be.true(); - tagOp1Stub.calledOnce.should.be.true(); - tagOp2Stub.calledOnce.should.be.true(); - - sinon.assert.callOrder( - loggerStub.info, postAllStub, postCollStub.mapThen, postObjStub.reduce, - loggerStub.info, tagOp1Stub, tagOp2Stub, loggerStub.info - ); - - done(); - }).catch(done); - }); - - it('does not execute sequence, if migrationHasRunFlag gets set to true', function (done) { - tagObjStub.pivot.get.returns(1); - // By returning from mapThen, we can skip doing tag.load in this test - postCollStub.mapThen.returns([postObjStub]); - - addPostTagOrder({}, 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( - loggerStub.info, postAllStub, postCollStub.mapThen, postObjStub.related, - tagObjStub.pivot.get, loggerStub.warn - ); - - done(); - }).catch(done); - }); - - it('does execute sequence, if migrationHasRunFlag is false', function (done) { - // If pivot gets a non-zero, migrationHasRunFlag gets set to true - tagObjStub.pivot.get.returns(0); - // By returning from mapThen, we can skip doing tag.load in this test - postCollStub.mapThen.returns([postObjStub]); - - addPostTagOrder({}, 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(); - tagObjStub.pivot.get.calledOnce.should.be.true(); - tagObjStub.pivot.get.calledWith('sort_order').should.be.true(); - - postObjStub.tags.calledOnce.should.be.true(); - postObjStub.updatePivot.calledOnce.should.be.true(); - sinon.assert.callOrder( - loggerStub.info, postAllStub, postCollStub.mapThen, postObjStub.related, tagObjStub.pivot.get, - loggerStub.info, postObjStub.tags, postObjStub.updatePivot, loggerStub.info - ); - - done(); - }).catch(done); - }); - - it('tries to add incremental sort_order to posts_tags', function (done) { - // If pivot gets a non-zero, migrationHasRunFlag gets set to true - tagObjStub.pivot.get.returns(0); - // By returning an array from related, we can use real reduce to simulate a result here - postObjStub.related.returns([tagObjStub, tagObjStub, tagObjStub]); - // By returning from mapThen, we can skip doing tag.load in this test - postCollStub.mapThen.returns([postObjStub]); - - addPostTagOrder({}, 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(); - tagObjStub.pivot.get.calledThrice.should.be.true(); - - postObjStub.tags.calledThrice.should.be.true(); - postObjStub.updatePivot.calledThrice.should.be.true(); - - postObjStub.updatePivot.firstCall.args[0].should.eql({sort_order: 0}); - postObjStub.updatePivot.secondCall.args[0].should.eql({sort_order: 1}); - postObjStub.updatePivot.thirdCall.args[0].should.eql({sort_order: 2}); - - sinon.assert.callOrder( - loggerStub.info, postAllStub, postCollStub.mapThen, postObjStub.related, - tagObjStub.pivot.get, tagObjStub.pivot.get, tagObjStub.pivot.get, - loggerStub.info, - postObjStub.tags, postObjStub.updatePivot, - postObjStub.tags, postObjStub.updatePivot, - postObjStub.tags, postObjStub.updatePivot, - loggerStub.info - ); - - done(); - }).catch(done); - }); - }); - - describe('08-add-post-fixture', function () { - var postOneStub, postAddStub, - addPostFixture = fixtures004[7]; - - beforeEach(function () { - postOneStub = sandbox.stub(models.Post, 'findOne').returns(Promise.resolve()); - postAddStub = sandbox.stub(models.Post, 'add').returns(Promise.resolve()); - }); - - it('tries to add a new post fixture correctly', function (done) { - addPostFixture({}, loggerStub).then(function () { - postOneStub.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, loggerStub.info, postAddStub); - - done(); - }).catch(done); - }); - - it('does not try to add new post fixture if it already exists', function (done) { - postOneStub.returns(Promise.resolve({})); - - addPostFixture({}, 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(); - - sinon.assert.callOrder(postOneStub, loggerStub.warn); - - done(); - }).catch(done); - }); - }); - }); - }); - - describe('Update to 005', function () { - it('should call all the 005 fixture upgrades', function (done) { - // Setup - // Create a new stub, this will replace sequence, so that db calls don't actually get run - var sequenceStub = sandbox.stub(), - sequenceReset = update.__set__('sequence', sequenceStub), - tasks = versioning.getUpdateFixturesTasks('005', loggerStub); - - sequenceStub.returns(Promise.resolve([])); - - update(tasks, loggerStub, {transacting: transactionStub}).then(function (result) { - should.exist(result); - - loggerStub.info.calledOnce.should.be.true(); - loggerStub.warn.called.should.be.false(); - - sequenceStub.calledOnce.should.be.true(); - - sequenceStub.firstCall.calledWith(sinon.match.array, sinon.match.object, loggerStub).should.be.true(); - sequenceStub.firstCall.args[0].should.be.an.Array().with.lengthOf(4); - sequenceStub.firstCall.args[0][0].should.be.a.Function().with.property('name', 'updateGhostClientsSecrets'); - sequenceStub.firstCall.args[0][1].should.be.a.Function().with.property('name', 'addGhostFrontendClient'); - sequenceStub.firstCall.args[0][2].should.be.a.Function().with.property('name', 'addClientPermissions'); - sequenceStub.firstCall.args[0][3].should.be.a.Function().with.property('name', 'addSubscriberPermissions'); - - // Reset - sequenceReset(); - done(); - }).catch(done); - }); - - describe('Tasks:', function () { - it('should have tasks for 005', function () { - should.exist(fixtures005); - fixtures005.should.be.an.Array().with.lengthOf(4); - }); - - describe('01-update-ghost-client-secrets', function () { - var queryStub, clientForgeStub, clientEditStub, - updateClient = fixtures005[0]; - - beforeEach(function () { - queryStub = { - query: sandbox.stub().returnsThis(), - fetch: sandbox.stub() - }; - - clientForgeStub = sandbox.stub(models.Clients, 'forge').returns(queryStub); - clientEditStub = sandbox.stub(models.Client, 'edit'); - }); - - it('should do nothing if there are no incorrect secrets', function (done) { - // Setup - queryStub.fetch.returns(new Promise.resolve({models: []})); - - // Execute - updateClient({}, loggerStub).then(function () { - clientForgeStub.calledOnce.should.be.true(); - clientEditStub.called.should.be.false(); - loggerStub.info.called.should.be.false(); - loggerStub.warn.calledOnce.should.be.true(); - done(); - }).catch(done); - }); - - it('should try to fix any incorrect secrets', function (done) { - // Setup - queryStub.fetch.returns(new Promise.resolve({models: [{id: 1}]})); - - // Execute - updateClient({}, loggerStub).then(function () { - clientForgeStub.calledOnce.should.be.true(); - clientEditStub.called.should.be.true(); - loggerStub.info.calledOnce.should.be.true(); - loggerStub.warn.called.should.be.false(); - done(); - }).catch(done); - }); - }); - - describe('02-add-ghost-scheduler-client', function () { - var clientOneStub, - addClient = fixtures005[1]; - - beforeEach(function () { - clientOneStub = sandbox.stub(models.Client, 'findOne').returns(Promise.resolve({})); - }); - - it('tries to add client correctly', function (done) { - var clientAddStub = sandbox.stub(models.Client, 'add').returns(Promise.resolve()); - clientOneStub.returns(Promise.resolve()); - - addClient({}, loggerStub).then(function () { - clientOneStub.calledOnce.should.be.true(); - clientOneStub.calledWith({slug: 'ghost-scheduler'}).should.be.true(); - clientAddStub.calledOnce.should.be.true(); - 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 clientAddStub = sandbox.stub(models.Client, 'add').returns(Promise.resolve()); - - addClient({}, loggerStub).then(function () { - clientOneStub.calledOnce.should.be.true(); - clientOneStub.calledWith({slug: 'ghost-scheduler'}).should.be.true(); - clientAddStub.called.should.be.false(); - loggerStub.info.called.should.be.false(); - loggerStub.warn.calledOnce.should.be.true(); - - done(); - }).catch(done); - }); - }); - - describe('03-add-client-permissions', function () { - var modelResult, addModelStub, relationResult, addRelationStub, - addClientPermissions = fixtures005[2]; - - 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 - addClientPermissions({}, loggerStub).then(function () { - addModelStub.calledOnce.should.be.true(); - addModelStub.calledWith( - fixtureUtils.findModelFixtures('Permission', {object_type: 'client'}) - ).should.be.true(); - - addRelationStub.calledOnce.should.be.true(); - addRelationStub.calledWith( - fixtureUtils.findPermissionRelationsForObject('client') - ).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 - addClientPermissions({}, loggerStub).then(function () { - addModelStub.calledOnce.should.be.true(); - addModelStub.calledWith( - fixtureUtils.findModelFixtures('Permission', {object_type: 'client'}) - ).should.be.true(); - - addRelationStub.calledOnce.should.be.true(); - addRelationStub.calledWith( - fixtureUtils.findPermissionRelationsForObject('client') - ).should.be.true(); - - loggerStub.info.calledOnce.should.be.true(); - loggerStub.warn.calledOnce.should.be.true(); - - done(); - }); - }); - }); - - 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(); - }); - }); - }); - }); - }); - - describe('Update to 006', function () { - it('should call all the 006 fixture upgrades', function (done) { - // Setup - // Create a new stub, this will replace sequence, so that db calls don't actually get run - var sequenceStub = sandbox.stub(), - sequenceReset = update.__set__('sequence', sequenceStub), - tasks = versioning.getUpdateFixturesTasks('006', loggerStub); - - sequenceStub.returns(Promise.resolve([])); - - update(tasks, loggerStub, {transacting: transactionStub}).then(function (result) { - should.exist(result); - - loggerStub.info.calledOnce.should.be.true(); - loggerStub.warn.called.should.be.false(); - - sequenceStub.calledOnce.should.be.true(); - - sequenceStub.firstCall.calledWith(sinon.match.array, sinon.match.object, loggerStub).should.be.true(); - sequenceStub.firstCall.args[0].should.be.an.Array().with.lengthOf(1); - sequenceStub.firstCall.args[0][0].should.be.a.Function().with.property('name', 'transformDatesIntoUTC'); - - // Reset - sequenceReset(); - done(); - }).catch(done); - }); - - describe('Tasks:', function () { - it('should have tasks for 006', function () { - should.exist(fixtures006); - fixtures006.should.be.an.Array().with.lengthOf(1); - }); - - describe('01-transform-dates-into-utc', function () { - var updateClient = fixtures006[0], - serverTimezoneOffset, - migrationsSettingsValue; - - beforeEach(function () { - sandbox.stub(Date.prototype, 'getTimezoneOffset', function () { - return serverTimezoneOffset; - }); - }); - - describe('error cases', function () { - before(function () { - serverTimezoneOffset = 0; - }); - - beforeEach(function () { - sandbox.stub(models.Settings, 'findOne', function () { - return Promise.resolve({attributes: {value: migrationsSettingsValue}}); - }); - }); - - it('server offset is 0 and mysql', function (done) { - migrationsSettingsValue = '{}'; - configUtils.set('database:client', 'mysql'); - - updateClient({}, loggerStub) - .then(function () { - loggerStub.warn.called.should.be.true(); - done(); - }) - .catch(done); - }); - - it('migration already ran', function (done) { - migrationsSettingsValue = '{ "006/01": "timestamp" }'; - - updateClient({}, loggerStub) - .then(function () { - loggerStub.warn.called.should.be.true(); - done(); - }) - .catch(done); - }); - }); - - describe('success cases', function () { - var newModels, createdAt, migrationsSettingsWasUpdated; - - before(function () { - serverTimezoneOffset = -60; - migrationsSettingsValue = '{}'; - }); - - beforeEach(function () { - newModels = {}; - migrationsSettingsWasUpdated = false; - serverTimezoneOffset = -60; - migrationsSettingsValue = '{}'; - - // stub for checkIfMigrationAlreadyRan - sandbox.stub(models.Settings.prototype, 'fetch', function () { - // CASE: we update migrations settings entry - if (this.get('key') === 'migrations') { - migrationsSettingsWasUpdated = true; - return Promise.resolve(newModels[Object.keys(newModels)[0]] || {attributes: {value: migrationsSettingsValue}}); - } - - return Promise.resolve(newModels[Number(this.get('key'))]); - }); - - _.each(['Post', 'User', 'Subscriber', 'Settings', 'Role', 'Permission', 'Tag', 'App', 'AppSetting', 'AppField', 'Client'], function (modelType) { - sandbox.stub(models[modelType], 'findAll', function () { - var model = models[modelType].forge(); - model.set('id', Date.now()); - model.set('created_at', createdAt); - model.set('key', model.id.toString()); - model.set('name', modelType); - - newModels[model.id] = model; - return Promise.resolve({models: [model]}); - }); - - if (modelType !== 'Settings') { - sandbox.stub(models[modelType], 'findOne', function (data) { - return Promise.resolve(newModels[data.id]); - }); - } - - sandbox.stub(models[modelType], 'edit').returns(Promise.resolve({})); - }); - - sandbox.stub(api.settings, 'updateSettingsCache').returns(Promise.resolve({})); - }); - - it('server offset is 0 and sqlite', function (done) { - serverTimezoneOffset = 0; - createdAt = moment(1464798678537).toDate(); - configUtils.set('database:client', 'sqlite3'); - - moment(createdAt).format('YYYY-MM-DD HH:mm:ss').should.eql('2016-06-01 16:31:18'); - - updateClient({}, loggerStub) - .then(function () { - _.each(newModels, function (model) { - moment(model.get('created_at')).format('YYYY-MM-DD HH:mm:ss').should.eql('2016-06-01 16:31:18'); - }); - - migrationsSettingsWasUpdated.should.eql(true); - done(); - }) - .catch(done); - }); - - it('sqlite: no UTC update, only format', function (done) { - createdAt = moment(1464798678537).toDate(); - configUtils.set('database:client', 'sqlite3'); - moment(createdAt).format('YYYY-MM-DD HH:mm:ss').should.eql('2016-06-01 16:31:18'); - - updateClient({}, loggerStub) - .then(function () { - _.each(newModels, function (model) { - moment(model.get('created_at')).format('YYYY-MM-DD HH:mm:ss').should.eql('2016-06-01 16:31:18'); - }); - - migrationsSettingsWasUpdated.should.eql(true); - done(); - }) - .catch(done); - }); - - it('mysql: UTC update', function (done) { - /** - * we fetch 2016-06-01 06:00:00 from the database which was stored as local representation - * our base model will wrap it into a UTC moment - * the offset is 1 hour - * we expect 2016-06-01 05:00:00 - */ - createdAt = moment('2016-06-01 06:00:00').toDate(); - configUtils.set('database:client', 'mysql'); - moment(createdAt).format('YYYY-MM-DD HH:mm:ss').should.eql('2016-06-01 06:00:00'); - - updateClient({}, loggerStub) - .then(function () { - _.each(newModels, function (model) { - moment(model.get('created_at')).format('YYYY-MM-DD HH:mm:ss').should.eql('2016-06-01 05:00:00'); - }); - - migrationsSettingsWasUpdated.should.eql(true); - done(); - }) - .catch(done); - }); - }); - }); - }); - }); - - describe('Update to 007', function () { - it('should call all the 007 fixture upgrades', function (done) { - // Setup - // Create a new stub, this will replace sequence, so that db calls don't actually get run - var sequenceStub = sandbox.stub(), - sequenceReset = update.__set__('sequence', sequenceStub), - tasks = versioning.getUpdateFixturesTasks('007', loggerStub); - - sequenceStub.returns(Promise.resolve([])); - - update(tasks, loggerStub, {transacting: transactionStub}).then(function (result) { - should.exist(result); - - loggerStub.info.calledOnce.should.be.true(); - loggerStub.warn.called.should.be.false(); - - sequenceStub.calledOnce.should.be.true(); - - sequenceStub.firstCall.calledWith(sinon.match.array, sinon.match.object, loggerStub).should.be.true(); - sequenceStub.firstCall.args[0].should.be.an.Array().with.lengthOf(1); - sequenceStub.firstCall.args[0][0].should.be.a.Function().with.property('name', 'addThemePermissions'); - - // Reset - sequenceReset(); - done(); - }).catch(done); - }); - - describe('Tasks:', function () { - it('should have tasks for 007', function () { - should.exist(fixtures007); - fixtures007.should.be.an.Array().with.lengthOf(1); - }); - - describe('01-addThemePermissions', function () { - var updateThemePermissions = fixtures007[0], addModelStub, relationResult, addRelationStub, modelResult; - - before(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)); - - sandbox.stub(permissions, 'init').returns(Promise.resolve()); - }); - - it('ensure permissions get updates', function (done) { - updateThemePermissions({context: {internal: true}}, loggerStub) - .then(function () { - addModelStub.calledOnce.should.be.true(); - addModelStub.calledWith( - fixtureUtils.findModelFixtures('Permission', {object_type: 'theme'}) - ).should.be.true(); - - addRelationStub.calledOnce.should.be.true(); - addRelationStub.calledWith( - fixtureUtils.findPermissionRelationsForObject('theme') - ).should.be.true(); - - permissions.init.calledOnce.should.eql(true); - done(); - }) - .catch(done); - }); - }); - }); - }); - - describe('Update to 008', function () { - it('should call all the 008 fixture upgrades', function (done) { - // Setup - // Create a new stub, this will replace sequence, so that db calls don't actually get run - var sequenceStub = sandbox.stub(), - sequenceReset = update.__set__('sequence', sequenceStub), - tasks = versioning.getUpdateFixturesTasks('008', loggerStub); - - sequenceStub.returns(Promise.resolve([])); - - update(tasks, loggerStub, {transacting: transactionStub}).then(function (result) { - should.exist(result); - - loggerStub.info.calledOnce.should.be.true(); - loggerStub.warn.called.should.be.false(); - - sequenceStub.calledOnce.should.be.true(); - - sequenceStub.firstCall.calledWith(sinon.match.array, sinon.match.object, loggerStub).should.be.true(); - sequenceStub.firstCall.args[0].should.be.an.Array().with.lengthOf(1); - sequenceStub.firstCall.args[0][0].should.be.a.Function().with.property('name', 'fixSqliteFormat'); - - // Reset - sequenceReset(); - done(); - }).catch(done); - }); - - describe('Tasks:', function () { - it('should have tasks for 008', function () { - should.exist(fixtures008); - fixtures008.should.be.an.Array().with.lengthOf(1); - }); - - describe('01-fix-sqlite-pg-format', function () { - var updateClient = rewire('../../server/data/migration/fixtures/008/01-fix-sqlite-pg-format'), - serverTimezoneOffset = 60, - transfomDatesIntoUTCStub, rawStub; - - beforeEach(function () { - sandbox.stub(Date.prototype, 'getTimezoneOffset', function () { - return serverTimezoneOffset; - }); - }); - - afterEach(function () { - serverTimezoneOffset = 60; - }); - - describe('success', function () { - beforeEach(function () { - sandbox.stub(models.Settings, 'findOne', function (options) { - if (options.key === 'migrations') { - return Promise.resolve({attributes: {value: '{"006/01":"2016-09-05T12:39:11Z", "005/02": "2015-09-05T12:39:11Z"}'}}); - } - - return Promise.resolve(); - }); - - sandbox.stub(models.Settings, 'edit', function (data) { - data.key.should.eql('migrations'); - data.value.should.eql('{"005/02":"2015-09-05T12:39:11Z"}'); - return Promise.resolve(); - }); - - transfomDatesIntoUTCStub = sandbox.stub().returns(Promise.resolve()); - updateClient.__set__('transfomDatesIntoUTC', transfomDatesIntoUTCStub); - }); - - it('sqlite and server TZ is UTC: date format is integer', function (done) { - serverTimezoneOffset = 0; - configUtils.set('database:client', 'sqlite3'); - - rawStub = sandbox.stub().returns(Promise.resolve([{created_at: Date.now()}])); - - updateClient({transacting: {raw: rawStub}}, loggerStub) - .then(function () { - models.Settings.edit.callCount.should.eql(1); - models.Settings.findOne.callCount.should.eql(1); - transfomDatesIntoUTCStub.callCount.should.eql(1); - done(); - }) - .catch(done); - }); - }); - - describe('error', function () { - it('skip mysql', function (done) { - configUtils.set('database:client', 'mysql'); - - updateClient({}, loggerStub) - .then(function () { - loggerStub.warn.called.should.be.true(); - done(); - }) - .catch(done); - }); - - it('skip sqlite and non UTC server timezone', function (done) { - configUtils.set('database:client', 'sqlite3'); - rawStub = sandbox.stub().returns(Promise.resolve([{created_at: moment().format('YYYY-MM-DD HH:mm:ss')}])); - - updateClient({transacting: {raw:rawStub}}, loggerStub) - .then(function () { - loggerStub.warn.called.should.be.true(); - done(); - }) - .catch(done); - }); - - it('skip sqlite with UTC server timezone, but correct format', function (done) { - configUtils.set('database:client', 'sqlite3'); - serverTimezoneOffset = 0; - - rawStub = sandbox.stub().returns(Promise.resolve([{created_at: moment().format('YYYY-MM-DD HH:mm:ss')}])); - - updateClient({transacting: {raw: rawStub}}, loggerStub) - .then(function () { - loggerStub.warn.called.should.be.true(); - done(); - }) - .catch(done); - }); - }); - }); - }); - }); - }); - - describe('Populate 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 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()), - permsAddStub = sandbox.stub(models.Permission, 'add').returns(Promise.resolve()), - - // Existence checks - postOneStub = sandbox.stub(models.Post, 'findOne').returns(Promise.resolve()), - tagOneStub = sandbox.stub(models.Tag, 'findOne').returns(Promise.resolve()), - roleOneStub = sandbox.stub(models.Role, 'findOne').returns(Promise.resolve()), - clientOneStub = sandbox.stub(models.Client, 'findOne').returns(Promise.resolve()), - permOneStub = sandbox.stub(models.Permission, 'findOne').returns(Promise.resolve()), - - // Relations - fromItem = { - related: sandbox.stub().returnsThis(), - findWhere: sandbox.stub().returns({}) - }, - toItem = [{get: sandbox.stub()}], - modelMethodStub = {filter: sandbox.stub().returns(toItem), find: sandbox.stub().returns(fromItem)}, - permsAllStub = sandbox.stub(models.Permission, 'findAll').returns(Promise.resolve(modelMethodStub)), - rolesAllStub = sandbox.stub(models.Role, 'findAll').returns(Promise.resolve(modelMethodStub)), - postsAllStub = sandbox.stub(models.Post, 'findAll').returns(Promise.resolve(modelMethodStub)), - tagsAllStub = sandbox.stub(models.Tag, 'findAll').returns(Promise.resolve(modelMethodStub)), - - // Create Owner - userAddStub = sandbox.stub(models.User, 'add').returns(Promise.resolve({})); - roleOneStub.onCall(4).returns(Promise.resolve({id: 1})); - - populate(loggerStub).then(function () { - loggerStub.info.calledTwice.should.be.true(); - loggerStub.warn.called.should.be.false(); - - postOneStub.calledOnce.should.be.true(); - postAddStub.calledOnce.should.be.true(); - tagOneStub.calledOnce.should.be.true(); - tagAddStub.calledOnce.should.be.true(); - roleOneStub.callCount.should.be.aboveOrEqual(4); - roleAddStub.callCount.should.eql(4); - clientOneStub.calledThrice.should.be.true(); - clientAddStub.calledThrice.should.be.true(); - - permOneStub.callCount.should.eql(48); - permsAddStub.called.should.be.true(); - permsAddStub.callCount.should.eql(48); - - permsAllStub.calledOnce.should.be.true(); - rolesAllStub.calledOnce.should.be.true(); - postsAllStub.calledOnce.should.be.true(); - tagsAllStub.calledOnce.should.be.true(); - - // Relations - modelMethodStub.filter.called.should.be.true(); - // 29 permissions, 1 tag - modelMethodStub.filter.callCount.should.eql(29 + 1); - modelMethodStub.find.called.should.be.true(); - // 3 roles, 1 post - modelMethodStub.find.callCount.should.eql(3 + 1); - - // Create Owner - roleOneStub.callCount.should.eql(5); - userAddStub.calledOnce.should.be.true(); - - done(); - }).catch(done); - }); - - describe('Create Owner', function () { - var createOwner = populate.__get__('createOwner'), - roleOneStub, userAddStub; - - beforeEach(function () { - roleOneStub = sandbox.stub(models.Role, 'findOne'); - userAddStub = sandbox.stub(models.User, 'add'); - }); - - it('createOwner will add user if owner role is present', function (done) { - roleOneStub.returns(Promise.resolve({id: 1})); - userAddStub.returns(Promise.resolve({})); - - 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(); - - done(); - }).catch(done); - }); - - it('createOwner does not add user if owner role is not present', function (done) { - roleOneStub.returns(Promise.resolve()); - userAddStub.returns(Promise.resolve({})); - - createOwner().then(function () { - roleOneStub.calledOnce.should.be.true(); - userAddStub.called.should.be.false(); - - done(); - }).catch(done); - }); - }); - }); -}); diff --git a/core/test/unit/migration_spec.js b/core/test/unit/migration_spec.js index facb7d61fe..53c190b121 100644 --- a/core/test/unit/migration_spec.js +++ b/core/test/unit/migration_spec.js @@ -5,25 +5,16 @@ var should = require('should'), Promise = require('bluebird'), crypto = require('crypto'), fs = require('fs'), - - // Stuff we are testing - db = require('../../server/data/db'), errors = require('../../server/errors'), models = require('../../server/models'), exporter = require('../../server/data/export'), schema = require('../../server/data/schema'), - migration = rewire('../../server/data/migration'), fixtures = require('../../server/data/migration/fixtures'), populate = require('../../server/data/migration/populate'), update = rewire('../../server/data/migration/update'), - updates004 = require('../../server/data/migration/004'), - updates005 = require('../../server/data/migration/005'), - updates008 = require('../../server/data/migration/008'), - defaultSettings = schema.defaultSettings, schemaTables = Object.keys(schema.tables), - sandbox = sinon.sandbox.create(); // Check version integrity @@ -255,1312 +246,4 @@ describe('Migrations', function () { (response.error instanceof errors.DatabaseVersion).should.eql(true); }); }); - - describe('Update', function () { - describe('Update function', function () { - var resetBackup, backupStub, fixturesStub, setDbStub, versionsSpy, tasksSpy, transactionStub, transaction; - - beforeEach(function () { - transaction = { - rollback: sandbox.stub(), - commit: sandbox.stub() - }; - - // Stubs - backupStub = sandbox.stub().returns(new Promise.resolve()); - fixturesStub = sandbox.stub(fixtures, 'update').returns(new Promise.resolve()); - setDbStub = sandbox.stub(schema.versioning, 'setDatabaseVersion').returns(new Promise.resolve()); - - transactionStub = sandbox.stub(db.knex, 'transaction', function (transactionStart) { - return new Promise(function () { - transactionStart(transaction); - }); - }); - - // Spys - versionsSpy = sandbox.spy(schema.versioning, 'getMigrationVersions'); - tasksSpy = sandbox.spy(schema.versioning, 'getUpdateDatabaseTasks'); - - // Internal overrides - resetBackup = update.__set__('backup', backupStub); - }); - - afterEach(function () { - resetBackup(); - }); - - describe('Pre & post update process', function () { - var updateDatabaseSchemaStub, updateDatabaseSchemaReset; - - beforeEach(function () { - // For these tests, stub out the actual update task - updateDatabaseSchemaStub = sandbox.stub().returns(new Promise.resolve()); - updateDatabaseSchemaReset = update.__set__('updateDatabaseSchema', updateDatabaseSchemaStub); - }); - - afterEach(function () { - updateDatabaseSchemaReset(); - }); - - it('should attempt to run the pre & post update tasks correctly', function (done) { - // Execute - update.execute({fromVersion: '100', toVersion: '102'}).then(function () { - // getMigrationVersions should be called with the correct versions - versionsSpy.calledOnce.should.be.true(); - versionsSpy.calledWith('100', '102').should.be.true(); - - // It should attempt to do a backup - backupStub.calledOnce.should.be.true(); - - // Now it's going to try to actually do the update... - updateDatabaseSchemaStub.calledTwice.should.be.true(); - updateDatabaseSchemaStub.firstCall.calledWith([], loggerStub, { - transacting: transaction, - context: {internal: true} - }).should.be.true(); - updateDatabaseSchemaStub.secondCall.calledWith([], loggerStub, { - transacting: transaction, - context: {internal: true} - }).should.be.true(); - - // Then fixture updates - fixturesStub.calledTwice.should.be.true(); - // And finally, set the new DB version - setDbStub.calledTwice.should.be.true(); - - transaction.commit.called.should.eql(true); - transaction.rollback.called.should.eql(false); - - // Just to be sure, lets assert the call order - sinon.assert.callOrder( - versionsSpy, backupStub, updateDatabaseSchemaStub, fixturesStub, setDbStub - ); - - done(); - }).catch(done); - }); - - it('should upgrade from minimum version, if force migration is set', function (done) { - var migrateToDatabaseVersionStub = sandbox.stub().returns(new Promise.resolve()), - migrateToDatabaseVersionReset = update.__set__('migrateToDatabaseVersion', migrateToDatabaseVersionStub); - - update.execute({fromVersion: '005', toVersion: '006', forceMigration: true}).then(function () { - // getMigrationVersions should be called with the correct versions - versionsSpy.calledOnce.should.be.true(); - versionsSpy.calledWith('003', '006').should.be.true(); - versionsSpy.returned(['003', '004', '005', '006']).should.be.true(); - - // It should try to do the update - migrateToDatabaseVersionStub.callCount.should.eql(3); - migrateToDatabaseVersionStub.firstCall.args[0].should.eql('004'); - migrateToDatabaseVersionStub.secondCall.args[0].should.eql('005'); - migrateToDatabaseVersionStub.thirdCall.args[0].should.eql('006'); - - migrateToDatabaseVersionReset(); - done(); - }).catch(done); - }); - - it('should do an UPDATE if newer database version is higher', function (done) { - var migrateToDatabaseVersionStub = sandbox.stub().returns(new Promise.resolve()), - migrateToDatabaseVersionReset = update.__set__('migrateToDatabaseVersion', migrateToDatabaseVersionStub); - - update.execute({fromVersion: '004', toVersion: '005'}).then(function () { - versionsSpy.calledOnce.should.be.true(); - versionsSpy.calledWith('004', '005').should.be.true(); - versionsSpy.returned(['004', '005']).should.be.true(); - - migrateToDatabaseVersionStub.callCount.should.eql(1); - migrateToDatabaseVersionStub.firstCall.args[0].should.eql('005'); - - migrateToDatabaseVersionReset(); - - done(); - }).catch(done); - }); - - it('should do an UPDATE if default version is significantly higher', function (done) { - var migrateToDatabaseVersionStub = sandbox.stub().returns(new Promise.resolve()), - migrateToDatabaseVersionReset = update.__set__('migrateToDatabaseVersion', migrateToDatabaseVersionStub); - - update.execute({fromVersion: '004', toVersion: '010'}).then(function () { - versionsSpy.calledOnce.should.be.true(); - versionsSpy.calledWith('004', '010').should.be.true(); - versionsSpy.returned(['004', '005', '006', '007', '008', '009', '010']).should.be.true(); - - migrateToDatabaseVersionStub.callCount.should.eql(6); - migrateToDatabaseVersionStub.firstCall.args[0].should.eql('005'); - migrateToDatabaseVersionStub.lastCall.args[0].should.eql('010'); - - migrateToDatabaseVersionReset(); - - done(); - }).catch(done); - }); - - it('should do an UPDATE even if versions are the same, when FORCE_MIGRATION set', function (done) { - var migrateToDatabaseVersionStub = sandbox.stub().returns(new Promise.resolve()), - migrateToDatabaseVersionReset = update.__set__('migrateToDatabaseVersion', migrateToDatabaseVersionStub); - - update.execute({fromVersion: '004', toVersion: '004', forceMigration: true}).then(function () { - versionsSpy.calledOnce.should.be.true(); - versionsSpy.calledWith('003', '004').should.be.true(); - versionsSpy.returned(['003', '004']).should.be.true(); - - migrateToDatabaseVersionStub.callCount.should.eql(1); - migrateToDatabaseVersionStub.firstCall.args[0].should.eql('004'); - migrateToDatabaseVersionReset(); - - done(); - }).catch(done); - }); - }); - - describe('Update to 004', function () { - it('should call all the 004 database upgrade tasks', function (done) { - // Setup - // Create a new stub, this will replace sequence, so that db calls don't actually get run - var sequenceStub = sandbox.stub(), - sequenceReset = update.__set__('sequence', sequenceStub); - - sequenceStub.returns(Promise.resolve([])); - - // Execute - update.execute({fromVersion: '003', toVersion: '004'}).then(function () { - versionsSpy.calledOnce.should.be.true(); - versionsSpy.calledWith('003', '004').should.be.true(); - - // returns the same, but get sliced afterwards! - versionsSpy.returned(['003', '004']).should.be.true(); - - tasksSpy.calledOnce.should.be.true(); - tasksSpy.calledWith('004', loggerStub).should.be.true(); - tasksSpy.firstCall.returnValue.should.be.an.Array().with.lengthOf(5); - - transaction.commit.called.should.eql(true); - transaction.rollback.called.should.eql(false); - - sequenceStub.calledOnce.should.be.true(); - - sequenceStub.firstCall.calledWith(sinon.match.array, { - transacting: transaction, - context: { - internal: true - } - }, loggerStub).should.be.true(); - - sequenceStub.firstCall.args[0].should.be.an.Array().with.lengthOf(5); - sequenceStub.firstCall.args[0][0].should.be.a.Function().with.property('name', 'addTourColumnToUsers'); - sequenceStub.firstCall.args[0][1].should.be.a.Function().with.property('name', 'addSortOrderColumnToPostsTags'); - sequenceStub.firstCall.args[0][2].should.be.a.Function().with.property('name', 'addManyColumnsToClients'); - sequenceStub.firstCall.args[0][3].should.be.a.Function().with.property('name', 'addClientTrustedDomainsTable'); - sequenceStub.firstCall.args[0][4].should.be.a.Function().with.property('name', 'dropUniqueOnClientsSecret'); - - // Reset sequence - sequenceReset(); - done(); - }).catch(done); - }); - - describe('Tasks:', function () { - var addColumnStub, createTableStub, getIndexesStub, dropUniqueStub, - knexStub, knexMock; - - beforeEach(function () { - knexMock = sandbox.stub().returns({}); - knexMock.schema = { - hasTable: sandbox.stub(), - hasColumn: sandbox.stub() - }; - // this MUST use sinon, not sandbox, see sinonjs/sinon#781 - knexStub = sinon.stub(db, 'knex', { - get: function () { - return knexMock; - } - }); - - addColumnStub = sandbox.stub(schema.commands, 'addColumn'); - createTableStub = sandbox.stub(schema.commands, 'createTable'); - getIndexesStub = sandbox.stub(schema.commands, 'getIndexes'); - dropUniqueStub = sandbox.stub(schema.commands, 'dropUnique'); - }); - - afterEach(function () { - knexStub.restore(); - }); - - it('should have tasks for 004', function () { - should.exist(updates004); - updates004.should.be.an.Array().with.lengthOf(5); - }); - - 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 - addTourColumn({transacting: knexMock}, loggerStub) - .then(function () { - done(new Error('expected table not found error')); - }) - .catch(function (err) { - should.exist(err); - err.message.should.eql('Table does not exist!'); - knexMock.schema.hasTable.calledOnce.should.be.true(); - knexMock.schema.hasTable.calledWith('users').should.be.true(); - - knexMock.schema.hasColumn.called.should.be.false(); - - addColumnStub.called.should.be.false(); - - loggerStub.info.called.should.be.false(); - loggerStub.warn.calledOnce.should.be.false(); - done(); - }); - }); - - it('does not try to add a new column if the column already exists', function (done) { - // Setup - knexMock.schema.hasTable.withArgs('users').returns(new Promise.resolve(true)); - knexMock.schema.hasColumn.withArgs('users', 'tour').returns(new Promise.resolve(true)); - - // Execute - addTourColumn({transacting: knexMock}, loggerStub).then(function () { - knexMock.schema.hasTable.calledOnce.should.be.true(); - knexMock.schema.hasTable.calledWith('users').should.be.true(); - - knexMock.schema.hasColumn.calledOnce.should.be.true(); - knexMock.schema.hasColumn.calledWith('users', 'tour').should.be.true(); - - addColumnStub.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 - knexMock.schema.hasTable.withArgs('users').returns(new Promise.resolve(true)); - knexMock.schema.hasColumn.withArgs('users', 'tour').returns(new Promise.resolve(false)); - - // Execute - addTourColumn({transacting: knexMock}, loggerStub).then(function () { - knexMock.schema.hasTable.calledOnce.should.be.true(); - knexMock.schema.hasTable.calledWith('users').should.be.true(); - - knexMock.schema.hasColumn.calledOnce.should.be.true(); - knexMock.schema.hasColumn.calledWith('users', 'tour').should.be.true(); - - addColumnStub.calledOnce.should.be.true(); - addColumnStub.calledWith('users', 'tour').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 () { - 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 - addSortOrderColumn({transacting: knexMock}, loggerStub) - .then(function () { - done(new Error('expected table not found error')); - }) - .catch(function (err) { - should.exist(err); - err.message.should.eql('Table does not exist!'); - knexMock.schema.hasTable.calledOnce.should.be.true(); - knexMock.schema.hasTable.calledWith('posts_tags').should.be.true(); - - knexMock.schema.hasColumn.called.should.be.false(); - - addColumnStub.called.should.be.false(); - - loggerStub.info.called.should.be.false(); - loggerStub.warn.calledOnce.should.be.false(); - done(); - }); - }); - - it('does not try to add a new column if the column already exists', function (done) { - // Setup - 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 - addSortOrderColumn({transacting: knexMock}, loggerStub).then(function () { - knexMock.schema.hasTable.calledOnce.should.be.true(); - knexMock.schema.hasTable.calledWith('posts_tags').should.be.true(); - - knexMock.schema.hasColumn.calledOnce.should.be.true(); - knexMock.schema.hasColumn.calledWith('posts_tags', 'sort_order').should.be.true(); - - addColumnStub.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 - 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 - addSortOrderColumn({transacting: knexMock}, loggerStub).then(function () { - knexMock.schema.hasTable.calledOnce.should.be.true(); - knexMock.schema.hasTable.calledWith('posts_tags').should.be.true(); - - knexMock.schema.hasColumn.calledOnce.should.be.true(); - knexMock.schema.hasColumn.calledWith('posts_tags', 'sort_order').should.be.true(); - - addColumnStub.calledOnce.should.be.true(); - addColumnStub.calledWith('posts_tags', 'sort_order').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 () { - 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 - addClientColumns({transacting: knexMock}, loggerStub) - .then(function () { - done(new Error('expected table not found error')); - }) - .catch(function (err) { - should.exist(err); - err.message.should.eql('Table does not exist!'); - knexMock.schema.hasTable.calledOnce.should.be.true(); - knexMock.schema.hasTable.calledWith('clients').should.be.true(); - - knexMock.schema.hasColumn.called.should.be.false(); - - addColumnStub.called.should.be.false(); - - loggerStub.info.called.should.be.false(); - loggerStub.warn.calledOnce.should.be.false(); - done(); - }); - }); - - it('does not try to add new columns if the columns already exist', function (done) { - // Setup - 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)); - knexMock.schema.hasColumn.withArgs('clients', 'status').returns(new Promise.resolve(true)); - knexMock.schema.hasColumn.withArgs('clients', 'type').returns(new Promise.resolve(true)); - knexMock.schema.hasColumn.withArgs('clients', 'description').returns(new Promise.resolve(true)); - - // Execute - addClientColumns({transacting: knexMock}, loggerStub).then(function () { - knexMock.schema.hasTable.calledOnce.should.be.true(); - knexMock.schema.hasTable.calledWith('clients').should.be.true(); - - knexMock.schema.hasColumn.callCount.should.eql(5); - knexMock.schema.hasColumn.calledWith('clients', 'redirection_uri').should.be.true(); - knexMock.schema.hasColumn.calledWith('clients', 'logo').should.be.true(); - knexMock.schema.hasColumn.calledWith('clients', 'status').should.be.true(); - knexMock.schema.hasColumn.calledWith('clients', 'type').should.be.true(); - knexMock.schema.hasColumn.calledWith('clients', 'description').should.be.true(); - - addColumnStub.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 - 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)); - knexMock.schema.hasColumn.withArgs('clients', 'status').returns(new Promise.resolve(false)); - knexMock.schema.hasColumn.withArgs('clients', 'type').returns(new Promise.resolve(false)); - knexMock.schema.hasColumn.withArgs('clients', 'description').returns(new Promise.resolve(false)); - - // Execute - addClientColumns({transacting: knexMock}, loggerStub).then(function () { - knexMock.schema.hasTable.calledOnce.should.be.true(); - knexMock.schema.hasTable.calledWith('clients').should.be.true(); - - knexMock.schema.hasColumn.callCount.should.eql(5); - knexMock.schema.hasColumn.calledWith('clients', 'redirection_uri').should.be.true(); - knexMock.schema.hasColumn.calledWith('clients', 'logo').should.be.true(); - knexMock.schema.hasColumn.calledWith('clients', 'status').should.be.true(); - knexMock.schema.hasColumn.calledWith('clients', 'type').should.be.true(); - knexMock.schema.hasColumn.calledWith('clients', 'description').should.be.true(); - - addColumnStub.callCount.should.eql(5); - addColumnStub.calledWith('clients', 'redirection_uri').should.be.true(); - addColumnStub.calledWith('clients', 'logo').should.be.true(); - addColumnStub.calledWith('clients', 'status').should.be.true(); - addColumnStub.calledWith('clients', 'type').should.be.true(); - addColumnStub.calledWith('clients', 'description').should.be.true(); - - 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 - 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)); - knexMock.schema.hasColumn.withArgs('clients', 'status').returns(new Promise.resolve(true)); - knexMock.schema.hasColumn.withArgs('clients', 'type').returns(new Promise.resolve(false)); - knexMock.schema.hasColumn.withArgs('clients', 'description').returns(new Promise.resolve(true)); - - // Execute - addClientColumns({transacting: knexMock}, loggerStub).then(function () { - knexMock.schema.hasTable.calledOnce.should.be.true(); - knexMock.schema.hasTable.calledWith('clients').should.be.true(); - - knexMock.schema.hasColumn.callCount.should.eql(5); - knexMock.schema.hasColumn.calledWith('clients', 'redirection_uri').should.be.true(); - knexMock.schema.hasColumn.calledWith('clients', 'logo').should.be.true(); - knexMock.schema.hasColumn.calledWith('clients', 'status').should.be.true(); - knexMock.schema.hasColumn.calledWith('clients', 'type').should.be.true(); - knexMock.schema.hasColumn.calledWith('clients', 'description').should.be.true(); - - addColumnStub.callCount.should.eql(2); - addColumnStub.calledWith('clients', 'logo').should.be.true(); - addColumnStub.calledWith('clients', 'type').should.be.true(); - - loggerStub.info.callCount.should.eql(2); - loggerStub.warn.callCount.should.eql(3); - - done(); - }).catch(done); - }); - }); - - 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 - addTrustedDomains({transacting: knexMock}, loggerStub) - .then(function () { - knexMock.schema.hasTable.calledOnce.should.be.true(); - knexMock.schema.hasTable.calledWith('client_trusted_domains').should.be.true(); - - knexMock.schema.hasColumn.called.should.be.false(); - - addColumnStub.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('client_trusted_domains').returns(new Promise.resolve(false)); - - // Execute - addTrustedDomains({transacting: knexMock}, 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(); - - loggerStub.info.calledOnce.should.be.true(); - loggerStub.warn.called.should.be.false(); - - done(); - }).catch(done); - }); - }); - - 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( - ['clients_slug_unique', 'clients_name_unique', 'clients_secret_unique']) - ); - knexMock.schema.hasTable.withArgs('clients').returns(new Promise.resolve(false)); - - // Execute - dropUnique({transacting: knexMock}, loggerStub) - .then(function () { - done(new Error('expected table not found error')); - }) - .catch(function (err) { - should.exist(err); - err.message.should.eql('Table does not exist!'); - knexMock.schema.hasTable.calledOnce.should.be.true(); - knexMock.schema.hasTable.calledWith('clients').should.be.true(); - - knexMock.schema.hasColumn.called.should.be.false(); - - addColumnStub.called.should.be.false(); - - loggerStub.info.called.should.be.false(); - loggerStub.warn.calledOnce.should.be.false(); - done(); - }); - }); - - it('does not try to drop unique if the index does not exist', function (done) { - // Setup - knexMock.schema.hasTable.withArgs('clients').returns(new Promise.resolve(true)); - - getIndexesStub.withArgs('clients').returns(new Promise.resolve( - ['clients_slug_unique', 'clients_name_unique']) - ); - - // Execute - dropUnique({transacting: knexMock}, loggerStub).then(function () { - knexMock.schema.hasTable.calledOnce.should.be.true(); - knexMock.schema.hasTable.calledWith('clients').should.be.true(); - - getIndexesStub.calledOnce.should.be.true(); - getIndexesStub.calledWith('clients').should.be.true(); - - dropUniqueStub.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 - knexMock.schema.hasTable.withArgs('clients').returns(new Promise.resolve(true)); - - getIndexesStub.withArgs('clients').returns(new Promise.resolve( - ['clients_slug_unique', 'clients_name_unique', 'clients_secret_unique']) - ); - - // Execute - dropUnique({transacting: knexMock}, loggerStub).then(function () { - knexMock.schema.hasTable.calledOnce.should.be.true(); - knexMock.schema.hasTable.calledWith('clients').should.be.true(); - - getIndexesStub.calledOnce.should.be.true(); - getIndexesStub.calledWith('clients').should.be.true(); - - dropUniqueStub.calledOnce.should.be.true(); - dropUniqueStub.calledWith('clients', 'secret').should.be.true(); - - loggerStub.info.calledOnce.should.be.true(); - loggerStub.warn.called.should.be.false(); - - done(); - }).catch(done); - }); - }); - }); - }); - - describe('Update to 005', function () { - it('should call all the 005 database upgrade tasks', function (done) { - // Setup - // Create a new stub, this will replace sequence, so that db calls don't actually get run - var sequenceStub = sandbox.stub(), - sequenceReset = update.__set__('sequence', sequenceStub); - - sequenceStub.returns(Promise.resolve([])); - - // Execute - update.execute({fromVersion: '004', toVersion: '005'}).then(function () { - versionsSpy.calledOnce.should.be.true(); - versionsSpy.calledWith('004', '005').should.be.true(); - versionsSpy.returned(['004', '005']).should.be.true(); - - tasksSpy.calledOnce.should.be.true(); - tasksSpy.calledWith('005', loggerStub).should.be.true(); - tasksSpy.firstCall.returnValue.should.be.an.Array().with.lengthOf(5); - - sequenceStub.calledOnce.should.be.true(); - - sequenceStub.firstCall.calledWith(sinon.match.array, { - transacting: transaction, - context: { - internal: true - } - }, loggerStub).should.be.true(); - - sequenceStub.firstCall.args[0].should.be.an.Array().with.lengthOf(5); - sequenceStub.firstCall.args[0][0].should.be.a.Function().with.property('name', 'dropHiddenColumnFromTags'); - sequenceStub.firstCall.args[0][1].should.be.a.Function().with.property('name', 'addVisibilityColumnToKeyTables'); - sequenceStub.firstCall.args[0][2].should.be.a.Function().with.property('name', 'addMobiledocColumnToPosts'); - sequenceStub.firstCall.args[0][3].should.be.a.Function().with.property('name', 'addSocialMediaColumnsToUsers'); - sequenceStub.firstCall.args[0][4].should.be.a.Function().with.property('name', 'addSubscribersTable'); - - // Reset sequence - sequenceReset(); - done(); - }).catch(done); - }); - - describe('Tasks:', function () { - var dropColumnStub, addColumnStub, createTableStub, - knexStub, knexMock; - - beforeEach(function () { - knexMock = sandbox.stub().returns({}); - knexMock.schema = { - hasTable: sandbox.stub(), - hasColumn: sandbox.stub() - }; - // this MUST use sinon, not sandbox, see sinonjs/sinon#781 - knexStub = sinon.stub(db, 'knex', { - get: function () { - return knexMock; - } - }); - - dropColumnStub = sandbox.stub(schema.commands, 'dropColumn'); - addColumnStub = sandbox.stub(schema.commands, 'addColumn'); - createTableStub = sandbox.stub(schema.commands, 'createTable'); - }); - - afterEach(function () { - knexStub.restore(); - }); - - it('should have tasks for 005', function () { - should.exist(updates005); - 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 - dropHiddenColumn({transacting: knexMock}, loggerStub) - .then(function () { - done(new Error('expected table not found error')); - }) - .catch(function (err) { - should.exist(err); - err.message.should.eql('Table does not exist!'); - knexMock.schema.hasTable.calledOnce.should.be.true(); - knexMock.schema.hasTable.calledWith('tags').should.be.true(); - - knexMock.schema.hasColumn.called.should.be.false(); - - addColumnStub.called.should.be.false(); - - loggerStub.info.called.should.be.false(); - loggerStub.warn.calledOnce.should.be.false(); - done(); - }); - }); - - it('does not try to drop column if the column does not exist', function (done) { - // Setup - knexMock.schema.hasTable.withArgs('tags').returns(Promise.resolve(true)); - knexMock.schema.hasColumn.withArgs('tags', 'hidden').returns(Promise.resolve(false)); - - // Execute - dropHiddenColumn({transacting: knexMock}, loggerStub).then(function () { - knexMock.schema.hasTable.calledOnce.should.be.true(); - knexMock.schema.hasTable.calledWith('tags').should.be.true(); - - knexMock.schema.hasColumn.calledOnce.should.be.true(); - knexMock.schema.hasColumn.calledWith('tags', 'hidden').should.be.true(); - - dropColumnStub.called.should.be.false(); - - loggerStub.info.called.should.be.false(); - loggerStub.warn.calledOnce.should.be.true(); - - done(); - }).catch(done); - }); - - it('tries to add drop column if table and column are both present', function (done) { - // Setup - knexMock.schema.hasTable.withArgs('tags').returns(Promise.resolve(true)); - knexMock.schema.hasColumn.withArgs('tags', 'hidden').returns(Promise.resolve(true)); - - // Execute - dropHiddenColumn({transacting: knexMock}, loggerStub).then(function () { - knexMock.schema.hasTable.calledOnce.should.be.true(); - knexMock.schema.hasTable.calledWith('tags').should.be.true(); - - knexMock.schema.hasColumn.calledOnce.should.be.true(); - knexMock.schema.hasColumn.calledWith('tags', 'hidden').should.be.true(); - - dropColumnStub.calledOnce.should.be.true(); - dropColumnStub.calledWith('tags', 'hidden').should.be.true(); - - loggerStub.info.calledOnce.should.be.true(); - loggerStub.warn.called.should.be.false(); - - done(); - }).catch(done); - }); - }); - - 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)); - knexMock.schema.hasTable.withArgs('tags').returns(Promise.resolve(false)); - knexMock.schema.hasTable.withArgs('users').returns(Promise.resolve(false)); - - // Execute - addVisibilityColumn({transacting: knexMock}, loggerStub) - .then(function () { - done(new Error('expected table not found error')); - }) - .catch(function (err) { - should.exist(err); - err.message.should.eql('Table does not exist!'); - knexMock.schema.hasTable.calledOnce.should.be.true(); - knexMock.schema.hasTable.firstCall.calledWith('posts').should.be.true(); - - knexMock.schema.hasColumn.called.should.be.false(); - - addColumnStub.called.should.be.false(); - - loggerStub.info.called.should.be.false(); - loggerStub.warn.calledOnce.should.be.false(); - done(); - }); - }); - - it('does not try to add new columns if the columns already exist', function (done) { - // Setup - knexMock.schema.hasTable.withArgs('posts').returns(Promise.resolve(true)); - knexMock.schema.hasTable.withArgs('tags').returns(Promise.resolve(true)); - knexMock.schema.hasTable.withArgs('users').returns(Promise.resolve(true)); - - knexMock.schema.hasColumn.withArgs('posts', 'visibility').returns(Promise.resolve(true)); - knexMock.schema.hasColumn.withArgs('tags', 'visibility').returns(Promise.resolve(true)); - knexMock.schema.hasColumn.withArgs('users', 'visibility').returns(Promise.resolve(true)); - - // Execute - addVisibilityColumn({transacting: knexMock}, 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(); - knexMock.schema.hasTable.calledWith('users').should.be.true(); - - knexMock.schema.hasColumn.calledThrice.should.be.true(); - knexMock.schema.hasColumn.calledWith('posts', 'visibility').should.be.true(); - knexMock.schema.hasColumn.calledWith('tags', 'visibility').should.be.true(); - knexMock.schema.hasColumn.calledWith('users', 'visibility').should.be.true(); - - addColumnStub.called.should.be.false(); - - loggerStub.info.called.should.be.false(); - loggerStub.warn.calledThrice.should.be.true(); - - done(); - }).catch(done); - }); - - it('tries to add new columns if table is present but columns are not', function (done) { - // Setup - knexMock.schema.hasTable.withArgs('posts').returns(Promise.resolve(true)); - knexMock.schema.hasTable.withArgs('tags').returns(Promise.resolve(true)); - knexMock.schema.hasTable.withArgs('users').returns(Promise.resolve(true)); - - knexMock.schema.hasColumn.withArgs('posts', 'visibility').returns(Promise.resolve(false)); - knexMock.schema.hasColumn.withArgs('tags', 'visibility').returns(Promise.resolve(false)); - knexMock.schema.hasColumn.withArgs('users', 'visibility').returns(Promise.resolve(false)); - - // Execute - addVisibilityColumn({transacting: knexMock}, 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(); - knexMock.schema.hasTable.calledWith('users').should.be.true(); - - knexMock.schema.hasColumn.calledThrice.should.be.true(); - knexMock.schema.hasColumn.calledWith('posts', 'visibility').should.be.true(); - knexMock.schema.hasColumn.calledWith('tags', 'visibility').should.be.true(); - knexMock.schema.hasColumn.calledWith('users', 'visibility').should.be.true(); - - addColumnStub.calledThrice.should.be.true(); - addColumnStub.calledWith('posts', 'visibility').should.be.true(); - addColumnStub.calledWith('tags', 'visibility').should.be.true(); - addColumnStub.calledWith('users', 'visibility').should.be.true(); - - loggerStub.info.calledThrice.should.be.true(); - loggerStub.warn.called.should.be.false(); - - done(); - }).catch(done); - }); - - it('will only try to add columns that do not exist', function (done) { - // Setup - knexMock.schema.hasTable.withArgs('posts').returns(Promise.resolve(true)); - knexMock.schema.hasTable.withArgs('tags').returns(Promise.resolve(true)); - knexMock.schema.hasTable.withArgs('users').returns(Promise.resolve(true)); - - knexMock.schema.hasColumn.withArgs('posts', 'visibility').returns(Promise.resolve(false)); - knexMock.schema.hasColumn.withArgs('tags', 'visibility').returns(Promise.resolve(true)); - knexMock.schema.hasColumn.withArgs('users', 'visibility').returns(Promise.resolve(false)); - // Execute - addVisibilityColumn({transacting: knexMock}, 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(); - knexMock.schema.hasTable.calledWith('users').should.be.true(); - - knexMock.schema.hasColumn.calledThrice.should.be.true(); - knexMock.schema.hasColumn.calledWith('posts', 'visibility').should.be.true(); - knexMock.schema.hasColumn.calledWith('tags', 'visibility').should.be.true(); - knexMock.schema.hasColumn.calledWith('users', 'visibility').should.be.true(); - - addColumnStub.calledTwice.should.be.true(); - addColumnStub.calledWith('posts', 'visibility').should.be.true(); - addColumnStub.calledWith('tags', 'visibility').should.be.false(); - addColumnStub.calledWith('users', 'visibility').should.be.true(); - - loggerStub.info.calledTwice.should.be.true(); - loggerStub.warn.calledOnce.should.be.true(); - - done(); - }).catch(done); - }); - }); - - 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 - addMobiledocColumn({transacting: knexMock}, loggerStub) - .then(function () { - done(new Error('expected table not found error')); - }) - .catch(function (err) { - should.exist(err); - err.message.should.eql('Table does not exist!'); - knexMock.schema.hasTable.calledOnce.should.be.true(); - knexMock.schema.hasTable.firstCall.calledWith('posts').should.be.true(); - - knexMock.schema.hasColumn.called.should.be.false(); - - addColumnStub.called.should.be.false(); - - loggerStub.info.called.should.be.false(); - loggerStub.warn.calledOnce.should.be.false(); - done(); - }); - }); - - it('does not try to add a new column if the column already exists', function (done) { - // Setup - knexMock.schema.hasTable.withArgs('posts').returns(new Promise.resolve(true)); - knexMock.schema.hasColumn.withArgs('posts', 'mobiledoc').returns(Promise.resolve(true)); - - // Execute - addMobiledocColumn({transacting: knexMock}, loggerStub).then(function () { - knexMock.schema.hasTable.calledOnce.should.be.true(); - knexMock.schema.hasTable.calledWith('posts').should.be.true(); - - knexMock.schema.hasColumn.calledOnce.should.be.true(); - knexMock.schema.hasColumn.calledWith('posts', 'mobiledoc').should.be.true(); - - addColumnStub.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 - knexMock.schema.hasTable.withArgs('posts').returns(Promise.resolve(true)); - knexMock.schema.hasColumn.withArgs('posts', 'mobiledoc').returns(Promise.resolve(false)); - - // Execute - addMobiledocColumn({transacting: knexMock}, loggerStub).then(function () { - knexMock.schema.hasTable.calledOnce.should.be.true(); - knexMock.schema.hasTable.calledWith('posts').should.be.true(); - - knexMock.schema.hasColumn.calledOnce.should.be.true(); - knexMock.schema.hasColumn.calledWith('posts', 'mobiledoc').should.be.true(); - - addColumnStub.calledOnce.should.be.true(); - addColumnStub.calledWith('posts', 'mobiledoc').should.be.true(); - - loggerStub.info.calledOnce.should.be.true(); - loggerStub.warn.called.should.be.false(); - - done(); - }).catch(done); - }); - }); - - 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 - addSocialMediaColumns({transacting: knexMock}, loggerStub) - .then(function () { - done(new Error('expected table not found error')); - }) - .catch(function (err) { - should.exist(err); - err.message.should.eql('Table does not exist!'); - knexMock.schema.hasTable.calledOnce.should.be.true(); - knexMock.schema.hasTable.firstCall.calledWith('users').should.be.true(); - - knexMock.schema.hasColumn.called.should.be.false(); - - addColumnStub.called.should.be.false(); - - loggerStub.info.called.should.be.false(); - loggerStub.warn.calledOnce.should.be.false(); - done(); - }); - }); - - it('does not try to add new columns if the columns already exist', function (done) { - // Setup - knexMock.schema.hasTable.withArgs('users').returns(Promise.resolve(true)); - knexMock.schema.hasColumn.withArgs('users', 'facebook').returns(Promise.resolve(true)); - knexMock.schema.hasColumn.withArgs('users', 'twitter').returns(Promise.resolve(true)); - - // Execute - addSocialMediaColumns({transacting: knexMock}, loggerStub).then(function () { - knexMock.schema.hasTable.calledOnce.should.be.true(); - knexMock.schema.hasTable.calledWith('users').should.be.true(); - - knexMock.schema.hasColumn.calledTwice.should.be.true(); - knexMock.schema.hasColumn.calledWith('users', 'facebook').should.be.true(); - knexMock.schema.hasColumn.calledWith('users', 'twitter').should.be.true(); - - addColumnStub.called.should.be.false(); - - loggerStub.info.called.should.be.false(); - loggerStub.warn.calledTwice.should.be.true(); - - done(); - }).catch(done); - }); - - it('tries to add new columns if table is present but columns are not', function (done) { - // Setup - knexMock.schema.hasTable.withArgs('users').returns(Promise.resolve(true)); - knexMock.schema.hasColumn.withArgs('users', 'facebook').returns(Promise.resolve(false)); - knexMock.schema.hasColumn.withArgs('users', 'twitter').returns(Promise.resolve(false)); - - // Execute - addSocialMediaColumns({transacting: knexMock}, loggerStub).then(function () { - knexMock.schema.hasTable.calledOnce.should.be.true(); - knexMock.schema.hasTable.calledWith('users').should.be.true(); - - knexMock.schema.hasColumn.calledTwice.should.be.true(); - knexMock.schema.hasColumn.calledWith('users', 'facebook').should.be.true(); - knexMock.schema.hasColumn.calledWith('users', 'twitter').should.be.true(); - - addColumnStub.calledTwice.should.be.true(); - addColumnStub.calledWith('users', 'facebook').should.be.true(); - addColumnStub.calledWith('users', 'twitter').should.be.true(); - - loggerStub.info.calledTwice.should.be.true(); - loggerStub.warn.called.should.be.false(); - - done(); - }).catch(done); - }); - - it('will only try to add columns that do not exist', function (done) { - // Setup - knexMock.schema.hasTable.withArgs('users').returns(Promise.resolve(true)); - knexMock.schema.hasColumn.withArgs('users', 'facebook').returns(Promise.resolve(false)); - knexMock.schema.hasColumn.withArgs('users', 'twitter').returns(Promise.resolve(true)); - - // Execute - addSocialMediaColumns({transacting: knexMock}, loggerStub).then(function () { - knexMock.schema.hasTable.calledOnce.should.be.true(); - knexMock.schema.hasTable.calledWith('users').should.be.true(); - - knexMock.schema.hasColumn.calledTwice.should.be.true(); - knexMock.schema.hasColumn.calledWith('users', 'facebook').should.be.true(); - knexMock.schema.hasColumn.calledWith('users', 'twitter').should.be.true(); - - addColumnStub.callCount.should.eql(1); - addColumnStub.calledWith('users', 'facebook').should.be.true(); - addColumnStub.calledWith('users', 'twitter').should.be.false(); - - loggerStub.info.calledOnce.should.be.true(); - loggerStub.warn.calledOnce.should.be.true(); - - done(); - }).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({transacting: knexMock}, 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({transacting: knexMock}, 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); - }); - }); - }); - }); - describe('Update to 008', function () { - it('should call all the 008 database upgrade tasks', function (done) { - // Setup - // Create a new stub, this will replace sequence, so that db calls don't actually get run - var sequenceStub = sandbox.stub(), - sequenceReset = update.__set__('sequence', sequenceStub); - - sequenceStub.returns(Promise.resolve([])); - - // Execute - update.execute({fromVersion: '007', toVersion: '008'}).then(function () { - versionsSpy.calledOnce.should.be.true(); - versionsSpy.calledWith('007', '008').should.be.true(); - versionsSpy.returned(['007', '008']).should.be.true(); - - tasksSpy.calledOnce.should.be.true(); - tasksSpy.calledWith('008', loggerStub).should.be.true(); - tasksSpy.firstCall.returnValue.should.be.an.Array().with.lengthOf(1); - - sequenceStub.calledOnce.should.be.true(); - - sequenceStub.firstCall.calledWith(sinon.match.array, { - transacting: transaction, - context: { - internal: true - } - }, loggerStub).should.be.true(); - - sequenceStub.firstCall.args[0].should.be.an.Array().with.lengthOf(1); - sequenceStub.firstCall.args[0][0].should.be.a.Function().with.property('name', 'addAmpColumnToPosts'); - - // Reset sequence - sequenceReset(); - done(); - }).catch(done); - }); - - describe('Tasks:', function () { - var dropColumnStub, addColumnStub, createTableStub, - knexStub, knexMock; - - beforeEach(function () { - knexMock = sandbox.stub().returns({}); - knexMock.schema = { - hasTable: sandbox.stub(), - hasColumn: sandbox.stub() - }; - // this MUST use sinon, not sandbox, see sinonjs/sinon#781 - knexStub = sinon.stub(db, 'knex', { - get: function () { - return knexMock; - } - }); - - dropColumnStub = sandbox.stub(schema.commands, 'dropColumn'); - addColumnStub = sandbox.stub(schema.commands, 'addColumn'); - createTableStub = sandbox.stub(schema.commands, 'createTable'); - }); - - afterEach(function () { - knexStub.restore(); - }); - - it('should have tasks for 008', function () { - should.exist(updates008); - updates008.should.be.an.Array().with.lengthOf(1); - }); - - describe('01-add-amp-column-to-posts', function () { - var addAmpColumn = updates008[0]; - - 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 - addAmpColumn({transacting: knexMock}, loggerStub) - .then(function () { - done(new Error('expected table not found error')); - }) - .catch(function (err) { - should.exist(err); - err.message.should.eql('Table does not exist!'); - knexMock.schema.hasTable.calledOnce.should.be.true(); - knexMock.schema.hasTable.firstCall.calledWith('posts').should.be.true(); - - knexMock.schema.hasColumn.called.should.be.false(); - - addColumnStub.called.should.be.false(); - - loggerStub.info.called.should.be.false(); - loggerStub.warn.calledOnce.should.be.false(); - done(); - }); - }); - - it('does not try to add a new column if the column already exists', function (done) { - // Setup - knexMock.schema.hasTable.withArgs('posts').returns(new Promise.resolve(true)); - knexMock.schema.hasColumn.withArgs('posts', 'amp').returns(Promise.resolve(true)); - - // Execute - addAmpColumn({transacting: knexMock}, loggerStub).then(function () { - knexMock.schema.hasTable.calledOnce.should.be.true(); - knexMock.schema.hasTable.calledWith('posts').should.be.true(); - - knexMock.schema.hasColumn.calledOnce.should.be.true(); - knexMock.schema.hasColumn.calledWith('posts', 'amp').should.be.true(); - - addColumnStub.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 - knexMock.schema.hasTable.withArgs('posts').returns(Promise.resolve(true)); - knexMock.schema.hasColumn.withArgs('posts', 'amp').returns(Promise.resolve(false)); - - // Execute - addAmpColumn({transacting: knexMock}, loggerStub).then(function () { - knexMock.schema.hasTable.calledOnce.should.be.true(); - knexMock.schema.hasTable.calledWith('posts').should.be.true(); - - knexMock.schema.hasColumn.calledOnce.should.be.true(); - knexMock.schema.hasColumn.calledWith('posts', 'amp').should.be.true(); - - addColumnStub.calledOnce.should.be.true(); - addColumnStub.calledWith('posts', 'amp').should.be.true(); - - loggerStub.info.calledOnce.should.be.true(); - loggerStub.warn.called.should.be.false(); - - done(); - }).catch(done); - }); - }); - }); - }); - }); - - describe('Update Database Schema', function () { - var updateDatabaseSchema = update.__get__('updateDatabaseSchema'); - - it('should not do anything if there are no tasks', function (done) { - updateDatabaseSchema([], {}, loggerStub).then(function () { - loggerStub.info.called.should.be.false(); - loggerStub.warn.called.should.be.false(); - done(); - }).catch(done); - }); - - it('should call the tasks if they are provided', function (done) { - var task1Stub = sandbox.stub().returns(new Promise.resolve()), - task2Stub = sandbox.stub().returns(new Promise.resolve()); - - updateDatabaseSchema([task1Stub, task2Stub], loggerStub).then(function () { - task1Stub.calledOnce.should.be.true(); - task2Stub.calledOnce.should.be.true(); - sinon.assert.callOrder(task1Stub, task2Stub); - - done(); - }).catch(done); - }); - }); - }); }); diff --git a/core/test/unit/versioning_spec.js b/core/test/unit/versioning_spec.js index ef3993128b..f5eeaff26b 100644 --- a/core/test/unit/versioning_spec.js +++ b/core/test/unit/versioning_spec.js @@ -186,35 +186,4 @@ describe('Versioning', function () { }).catch(done); }); }); - - describe('getUpdateTasks', function () { - var logStub; - - beforeEach(function () { - logStub = { - info: sandbox.stub(), - warn: sandbox.stub() - }; - }); - - it('`getUpdateFixturesTasks` returns empty array if no tasks are found', function () { - versioning.getUpdateFixturesTasks('999', logStub).should.eql([]); - logStub.info.calledOnce.should.be.true(); - }); - - it('`getUpdateFixturesTasks` returns 8 items for 004', function () { - versioning.getUpdateFixturesTasks('004', logStub).should.be.an.Array().with.lengthOf(8); - logStub.info.calledOnce.should.be.false(); - }); - - it('`getUpdateDatabaseTasks` returns empty array if no tasks are found', function () { - versioning.getUpdateDatabaseTasks('999', logStub).should.eql([]); - logStub.info.calledOnce.should.be.true(); - }); - - it('`getUpdateDatabaseTasks` returns 5 items for 004', function () { - versioning.getUpdateDatabaseTasks('004', logStub).should.be.an.Array().with.lengthOf(5); - logStub.info.calledOnce.should.be.false(); - }); - }); });