mirror of
https://github.com/TryGhost/Ghost.git
synced 2025-03-11 02:12:21 -05:00
😱 🚀 🎨 tests: use truncate instead of database deletion (#8119)
* 😱 🚀 🎨 tests: use truncate instead of delete the database refs #7718, refs #7470 - should bring massive speed improvement - could also fix random test failures (e.g. sqlite database is busy) * gruntfile: add knex-migrator command in test-setup
This commit is contained in:
parent
feaa25dad2
commit
f8c51ac7e5
4 changed files with 205 additions and 95 deletions
15
Gruntfile.js
15
Gruntfile.js
|
@ -8,9 +8,15 @@
|
||||||
|
|
||||||
// jshint unused: false
|
// jshint unused: false
|
||||||
var overrides = require('./core/server/overrides'),
|
var overrides = require('./core/server/overrides'),
|
||||||
|
config = require('./core/server/config'),
|
||||||
_ = require('lodash'),
|
_ = require('lodash'),
|
||||||
chalk = require('chalk'),
|
chalk = require('chalk'),
|
||||||
fs = require('fs-extra'),
|
fs = require('fs-extra'),
|
||||||
|
KnexMigrator = require('knex-migrator'),
|
||||||
|
knexMigrator = new KnexMigrator({
|
||||||
|
knexMigratorFilePath: config.get('paths:appRoot')
|
||||||
|
}),
|
||||||
|
|
||||||
path = require('path'),
|
path = require('path'),
|
||||||
|
|
||||||
escapeChar = process.platform.match(/^win/) ? '^' : '\\',
|
escapeChar = process.platform.match(/^win/) ? '^' : '\\',
|
||||||
|
@ -446,6 +452,13 @@ var overrides = require('./core/server/overrides'),
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ensures the target database get's automatically created.
|
||||||
|
*/
|
||||||
|
grunt.registerTask('knex-migrator', function () {
|
||||||
|
return knexMigrator.init({noScripts: true});
|
||||||
|
});
|
||||||
|
|
||||||
// ### Validate
|
// ### Validate
|
||||||
// **Main testing task**
|
// **Main testing task**
|
||||||
//
|
//
|
||||||
|
@ -499,7 +512,7 @@ var overrides = require('./core/server/overrides'),
|
||||||
// ### test-setup *(utility)(
|
// ### test-setup *(utility)(
|
||||||
// `grunt test-setup` will run all the setup tasks required for running tests
|
// `grunt test-setup` will run all the setup tasks required for running tests
|
||||||
grunt.registerTask('test-setup', 'Setup ready to run tests',
|
grunt.registerTask('test-setup', 'Setup ready to run tests',
|
||||||
['clean:test', 'setTestEnv']
|
['knex-migrator', 'clean:test', 'setTestEnv']
|
||||||
);
|
);
|
||||||
|
|
||||||
// ### Unit Tests *(sub task)*
|
// ### Unit Tests *(sub task)*
|
||||||
|
|
|
@ -35,7 +35,9 @@ describe('Frontend Routing', function () {
|
||||||
}
|
}
|
||||||
|
|
||||||
function addPosts(done) {
|
function addPosts(done) {
|
||||||
testUtils.initData().then(function () {
|
testUtils.clearData().then(function () {
|
||||||
|
return testUtils.initData();
|
||||||
|
}).then(function () {
|
||||||
return testUtils.fixtures.insertPostsAndTags();
|
return testUtils.fixtures.insertPostsAndTags();
|
||||||
}).then(function () {
|
}).then(function () {
|
||||||
done();
|
done();
|
||||||
|
@ -493,10 +495,10 @@ describe('Frontend Routing', function () {
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('Site Map', function () {
|
describe('Site Map', function () {
|
||||||
before(testUtils.teardown);
|
|
||||||
|
|
||||||
before(function (done) {
|
before(function (done) {
|
||||||
testUtils.initData().then(function () {
|
testUtils.clearData().then(function () {
|
||||||
|
return testUtils.initData();
|
||||||
|
}).then(function () {
|
||||||
return testUtils.fixtures.insertPostsAndTags();
|
return testUtils.fixtures.insertPostsAndTags();
|
||||||
}).then(function () {
|
}).then(function () {
|
||||||
done();
|
done();
|
||||||
|
|
|
@ -49,6 +49,9 @@ function forkGhost(newConfig) {
|
||||||
.then(function (_port) {
|
.then(function (_port) {
|
||||||
port = _port;
|
port = _port;
|
||||||
|
|
||||||
|
return knexMigrator.reset();
|
||||||
|
})
|
||||||
|
.then(function () {
|
||||||
return knexMigrator.init();
|
return knexMigrator.init();
|
||||||
})
|
})
|
||||||
.then(function () {
|
.then(function () {
|
||||||
|
|
|
@ -1,28 +1,31 @@
|
||||||
var Promise = require('bluebird'),
|
/*jshint expr:true*/
|
||||||
_ = require('lodash'),
|
var Promise = require('bluebird'),
|
||||||
fs = require('fs-extra'),
|
_ = require('lodash'),
|
||||||
path = require('path'),
|
fs = require('fs-extra'),
|
||||||
Module = require('module'),
|
path = require('path'),
|
||||||
debug = require('debug')('ghost:test'),
|
Module = require('module'),
|
||||||
ObjectId = require('bson-objectid'),
|
debug = require('debug')('ghost:test'),
|
||||||
uuid = require('uuid'),
|
ObjectId = require('bson-objectid'),
|
||||||
KnexMigrator = require('knex-migrator'),
|
uuid = require('uuid'),
|
||||||
ghost = require('../../server'),
|
KnexMigrator = require('knex-migrator'),
|
||||||
errors = require('../../server/errors'),
|
ghost = require('../../server'),
|
||||||
db = require('../../server/data/db'),
|
errors = require('../../server/errors'),
|
||||||
fixtureUtils = require('../../server/data/schema/fixtures/utils'),
|
db = require('../../server/data/db'),
|
||||||
models = require('../../server/models'),
|
fixtureUtils = require('../../server/data/schema/fixtures/utils'),
|
||||||
SettingsLib = require('../../server/settings'),
|
schema = require('../../server/data/schema').tables,
|
||||||
permissions = require('../../server/permissions'),
|
schemaTables = Object.keys(schema),
|
||||||
sequence = require('../../server/utils/sequence'),
|
models = require('../../server/models'),
|
||||||
themes = require('../../server/themes'),
|
SettingsLib = require('../../server/settings'),
|
||||||
|
permissions = require('../../server/permissions'),
|
||||||
|
sequence = require('../../server/utils/sequence'),
|
||||||
|
themes = require('../../server/themes'),
|
||||||
DataGenerator = require('./fixtures/data-generator'),
|
DataGenerator = require('./fixtures/data-generator'),
|
||||||
filterData = require('./fixtures/filter-param'),
|
filterData = require('./fixtures/filter-param'),
|
||||||
API = require('./api'),
|
API = require('./api'),
|
||||||
fork = require('./fork'),
|
fork = require('./fork'),
|
||||||
mocks = require('./mocks'),
|
mocks = require('./mocks'),
|
||||||
config = require('../../server/config'),
|
config = require('../../server/config'),
|
||||||
knexMigrator = new KnexMigrator(),
|
knexMigrator = new KnexMigrator(),
|
||||||
fixtures,
|
fixtures,
|
||||||
getFixtureOps,
|
getFixtureOps,
|
||||||
toDoList,
|
toDoList,
|
||||||
|
@ -293,7 +296,7 @@ fixtures = {
|
||||||
|
|
||||||
insertOne: function insertOne(obj, fn, index) {
|
insertOne: function insertOne(obj, fn, index) {
|
||||||
return db.knex(obj)
|
return db.knex(obj)
|
||||||
.insert(DataGenerator.forKnex[fn](DataGenerator.Content[obj][index || 0]));
|
.insert(DataGenerator.forKnex[fn](DataGenerator.Content[obj][index || 0]));
|
||||||
},
|
},
|
||||||
|
|
||||||
insertApps: function insertApps() {
|
insertApps: function insertApps() {
|
||||||
|
@ -423,7 +426,9 @@ clearData = function clearData() {
|
||||||
};
|
};
|
||||||
|
|
||||||
toDoList = {
|
toDoList = {
|
||||||
app: function insertApp() { return fixtures.insertOne('apps', 'createApp'); },
|
app: function insertApp() {
|
||||||
|
return fixtures.insertOne('apps', 'createApp');
|
||||||
|
},
|
||||||
app_field: function insertAppField() {
|
app_field: function insertAppField() {
|
||||||
// TODO: use the actual app ID to create the field
|
// TODO: use the actual app ID to create the field
|
||||||
return fixtures.insertOne('apps', 'createApp').then(function () {
|
return fixtures.insertOne('apps', 'createApp').then(function () {
|
||||||
|
@ -436,32 +441,80 @@ toDoList = {
|
||||||
return fixtures.insertOne('app_settings', 'createAppSetting');
|
return fixtures.insertOne('app_settings', 'createAppSetting');
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
permission: function insertPermission() { return fixtures.insertOne('permissions', 'createPermission'); },
|
permission: function insertPermission() {
|
||||||
role: function insertRole() { return fixtures.insertOne('roles', 'createRole'); },
|
return fixtures.insertOne('permissions', 'createPermission');
|
||||||
roles: function insertRoles() { return fixtures.insertRoles(); },
|
|
||||||
tag: function insertTag() { return fixtures.insertOne('tags', 'createTag'); },
|
|
||||||
subscriber: function insertSubscriber() { return fixtures.insertOne('subscribers', 'createSubscriber'); },
|
|
||||||
posts: function insertPostsAndTags() { return fixtures.insertPostsAndTags(); },
|
|
||||||
'posts:mu': function insertMultiAuthorPosts() { return fixtures.insertMultiAuthorPosts(); },
|
|
||||||
tags: function insertMoreTags() { return fixtures.insertMoreTags(); },
|
|
||||||
apps: function insertApps() { return fixtures.insertApps(); },
|
|
||||||
settings: function populateSettings() { return SettingsLib.init(); },
|
|
||||||
'users:roles': function createUsersWithRoles() { return fixtures.createUsersWithRoles(); },
|
|
||||||
'users:no-owner': function createUsersWithoutOwner() { return fixtures.createUsersWithoutOwner(); },
|
|
||||||
users: function createExtraUsers() { return fixtures.createExtraUsers(); },
|
|
||||||
'user:token': function createTokensForUser() { return fixtures.createTokensForUser(); },
|
|
||||||
owner: function insertOwnerUser() { return fixtures.insertOwnerUser(); },
|
|
||||||
'owner:pre': function initOwnerUser() { return fixtures.initOwnerUser(); },
|
|
||||||
'owner:post': function overrideOwnerUser() { return fixtures.overrideOwnerUser(); },
|
|
||||||
'perms:init': function initPermissions() { return permissions.init(); },
|
|
||||||
perms: function permissionsFor(obj) {
|
|
||||||
return function permissionsForObj() { return fixtures.permissionsFor(obj); };
|
|
||||||
},
|
},
|
||||||
clients: function insertClients() { return fixtures.insertClients(); },
|
role: function insertRole() {
|
||||||
'client:trusted-domain': function insertClients() { return fixtures.insertClientWithTrustedDomain(); },
|
return fixtures.insertOne('roles', 'createRole');
|
||||||
filter: function createFilterParamFixtures() { return filterData(DataGenerator); },
|
},
|
||||||
invites: function insertInvites() { return fixtures.insertInvites(); },
|
roles: function insertRoles() {
|
||||||
themes: function loadThemes() { return themes.loadAll(); }
|
return fixtures.insertRoles();
|
||||||
|
},
|
||||||
|
tag: function insertTag() {
|
||||||
|
return fixtures.insertOne('tags', 'createTag');
|
||||||
|
},
|
||||||
|
subscriber: function insertSubscriber() {
|
||||||
|
return fixtures.insertOne('subscribers', 'createSubscriber');
|
||||||
|
},
|
||||||
|
posts: function insertPostsAndTags() {
|
||||||
|
return fixtures.insertPostsAndTags();
|
||||||
|
},
|
||||||
|
'posts:mu': function insertMultiAuthorPosts() {
|
||||||
|
return fixtures.insertMultiAuthorPosts();
|
||||||
|
},
|
||||||
|
tags: function insertMoreTags() {
|
||||||
|
return fixtures.insertMoreTags();
|
||||||
|
},
|
||||||
|
apps: function insertApps() {
|
||||||
|
return fixtures.insertApps();
|
||||||
|
},
|
||||||
|
settings: function populateSettings() {
|
||||||
|
return SettingsLib.init();
|
||||||
|
},
|
||||||
|
'users:roles': function createUsersWithRoles() {
|
||||||
|
return fixtures.createUsersWithRoles();
|
||||||
|
},
|
||||||
|
'users:no-owner': function createUsersWithoutOwner() {
|
||||||
|
return fixtures.createUsersWithoutOwner();
|
||||||
|
},
|
||||||
|
users: function createExtraUsers() {
|
||||||
|
return fixtures.createExtraUsers();
|
||||||
|
},
|
||||||
|
'user:token': function createTokensForUser() {
|
||||||
|
return fixtures.createTokensForUser();
|
||||||
|
},
|
||||||
|
owner: function insertOwnerUser() {
|
||||||
|
return fixtures.insertOwnerUser();
|
||||||
|
},
|
||||||
|
'owner:pre': function initOwnerUser() {
|
||||||
|
return fixtures.initOwnerUser();
|
||||||
|
},
|
||||||
|
'owner:post': function overrideOwnerUser() {
|
||||||
|
return fixtures.overrideOwnerUser();
|
||||||
|
},
|
||||||
|
'perms:init': function initPermissions() {
|
||||||
|
return permissions.init();
|
||||||
|
},
|
||||||
|
perms: function permissionsFor(obj) {
|
||||||
|
return function permissionsForObj() {
|
||||||
|
return fixtures.permissionsFor(obj);
|
||||||
|
};
|
||||||
|
},
|
||||||
|
clients: function insertClients() {
|
||||||
|
return fixtures.insertClients();
|
||||||
|
},
|
||||||
|
'client:trusted-domain': function insertClients() {
|
||||||
|
return fixtures.insertClientWithTrustedDomain();
|
||||||
|
},
|
||||||
|
filter: function createFilterParamFixtures() {
|
||||||
|
return filterData(DataGenerator);
|
||||||
|
},
|
||||||
|
invites: function insertInvites() {
|
||||||
|
return fixtures.insertInvites();
|
||||||
|
},
|
||||||
|
themes: function loadThemes() {
|
||||||
|
return themes.loadAll();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -470,10 +523,10 @@ toDoList = {
|
||||||
* Takes the arguments from a setup function and turns them into an array of promises to fullfil
|
* Takes the arguments from a setup function and turns them into an array of promises to fullfil
|
||||||
*
|
*
|
||||||
* This is effectively a list of instructions with regard to which fixtures should be setup for this test.
|
* This is effectively a list of instructions with regard to which fixtures should be setup for this test.
|
||||||
* * `default` - a special option which will cause the full suite of normal fixtures to be initialised
|
* * `default` - a special option which will cause the full suite of normal fixtures to be initialised
|
||||||
* * `perms:init` - initialise the permissions object after having added permissions
|
* * `perms:init` - initialise the permissions object after having added permissions
|
||||||
* * `perms:obj` - initialise permissions for a particular object type
|
* * `perms:obj` - initialise permissions for a particular object type
|
||||||
* * `users:roles` - create a full suite of users, one per role
|
* * `users:roles` - create a full suite of users, one per role
|
||||||
* @param {Object} toDos
|
* @param {Object} toDos
|
||||||
*/
|
*/
|
||||||
getFixtureOps = function getFixtureOps(toDos) {
|
getFixtureOps = function getFixtureOps(toDos) {
|
||||||
|
@ -614,14 +667,14 @@ login = function login(request) {
|
||||||
client_id: 'ghost-admin',
|
client_id: 'ghost-admin',
|
||||||
client_secret: 'not_available'
|
client_secret: 'not_available'
|
||||||
}).then(function then(res) {
|
}).then(function then(res) {
|
||||||
if (res.statusCode !== 200) {
|
if (res.statusCode !== 200) {
|
||||||
return reject(new errors.GhostError({
|
return reject(new errors.GhostError({
|
||||||
message: res.body.errors[0].message
|
message: res.body.errors[0].message
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
resolve(res.body.access_token);
|
resolve(res.body.access_token);
|
||||||
}, reject);
|
}, reject);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -632,18 +685,20 @@ togglePermalinks = function togglePermalinks(request, toggle) {
|
||||||
doAuth(request).then(function (token) {
|
doAuth(request).then(function (token) {
|
||||||
request.put('/ghost/api/v0.1/settings/')
|
request.put('/ghost/api/v0.1/settings/')
|
||||||
.set('Authorization', 'Bearer ' + token)
|
.set('Authorization', 'Bearer ' + token)
|
||||||
.send({settings: [
|
.send({
|
||||||
{
|
settings: [
|
||||||
uuid: '75e994ae-490e-45e6-9207-0eab409c1c04',
|
{
|
||||||
key: 'permalinks',
|
uuid: '75e994ae-490e-45e6-9207-0eab409c1c04',
|
||||||
value: permalinkString,
|
key: 'permalinks',
|
||||||
type: 'blog',
|
value: permalinkString,
|
||||||
created_at: '2014-10-16T17:39:16.005Z',
|
type: 'blog',
|
||||||
created_by: 1,
|
created_at: '2014-10-16T17:39:16.005Z',
|
||||||
updated_at: '2014-10-20T19:44:18.077Z',
|
created_by: 1,
|
||||||
updated_by: 1
|
updated_at: '2014-10-20T19:44:18.077Z',
|
||||||
}
|
updated_by: 1
|
||||||
]})
|
}
|
||||||
|
]
|
||||||
|
})
|
||||||
.end(function (err, res) {
|
.end(function (err, res) {
|
||||||
if (err) {
|
if (err) {
|
||||||
return reject(err);
|
return reject(err);
|
||||||
|
@ -659,18 +714,55 @@ togglePermalinks = function togglePermalinks(request, toggle) {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Has to run in a transaction for MySQL, otherwise the foreign key check does not work.
|
||||||
|
* Sqlite3 has no truncate command.
|
||||||
|
*/
|
||||||
teardown = function teardown(done) {
|
teardown = function teardown(done) {
|
||||||
debug('Database reset');
|
debug('Database teardown');
|
||||||
|
var tables = schemaTables.concat(['migrations']);
|
||||||
|
|
||||||
if (done) {
|
if (config.get('database:client') === 'sqlite3') {
|
||||||
knexMigrator.reset()
|
return Promise
|
||||||
.then(function () {
|
.mapSeries(tables, function createTable(table) {
|
||||||
done();
|
return db.knex.raw('DELETE FROM ' + table + ';');
|
||||||
})
|
})
|
||||||
.catch(done);
|
.then(function () {
|
||||||
} else {
|
done && done();
|
||||||
return knexMigrator.reset();
|
})
|
||||||
|
.catch(function (err) {
|
||||||
|
// CASE: table does not exist
|
||||||
|
if (err.errno === 1) {
|
||||||
|
return done && done();
|
||||||
|
}
|
||||||
|
|
||||||
|
done && done(err);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return db.knex.transaction(function (trx) {
|
||||||
|
return db.knex.raw('SET FOREIGN_KEY_CHECKS=0;').transacting(trx)
|
||||||
|
.then(function () {
|
||||||
|
return Promise
|
||||||
|
.each(tables, function createTable(table) {
|
||||||
|
return db.knex.raw('TRUNCATE ' + table + ';').transacting(trx);
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.then(function () {
|
||||||
|
return db.knex.raw('SET FOREIGN_KEY_CHECKS=1;').transacting(trx);
|
||||||
|
})
|
||||||
|
.then(function () {
|
||||||
|
done && done();
|
||||||
|
})
|
||||||
|
.catch(function (err) {
|
||||||
|
// CASE: table does not exist
|
||||||
|
if (err.errno === 1146) {
|
||||||
|
return done && done();
|
||||||
|
}
|
||||||
|
|
||||||
|
return done ? done(err) : Promise.reject(err);
|
||||||
|
});
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -735,12 +827,12 @@ module.exports = {
|
||||||
|
|
||||||
// Helpers to make it easier to write tests which are easy to read
|
// Helpers to make it easier to write tests which are easy to read
|
||||||
context: {
|
context: {
|
||||||
internal: {context: {internal: true}},
|
internal: {context: {internal: true}},
|
||||||
external: {context: {external: true}},
|
external: {context: {external: true}},
|
||||||
owner: {context: {user: DataGenerator.Content.users[0].id}},
|
owner: {context: {user: DataGenerator.Content.users[0].id}},
|
||||||
admin: {context: {user: DataGenerator.Content.users[1].id}},
|
admin: {context: {user: DataGenerator.Content.users[1].id}},
|
||||||
editor: {context: {user: DataGenerator.Content.users[2].id}},
|
editor: {context: {user: DataGenerator.Content.users[2].id}},
|
||||||
author: {context: {user: DataGenerator.Content.users[3].id}}
|
author: {context: {user: DataGenerator.Content.users[3].id}}
|
||||||
},
|
},
|
||||||
users: {
|
users: {
|
||||||
ids: {
|
ids: {
|
||||||
|
@ -761,9 +853,9 @@ module.exports = {
|
||||||
|
|
||||||
cacheRules: {
|
cacheRules: {
|
||||||
public: 'public, max-age=0',
|
public: 'public, max-age=0',
|
||||||
hour: 'public, max-age=' + 3600,
|
hour: 'public, max-age=' + 3600,
|
||||||
day: 'public, max-age=' + 86400,
|
day: 'public, max-age=' + 86400,
|
||||||
year: 'public, max-age=' + 31536000,
|
year: 'public, max-age=' + 31536000,
|
||||||
private: 'no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0'
|
private: 'no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0'
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
Loading…
Add table
Reference in a new issue