mirror of
https://github.com/TryGhost/Ghost.git
synced 2025-02-10 23:36:14 -05:00
Moved acceptance test utils into own file
- starting and stopping Ghost is part of our rather unloved acceptance test framework - moving them into their own file to make the different pieces clearer and also to start to make improvements - first improvement had to happen as an aside - exposing the existingData property via a function and making the API clearer - this was a weird thing set on module.exports, very hidden and hard to follow - Note: stopGhost is only used once in the regression/modles/model_posts_spec.js file to make the test run fast enough... - These tests are effectively "DB integration" tests e.g. non-unit tests because they do use the DB, they need their own framework
This commit is contained in:
parent
52a97957e1
commit
0f42bbeac3
14 changed files with 297 additions and 274 deletions
|
@ -73,7 +73,7 @@ describe('Invites API', function () {
|
|||
.post(localUtils.API.getApiQuery('invites/'))
|
||||
.set('Origin', config.get('url'))
|
||||
.send({
|
||||
invites: [{email: 'test@example.com', role_id: testUtils.existingData.roles[1].id}]
|
||||
invites: [{email: 'test@example.com', role_id: testUtils.getExistingData().roles[1].id}]
|
||||
})
|
||||
.expect('Content-Type', /json/)
|
||||
.expect('Cache-Control', testUtils.cacheRules.private)
|
||||
|
@ -86,7 +86,7 @@ describe('Invites API', function () {
|
|||
jsonResponse.invites.should.have.length(1);
|
||||
|
||||
localUtils.API.checkResponse(jsonResponse.invites[0], 'invite');
|
||||
jsonResponse.invites[0].role_id.should.eql(testUtils.existingData.roles[1].id);
|
||||
jsonResponse.invites[0].role_id.should.eql(testUtils.getExistingData().roles[1].id);
|
||||
|
||||
mailService.GhostMailer.prototype.send.called.should.be.true();
|
||||
|
||||
|
|
|
@ -59,7 +59,7 @@ describe('Tag API', function () {
|
|||
|
||||
it('Can read a tag', async function () {
|
||||
const res = await request
|
||||
.get(localUtils.API.getApiQuery(`tags/${testUtils.existingData.tags[0].id}/?include=count.posts`))
|
||||
.get(localUtils.API.getApiQuery(`tags/${testUtils.getExistingData().tags[0].id}/?include=count.posts`))
|
||||
.set('Origin', config.get('url'))
|
||||
.expect('Content-Type', /json/)
|
||||
.expect('Cache-Control', testUtils.cacheRules.private)
|
||||
|
@ -132,10 +132,10 @@ describe('Tag API', function () {
|
|||
|
||||
it('Can edit a tag', async function () {
|
||||
const res = await request
|
||||
.put(localUtils.API.getApiQuery(`tags/${testUtils.existingData.tags[0].id}`))
|
||||
.put(localUtils.API.getApiQuery(`tags/${testUtils.getExistingData().tags[0].id}`))
|
||||
.set('Origin', config.get('url'))
|
||||
.send({
|
||||
tags: [Object.assign({}, testUtils.existingData.tags[0], {description: 'hey ho ab ins klo'})]
|
||||
tags: [Object.assign({}, testUtils.getExistingData().tags[0], {description: 'hey ho ab ins klo'})]
|
||||
})
|
||||
.expect('Content-Type', /json/)
|
||||
.expect('Cache-Control', testUtils.cacheRules.private)
|
||||
|
@ -152,7 +152,7 @@ describe('Tag API', function () {
|
|||
|
||||
it('Can destroy a tag', async function () {
|
||||
const res = await request
|
||||
.del(localUtils.API.getApiQuery(`tags/${testUtils.existingData.tags[0].id}`))
|
||||
.del(localUtils.API.getApiQuery(`tags/${testUtils.getExistingData().tags[0].id}`))
|
||||
.set('Origin', config.get('url'))
|
||||
.expect('Cache-Control', testUtils.cacheRules.private)
|
||||
.expect(204);
|
||||
|
|
|
@ -100,7 +100,7 @@ describe('User API', function () {
|
|||
});
|
||||
|
||||
it('Can retrieve a user by id', async function () {
|
||||
const res = await request.get(localUtils.API.getApiQuery('users/' + testUtils.existingData.users[0].id + '/?include=roles,roles.permissions,count.posts'))
|
||||
const res = await request.get(localUtils.API.getApiQuery('users/' + testUtils.getExistingData().users[0].id + '/?include=roles,roles.permissions,count.posts'))
|
||||
.set('Origin', config.get('url'))
|
||||
.expect('Content-Type', /json/)
|
||||
.expect('Cache-Control', testUtils.cacheRules.private)
|
||||
|
@ -186,7 +186,7 @@ describe('User API', function () {
|
|||
});
|
||||
|
||||
it('Can destroy an active user', async function () {
|
||||
const userId = testUtils.existingData.users[1].id;
|
||||
const userId = testUtils.getExistingData().users[1].id;
|
||||
|
||||
const res = await request
|
||||
.get(localUtils.API.getApiQuery(`posts/?filter=author_id:${userId}`))
|
||||
|
@ -257,7 +257,7 @@ describe('User API', function () {
|
|||
newPassword: '1234abcde!!',
|
||||
ne2Password: '1234abcde!!',
|
||||
oldPassword: 'Sl1m3rson99',
|
||||
user_id: testUtils.existingData.users[0].id
|
||||
user_id: testUtils.getExistingData().users[0].id
|
||||
}]
|
||||
})
|
||||
.expect('Content-Type', /json/)
|
||||
|
@ -287,7 +287,7 @@ describe('User API', function () {
|
|||
});
|
||||
|
||||
it('Can\'t read another user\'s Personal Token', async function () {
|
||||
const userNotAdmin = testUtils.existingData.users.find(user => user.email === 'ghost-author@example.com');
|
||||
const userNotAdmin = testUtils.getExistingData().users.find(user => user.email === 'ghost-author@example.com');
|
||||
const res = await request
|
||||
.get(localUtils.API.getApiQuery('users/' + userNotAdmin.id + '/token/'))
|
||||
.set('Origin', config.get('url'))
|
||||
|
|
|
@ -28,8 +28,8 @@ describe('DB API', function () {
|
|||
return localUtils.doAuth(request);
|
||||
})
|
||||
.then(() => {
|
||||
backupKey = _.find(testUtils.existingData.apiKeys, {integration: {slug: 'ghost-backup'}});
|
||||
schedulerKey = _.find(testUtils.existingData.apiKeys, {integration: {slug: 'ghost-scheduler'}});
|
||||
backupKey = _.find(testUtils.getExistingData().apiKeys, {integration: {slug: 'ghost-backup'}});
|
||||
schedulerKey = _.find(testUtils.getExistingData().apiKeys, {integration: {slug: 'ghost-scheduler'}});
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
@ -33,45 +33,45 @@ describe('Canary Schedules API', function () {
|
|||
request = supertest.agent(config.get('url'));
|
||||
|
||||
resources.push(testUtils.DataGenerator.forKnex.createPost({
|
||||
created_by: testUtils.existingData.users[0].id,
|
||||
author_id: testUtils.existingData.users[0].id,
|
||||
published_by: testUtils.existingData.users[0].id,
|
||||
created_by: testUtils.getExistingData().users[0].id,
|
||||
author_id: testUtils.getExistingData().users[0].id,
|
||||
published_by: testUtils.getExistingData().users[0].id,
|
||||
published_at: moment().add(30, 'seconds').toDate(),
|
||||
status: 'scheduled',
|
||||
slug: 'first'
|
||||
}));
|
||||
|
||||
resources.push(testUtils.DataGenerator.forKnex.createPost({
|
||||
created_by: testUtils.existingData.users[0].id,
|
||||
author_id: testUtils.existingData.users[0].id,
|
||||
published_by: testUtils.existingData.users[0].id,
|
||||
created_by: testUtils.getExistingData().users[0].id,
|
||||
author_id: testUtils.getExistingData().users[0].id,
|
||||
published_by: testUtils.getExistingData().users[0].id,
|
||||
published_at: moment().subtract(30, 'seconds').toDate(),
|
||||
status: 'scheduled',
|
||||
slug: 'second'
|
||||
}));
|
||||
|
||||
resources.push(testUtils.DataGenerator.forKnex.createPost({
|
||||
created_by: testUtils.existingData.users[0].id,
|
||||
author_id: testUtils.existingData.users[0].id,
|
||||
published_by: testUtils.existingData.users[0].id,
|
||||
created_by: testUtils.getExistingData().users[0].id,
|
||||
author_id: testUtils.getExistingData().users[0].id,
|
||||
published_by: testUtils.getExistingData().users[0].id,
|
||||
published_at: moment().add(10, 'minute').toDate(),
|
||||
status: 'scheduled',
|
||||
slug: 'third'
|
||||
}));
|
||||
|
||||
resources.push(testUtils.DataGenerator.forKnex.createPost({
|
||||
created_by: testUtils.existingData.users[0].id,
|
||||
author_id: testUtils.existingData.users[0].id,
|
||||
published_by: testUtils.existingData.users[0].id,
|
||||
created_by: testUtils.getExistingData().users[0].id,
|
||||
author_id: testUtils.getExistingData().users[0].id,
|
||||
published_by: testUtils.getExistingData().users[0].id,
|
||||
published_at: moment().subtract(10, 'minute').toDate(),
|
||||
status: 'scheduled',
|
||||
slug: 'fourth'
|
||||
}));
|
||||
|
||||
resources.push(testUtils.DataGenerator.forKnex.createPost({
|
||||
created_by: testUtils.existingData.users[0].id,
|
||||
author_id: testUtils.existingData.users[0].id,
|
||||
published_by: testUtils.existingData.users[0].id,
|
||||
created_by: testUtils.getExistingData().users[0].id,
|
||||
author_id: testUtils.getExistingData().users[0].id,
|
||||
published_by: testUtils.getExistingData().users[0].id,
|
||||
published_at: moment().add(30, 'seconds').toDate(),
|
||||
status: 'scheduled',
|
||||
slug: 'fifth',
|
||||
|
@ -89,7 +89,7 @@ describe('Canary Schedules API', function () {
|
|||
let token;
|
||||
|
||||
before(function () {
|
||||
const schedulerKey = _.find(testUtils.existingData.apiKeys, {integration: {slug: 'ghost-scheduler'}});
|
||||
const schedulerKey = _.find(testUtils.getExistingData().apiKeys, {integration: {slug: 'ghost-scheduler'}});
|
||||
|
||||
token = localUtils.getValidAdminToken('/canary/admin/', schedulerKey);
|
||||
});
|
||||
|
@ -124,7 +124,7 @@ describe('Canary Schedules API', function () {
|
|||
});
|
||||
|
||||
it('no access', function () {
|
||||
const zapierKey = _.find(testUtils.existingData.apiKeys, {integration: {slug: 'ghost-backup'}});
|
||||
const zapierKey = _.find(testUtils.getExistingData().apiKeys, {integration: {slug: 'ghost-backup'}});
|
||||
const zapierToken = localUtils.getValidAdminToken('/canary/admin/', zapierKey);
|
||||
|
||||
return request
|
||||
|
|
|
@ -217,7 +217,7 @@ describe('User API', function () {
|
|||
.set('Origin', config.get('url'))
|
||||
.send({
|
||||
owner: [{
|
||||
id: testUtils.existingData.users[1].id
|
||||
id: testUtils.getExistingData().users[1].id
|
||||
}]
|
||||
})
|
||||
.expect('Content-Type', /json/)
|
||||
|
|
|
@ -28,8 +28,8 @@ describe('DB API', function () {
|
|||
return localUtils.doAuth(request);
|
||||
})
|
||||
.then(() => {
|
||||
backupKey = _.find(testUtils.existingData.apiKeys, {integration: {slug: 'ghost-backup'}});
|
||||
schedulerKey = _.find(testUtils.existingData.apiKeys, {integration: {slug: 'ghost-scheduler'}});
|
||||
backupKey = _.find(testUtils.getExistingData().apiKeys, {integration: {slug: 'ghost-backup'}});
|
||||
schedulerKey = _.find(testUtils.getExistingData().apiKeys, {integration: {slug: 'ghost-scheduler'}});
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
@ -33,45 +33,45 @@ describe('v2 Schedules API', function () {
|
|||
request = supertest.agent(config.get('url'));
|
||||
|
||||
resources.push(testUtils.DataGenerator.forKnex.createPost({
|
||||
created_by: testUtils.existingData.users[0].id,
|
||||
author_id: testUtils.existingData.users[0].id,
|
||||
published_by: testUtils.existingData.users[0].id,
|
||||
created_by: testUtils.getExistingData().users[0].id,
|
||||
author_id: testUtils.getExistingData().users[0].id,
|
||||
published_by: testUtils.getExistingData().users[0].id,
|
||||
published_at: moment().add(30, 'seconds').toDate(),
|
||||
status: 'scheduled',
|
||||
slug: 'first'
|
||||
}));
|
||||
|
||||
resources.push(testUtils.DataGenerator.forKnex.createPost({
|
||||
created_by: testUtils.existingData.users[0].id,
|
||||
author_id: testUtils.existingData.users[0].id,
|
||||
published_by: testUtils.existingData.users[0].id,
|
||||
created_by: testUtils.getExistingData().users[0].id,
|
||||
author_id: testUtils.getExistingData().users[0].id,
|
||||
published_by: testUtils.getExistingData().users[0].id,
|
||||
published_at: moment().subtract(30, 'seconds').toDate(),
|
||||
status: 'scheduled',
|
||||
slug: 'second'
|
||||
}));
|
||||
|
||||
resources.push(testUtils.DataGenerator.forKnex.createPost({
|
||||
created_by: testUtils.existingData.users[0].id,
|
||||
author_id: testUtils.existingData.users[0].id,
|
||||
published_by: testUtils.existingData.users[0].id,
|
||||
created_by: testUtils.getExistingData().users[0].id,
|
||||
author_id: testUtils.getExistingData().users[0].id,
|
||||
published_by: testUtils.getExistingData().users[0].id,
|
||||
published_at: moment().add(10, 'minute').toDate(),
|
||||
status: 'scheduled',
|
||||
slug: 'third'
|
||||
}));
|
||||
|
||||
resources.push(testUtils.DataGenerator.forKnex.createPost({
|
||||
created_by: testUtils.existingData.users[0].id,
|
||||
author_id: testUtils.existingData.users[0].id,
|
||||
published_by: testUtils.existingData.users[0].id,
|
||||
created_by: testUtils.getExistingData().users[0].id,
|
||||
author_id: testUtils.getExistingData().users[0].id,
|
||||
published_by: testUtils.getExistingData().users[0].id,
|
||||
published_at: moment().subtract(10, 'minute').toDate(),
|
||||
status: 'scheduled',
|
||||
slug: 'fourth'
|
||||
}));
|
||||
|
||||
resources.push(testUtils.DataGenerator.forKnex.createPost({
|
||||
created_by: testUtils.existingData.users[0].id,
|
||||
author_id: testUtils.existingData.users[0].id,
|
||||
published_by: testUtils.existingData.users[0].id,
|
||||
created_by: testUtils.getExistingData().users[0].id,
|
||||
author_id: testUtils.getExistingData().users[0].id,
|
||||
published_by: testUtils.getExistingData().users[0].id,
|
||||
published_at: moment().add(30, 'seconds').toDate(),
|
||||
status: 'scheduled',
|
||||
slug: 'fifth',
|
||||
|
@ -89,7 +89,7 @@ describe('v2 Schedules API', function () {
|
|||
let token;
|
||||
|
||||
before(function () {
|
||||
const schedulerKey = _.find(testUtils.existingData.apiKeys, {integration: {slug: 'ghost-scheduler'}});
|
||||
const schedulerKey = _.find(testUtils.getExistingData().apiKeys, {integration: {slug: 'ghost-scheduler'}});
|
||||
|
||||
token = localUtils.getValidAdminToken('/v2/admin/', schedulerKey);
|
||||
});
|
||||
|
@ -124,7 +124,7 @@ describe('v2 Schedules API', function () {
|
|||
});
|
||||
|
||||
it('no access', function () {
|
||||
const zapierKey = _.find(testUtils.existingData.apiKeys, {integration: {slug: 'ghost-backup'}});
|
||||
const zapierKey = _.find(testUtils.getExistingData().apiKeys, {integration: {slug: 'ghost-backup'}});
|
||||
const zapierToken = localUtils.getValidAdminToken('/v2/admin/', zapierKey);
|
||||
|
||||
return request
|
||||
|
|
|
@ -217,7 +217,7 @@ describe('User API', function () {
|
|||
.set('Origin', config.get('url'))
|
||||
.send({
|
||||
owner: [{
|
||||
id: testUtils.existingData.users[1].id
|
||||
id: testUtils.getExistingData().users[1].id
|
||||
}]
|
||||
})
|
||||
.expect('Content-Type', /json/)
|
||||
|
|
|
@ -28,8 +28,8 @@ describe('DB API', function () {
|
|||
return localUtils.doAuth(request);
|
||||
})
|
||||
.then(() => {
|
||||
backupKey = _.find(testUtils.existingData.apiKeys, {integration: {slug: 'ghost-backup'}});
|
||||
schedulerKey = _.find(testUtils.existingData.apiKeys, {integration: {slug: 'ghost-scheduler'}});
|
||||
backupKey = _.find(testUtils.getExistingData().apiKeys, {integration: {slug: 'ghost-backup'}});
|
||||
schedulerKey = _.find(testUtils.getExistingData().apiKeys, {integration: {slug: 'ghost-scheduler'}});
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
@ -33,45 +33,45 @@ describe('v3 Schedules API', function () {
|
|||
request = supertest.agent(config.get('url'));
|
||||
|
||||
resources.push(testUtils.DataGenerator.forKnex.createPost({
|
||||
created_by: testUtils.existingData.users[0].id,
|
||||
author_id: testUtils.existingData.users[0].id,
|
||||
published_by: testUtils.existingData.users[0].id,
|
||||
created_by: testUtils.getExistingData().users[0].id,
|
||||
author_id: testUtils.getExistingData().users[0].id,
|
||||
published_by: testUtils.getExistingData().users[0].id,
|
||||
published_at: moment().add(30, 'seconds').toDate(),
|
||||
status: 'scheduled',
|
||||
slug: 'first'
|
||||
}));
|
||||
|
||||
resources.push(testUtils.DataGenerator.forKnex.createPost({
|
||||
created_by: testUtils.existingData.users[0].id,
|
||||
author_id: testUtils.existingData.users[0].id,
|
||||
published_by: testUtils.existingData.users[0].id,
|
||||
created_by: testUtils.getExistingData().users[0].id,
|
||||
author_id: testUtils.getExistingData().users[0].id,
|
||||
published_by: testUtils.getExistingData().users[0].id,
|
||||
published_at: moment().subtract(30, 'seconds').toDate(),
|
||||
status: 'scheduled',
|
||||
slug: 'second'
|
||||
}));
|
||||
|
||||
resources.push(testUtils.DataGenerator.forKnex.createPost({
|
||||
created_by: testUtils.existingData.users[0].id,
|
||||
author_id: testUtils.existingData.users[0].id,
|
||||
published_by: testUtils.existingData.users[0].id,
|
||||
created_by: testUtils.getExistingData().users[0].id,
|
||||
author_id: testUtils.getExistingData().users[0].id,
|
||||
published_by: testUtils.getExistingData().users[0].id,
|
||||
published_at: moment().add(10, 'minute').toDate(),
|
||||
status: 'scheduled',
|
||||
slug: 'third'
|
||||
}));
|
||||
|
||||
resources.push(testUtils.DataGenerator.forKnex.createPost({
|
||||
created_by: testUtils.existingData.users[0].id,
|
||||
author_id: testUtils.existingData.users[0].id,
|
||||
published_by: testUtils.existingData.users[0].id,
|
||||
created_by: testUtils.getExistingData().users[0].id,
|
||||
author_id: testUtils.getExistingData().users[0].id,
|
||||
published_by: testUtils.getExistingData().users[0].id,
|
||||
published_at: moment().subtract(10, 'minute').toDate(),
|
||||
status: 'scheduled',
|
||||
slug: 'fourth'
|
||||
}));
|
||||
|
||||
resources.push(testUtils.DataGenerator.forKnex.createPost({
|
||||
created_by: testUtils.existingData.users[0].id,
|
||||
author_id: testUtils.existingData.users[0].id,
|
||||
published_by: testUtils.existingData.users[0].id,
|
||||
created_by: testUtils.getExistingData().users[0].id,
|
||||
author_id: testUtils.getExistingData().users[0].id,
|
||||
published_by: testUtils.getExistingData().users[0].id,
|
||||
published_at: moment().add(30, 'seconds').toDate(),
|
||||
status: 'scheduled',
|
||||
slug: 'fifth',
|
||||
|
@ -89,7 +89,7 @@ describe('v3 Schedules API', function () {
|
|||
let token;
|
||||
|
||||
before(function () {
|
||||
const schedulerKey = _.find(testUtils.existingData.apiKeys, {integration: {slug: 'ghost-scheduler'}});
|
||||
const schedulerKey = _.find(testUtils.getExistingData().apiKeys, {integration: {slug: 'ghost-scheduler'}});
|
||||
|
||||
token = localUtils.getValidAdminToken('/v3/admin/', schedulerKey);
|
||||
});
|
||||
|
@ -124,7 +124,7 @@ describe('v3 Schedules API', function () {
|
|||
});
|
||||
|
||||
it('no access', function () {
|
||||
const zapierKey = _.find(testUtils.existingData.apiKeys, {integration: {slug: 'ghost-backup'}});
|
||||
const zapierKey = _.find(testUtils.getExistingData().apiKeys, {integration: {slug: 'ghost-backup'}});
|
||||
const zapierToken = localUtils.getValidAdminToken('/v3/admin/', zapierKey);
|
||||
|
||||
return request
|
||||
|
|
|
@ -217,7 +217,7 @@ describe('User API', function () {
|
|||
.set('Origin', config.get('url'))
|
||||
.send({
|
||||
owner: [{
|
||||
id: testUtils.existingData.users[1].id
|
||||
id: testUtils.getExistingData().users[1].id
|
||||
}]
|
||||
})
|
||||
.expect('Content-Type', /json/)
|
||||
|
|
223
test/utils/acceptance-utils.js
Normal file
223
test/utils/acceptance-utils.js
Normal file
|
@ -0,0 +1,223 @@
|
|||
require('../../core/server/overrides');
|
||||
|
||||
// Utility Packages
|
||||
const Promise = require('bluebird');
|
||||
const _ = require('lodash');
|
||||
const fs = require('fs-extra');
|
||||
const path = require('path');
|
||||
const os = require('os');
|
||||
const uuid = require('uuid');
|
||||
const KnexMigrator = require('knex-migrator');
|
||||
const knexMigrator = new KnexMigrator();
|
||||
|
||||
// Ghost Internals
|
||||
const config = require('../../core/shared/config');
|
||||
const boot = require('../../core/boot');
|
||||
const db = require('../../core/server/data/db');
|
||||
const models = require('../../core/server/models');
|
||||
const urlService = require('../../core/frontend/services/url');
|
||||
const settingsService = require('../../core/server/services/settings');
|
||||
const frontendSettingsService = require('../../core/frontend/services/settings');
|
||||
const settingsCache = require('../../core/server/services/settings/cache');
|
||||
const web = require('../../core/server/web');
|
||||
const themeService = require('../../core/server/services/themes');
|
||||
const limits = require('../../core/server/services/limits');
|
||||
|
||||
// Other Test Utilities
|
||||
const configUtils = require('./configUtils');
|
||||
const dbUtils = require('./db-utils');
|
||||
const urlServiceUtils = require('./url-service-utils');
|
||||
const redirects = require('./redirects');
|
||||
const context = require('./fixtures/context');
|
||||
|
||||
let ghostServer;
|
||||
let existingData = {};
|
||||
|
||||
/**
|
||||
* Because we use ObjectID we don't know the ID of fixtures ahead of time
|
||||
* This function fetches all of our fixtures and exposes them so that tests can use them
|
||||
* @TODO: Optimise this by making it optional / selective
|
||||
*/
|
||||
const exposeFixtures = async () => {
|
||||
const fixturePromises = {
|
||||
roles: models.Role.findAll({columns: ['id']}),
|
||||
users: models.User.findAll({columns: ['id', 'email']}),
|
||||
tags: models.Tag.findAll({columns: ['id']}),
|
||||
apiKeys: models.ApiKey.findAll({withRelated: 'integration'})
|
||||
};
|
||||
const keys = Object.keys(fixturePromises);
|
||||
existingData = {};
|
||||
|
||||
return Promise
|
||||
.all(Object.values(fixturePromises))
|
||||
.then((results) => {
|
||||
for (let i = 0; i < keys.length; i += 1) {
|
||||
existingData[keys[i]] = results[i].toJSON(context.internal);
|
||||
}
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error('Unable to expose fixtures', err); // eslint-disable-line no-console
|
||||
process.exit(1);
|
||||
});
|
||||
};
|
||||
|
||||
const prepareContentFolder = (options) => {
|
||||
const contentFolderForTests = options.contentFolder;
|
||||
|
||||
/**
|
||||
* We never use the root content folder for testing!
|
||||
* We use a tmp folder.
|
||||
*/
|
||||
configUtils.set('paths:contentPath', contentFolderForTests);
|
||||
|
||||
fs.ensureDirSync(contentFolderForTests);
|
||||
fs.ensureDirSync(path.join(contentFolderForTests, 'data'));
|
||||
fs.ensureDirSync(path.join(contentFolderForTests, 'themes'));
|
||||
fs.ensureDirSync(path.join(contentFolderForTests, 'images'));
|
||||
fs.ensureDirSync(path.join(contentFolderForTests, 'logs'));
|
||||
fs.ensureDirSync(path.join(contentFolderForTests, 'adapters'));
|
||||
fs.ensureDirSync(path.join(contentFolderForTests, 'settings'));
|
||||
|
||||
if (options.copyThemes) {
|
||||
// Copy all themes into the new test content folder. Default active theme is always casper. If you want to use a different theme, you have to set the active theme (e.g. stub)
|
||||
fs.copySync(path.join(__dirname, 'fixtures', 'themes'), path.join(contentFolderForTests, 'themes'));
|
||||
}
|
||||
|
||||
if (options.redirectsFile) {
|
||||
redirects.setupFile(contentFolderForTests, options.redirectsFileExt);
|
||||
}
|
||||
|
||||
if (options.copySettings) {
|
||||
fs.copySync(path.join(__dirname, 'fixtures', 'settings', 'routes.yaml'), path.join(contentFolderForTests, 'settings', 'routes.yaml'));
|
||||
}
|
||||
};
|
||||
|
||||
// CASE: Ghost Server is Running
|
||||
// In this case we need to reset things so it's as though Ghost just booted:
|
||||
// - truncate database
|
||||
// - re-run default fixtures
|
||||
// - reload affected services
|
||||
const restartModeGhostStart = async () => {
|
||||
console.log('Restart Mode'); // eslint-disable-line no-console
|
||||
|
||||
// Teardown truncates all tables and also calls urlServiceUtils.reset();
|
||||
await dbUtils.teardown();
|
||||
|
||||
// The tables have been truncated, this runs the fixture init task (init file 2) to re-add our default fixtures
|
||||
await knexMigrator.init({only: 2});
|
||||
|
||||
// Reset the settings cache
|
||||
// @TODO: Prob A: why/how is this different to using settingsCache.reset()
|
||||
settingsCache.shutdown();
|
||||
await settingsService.init();
|
||||
|
||||
// Reload the frontend
|
||||
await frontendSettingsService.init();
|
||||
await themeService.init();
|
||||
|
||||
// Reload the URL service & wait for it to be ready again
|
||||
// @TODO: Prob B: why/how is this different to urlService.resetGenerators?
|
||||
urlServiceUtils.reset();
|
||||
urlServiceUtils.init();
|
||||
await urlServiceUtils.isFinished();
|
||||
// @TODO: why does this happen _after_ URL service
|
||||
web.shared.middlewares.customRedirects.reload();
|
||||
|
||||
// Trigger themes to load again
|
||||
themeService.loadInactiveThemes();
|
||||
|
||||
// Reload limits service
|
||||
limits.init();
|
||||
};
|
||||
|
||||
const bootGhost = async () => {
|
||||
ghostServer = await boot();
|
||||
};
|
||||
|
||||
// CASE: Ghost Server needs Starting
|
||||
// In this case we need to ensure that Ghost is started cleanly:
|
||||
// - ensure the DB is reset
|
||||
// - CASE: If we are in force start mode the server is already running so we
|
||||
// - stop the server (if we are in force start mode it will be running)
|
||||
// - reload affected services - just settings and not the frontend!?
|
||||
// - Start Ghost: Uses OLD Boot process
|
||||
const freshModeGhostStart = async (options) => {
|
||||
if (options.forceStart) {
|
||||
console.log('Force Start Mode'); // eslint-disable-line no-console
|
||||
} else {
|
||||
console.log('Fresh Start Mode'); // eslint-disable-line no-console
|
||||
}
|
||||
|
||||
// Reset the DB
|
||||
await knexMigrator.reset({force: true});
|
||||
|
||||
// Stop the serve (forceStart Mode)
|
||||
await stopGhost();
|
||||
|
||||
// Reset the settings cache
|
||||
// @TODO: Prob A: why/how is this different to using settingsService.init() and why to do we need this?
|
||||
settingsCache.shutdown();
|
||||
settingsCache.reset();
|
||||
|
||||
// Do a full database initialisation
|
||||
await knexMigrator.init();
|
||||
|
||||
if (config.get('database:client') === 'sqlite3') {
|
||||
await db.knex.raw('PRAGMA journal_mode = TRUNCATE;');
|
||||
}
|
||||
|
||||
// Reset the URL service generators
|
||||
// @TODO: Prob B: why/how is this different to urlService.reset?
|
||||
// @TODO: why would we do this on a fresh boot?!
|
||||
urlService.resetGenerators();
|
||||
|
||||
// Actually boot Ghost
|
||||
await bootGhost(options);
|
||||
|
||||
// Wait for the URL service to be ready, which happens after boot
|
||||
await urlServiceUtils.isFinished();
|
||||
};
|
||||
|
||||
const startGhost = async (options) => {
|
||||
console.time('Start Ghost'); // eslint-disable-line no-console
|
||||
options = _.merge({
|
||||
redirectsFile: true,
|
||||
redirectsFileExt: '.json',
|
||||
forceStart: false,
|
||||
copyThemes: true,
|
||||
copySettings: true,
|
||||
contentFolder: path.join(os.tmpdir(), uuid.v4(), 'ghost-test'),
|
||||
subdir: false
|
||||
}, options);
|
||||
|
||||
// Ensure we have tmp content folders populated ready for testing
|
||||
// @TODO: tidy up the tmp folders after tests
|
||||
prepareContentFolder(options);
|
||||
|
||||
if (ghostServer && ghostServer.httpServer && !options.forceStart) {
|
||||
await restartModeGhostStart(options);
|
||||
} else {
|
||||
await freshModeGhostStart(options);
|
||||
}
|
||||
|
||||
// Expose fixture data, wrap-up and return
|
||||
await exposeFixtures();
|
||||
console.timeEnd('Start Ghost'); // eslint-disable-line no-console
|
||||
return ghostServer;
|
||||
};
|
||||
|
||||
const stopGhost = async () => {
|
||||
if (ghostServer && ghostServer.httpServer) {
|
||||
await ghostServer.stop();
|
||||
delete require.cache[require.resolve('../../core/app')];
|
||||
urlService.resetGenerators();
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
startGhost,
|
||||
stopGhost,
|
||||
getExistingData: () => {
|
||||
return existingData;
|
||||
}
|
||||
};
|
|
@ -1,35 +1,17 @@
|
|||
require('../../core/server/overrides');
|
||||
|
||||
// Utility Packages
|
||||
const Promise = require('bluebird');
|
||||
const {sequence} = require('@tryghost/promise');
|
||||
const _ = require('lodash');
|
||||
const fs = require('fs-extra');
|
||||
const path = require('path');
|
||||
const os = require('os');
|
||||
const uuid = require('uuid');
|
||||
const KnexMigrator = require('knex-migrator');
|
||||
const knexMigrator = new KnexMigrator();
|
||||
|
||||
// Ghost Internals
|
||||
const config = require('../../core/shared/config');
|
||||
const boot = require('../../core/boot');
|
||||
const db = require('../../core/server/data/db');
|
||||
const models = require('../../core/server/models');
|
||||
const urlService = require('../../core/frontend/services/url');
|
||||
const settingsService = require('../../core/server/services/settings');
|
||||
const frontendSettingsService = require('../../core/frontend/services/settings');
|
||||
const settingsCache = require('../../core/server/services/settings/cache');
|
||||
const web = require('../../core/server/web');
|
||||
const themeService = require('../../core/server/services/themes');
|
||||
const limits = require('../../core/server/services/limits');
|
||||
|
||||
// Other Test Utilities
|
||||
const acceptanceUtils = require('./acceptance-utils');
|
||||
const APIUtils = require('./api');
|
||||
const configUtils = require('./configUtils');
|
||||
const dbUtils = require('./db-utils');
|
||||
const fixtureUtils = require('./fixture-utils');
|
||||
const urlServiceUtils = require('./url-service-utils');
|
||||
const oldIntegrationUtils = require('./old-integration-utils');
|
||||
const redirects = require('./redirects');
|
||||
const cacheRules = require('./fixtures/cache-rules');
|
||||
|
@ -110,192 +92,10 @@ const createEmailedPost = async function createEmailedPost({postOptions, emailOp
|
|||
return {post, email};
|
||||
};
|
||||
|
||||
let ghostServer;
|
||||
|
||||
/**
|
||||
* Because we use ObjectID we don't know the ID of fixtures ahead of time
|
||||
* This function fetches all of our fixtures and exposes them so that tests can use them
|
||||
* @TODO: Optimise this by making it optional / selective
|
||||
*/
|
||||
const exposeFixtures = async () => {
|
||||
const fixturePromises = {
|
||||
roles: models.Role.findAll({columns: ['id']}),
|
||||
users: models.User.findAll({columns: ['id', 'email']}),
|
||||
tags: models.Tag.findAll({columns: ['id']}),
|
||||
apiKeys: models.ApiKey.findAll({withRelated: 'integration'})
|
||||
};
|
||||
const keys = Object.keys(fixturePromises);
|
||||
module.exports.existingData = {};
|
||||
|
||||
return Promise
|
||||
.all(Object.values(fixturePromises))
|
||||
.then((results) => {
|
||||
for (let i = 0; i < keys.length; i += 1) {
|
||||
module.exports.existingData[keys[i]] = results[i].toJSON(context.internal);
|
||||
}
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error('Unable to expose fixtures', err); // eslint-disable-line no-console
|
||||
process.exit(1);
|
||||
});
|
||||
};
|
||||
|
||||
const prepareContentFolder = (options) => {
|
||||
const contentFolderForTests = options.contentFolder;
|
||||
|
||||
/**
|
||||
* We never use the root content folder for testing!
|
||||
* We use a tmp folder.
|
||||
*/
|
||||
configUtils.set('paths:contentPath', contentFolderForTests);
|
||||
|
||||
fs.ensureDirSync(contentFolderForTests);
|
||||
fs.ensureDirSync(path.join(contentFolderForTests, 'data'));
|
||||
fs.ensureDirSync(path.join(contentFolderForTests, 'themes'));
|
||||
fs.ensureDirSync(path.join(contentFolderForTests, 'images'));
|
||||
fs.ensureDirSync(path.join(contentFolderForTests, 'logs'));
|
||||
fs.ensureDirSync(path.join(contentFolderForTests, 'adapters'));
|
||||
fs.ensureDirSync(path.join(contentFolderForTests, 'settings'));
|
||||
|
||||
if (options.copyThemes) {
|
||||
// Copy all themes into the new test content folder. Default active theme is always casper. If you want to use a different theme, you have to set the active theme (e.g. stub)
|
||||
fs.copySync(path.join(__dirname, 'fixtures', 'themes'), path.join(contentFolderForTests, 'themes'));
|
||||
}
|
||||
|
||||
if (options.redirectsFile) {
|
||||
redirects.setupFile(contentFolderForTests, options.redirectsFileExt);
|
||||
}
|
||||
|
||||
if (options.copySettings) {
|
||||
fs.copySync(path.join(__dirname, 'fixtures', 'settings', 'routes.yaml'), path.join(contentFolderForTests, 'settings', 'routes.yaml'));
|
||||
}
|
||||
};
|
||||
|
||||
// CASE: Ghost Server is Running
|
||||
// In this case we need to reset things so it's as though Ghost just booted:
|
||||
// - truncate database
|
||||
// - re-run default fixtures
|
||||
// - reload affected services
|
||||
const restartModeGhostStart = async () => {
|
||||
console.log('Restart Mode'); // eslint-disable-line no-console
|
||||
|
||||
// Teardown truncates all tables and also calls urlServiceUtils.reset();
|
||||
await dbUtils.teardown();
|
||||
|
||||
// The tables have been truncated, this runs the fixture init task (init file 2) to re-add our default fixtures
|
||||
await knexMigrator.init({only: 2});
|
||||
|
||||
// Reset the settings cache
|
||||
// @TODO: Prob A: why/how is this different to using settingsCache.reset()
|
||||
settingsCache.shutdown();
|
||||
await settingsService.init();
|
||||
|
||||
// Reload the frontend
|
||||
await frontendSettingsService.init();
|
||||
await themeService.init();
|
||||
|
||||
// Reload the URL service & wait for it to be ready again
|
||||
// @TODO: Prob B: why/how is this different to urlService.resetGenerators?
|
||||
urlServiceUtils.reset();
|
||||
urlServiceUtils.init();
|
||||
await urlServiceUtils.isFinished();
|
||||
// @TODO: why does this happen _after_ URL service
|
||||
web.shared.middlewares.customRedirects.reload();
|
||||
|
||||
// Trigger themes to load again
|
||||
themeService.loadInactiveThemes();
|
||||
|
||||
// Reload limits service
|
||||
limits.init();
|
||||
};
|
||||
|
||||
const bootGhost = async () => {
|
||||
ghostServer = await boot();
|
||||
};
|
||||
|
||||
// CASE: Ghost Server needs Starting
|
||||
// In this case we need to ensure that Ghost is started cleanly:
|
||||
// - ensure the DB is reset
|
||||
// - CASE: If we are in force start mode the server is already running so we
|
||||
// - stop the server (if we are in force start mode it will be running)
|
||||
// - reload affected services - just settings and not the frontend!?
|
||||
// - Start Ghost: Uses OLD Boot process
|
||||
const freshModeGhostStart = async (options) => {
|
||||
if (options.forceStart) {
|
||||
console.log('Force Start Mode'); // eslint-disable-line no-console
|
||||
} else {
|
||||
console.log('Fresh Start Mode'); // eslint-disable-line no-console
|
||||
}
|
||||
|
||||
// Reset the DB
|
||||
await knexMigrator.reset({force: true});
|
||||
|
||||
// Stop the serve (forceStart Mode)
|
||||
await stopGhost();
|
||||
|
||||
// Reset the settings cache
|
||||
// @TODO: Prob A: why/how is this different to using settingsService.init() and why to do we need this?
|
||||
settingsCache.shutdown();
|
||||
settingsCache.reset();
|
||||
|
||||
// Do a full database initialisation
|
||||
await knexMigrator.init();
|
||||
|
||||
if (config.get('database:client') === 'sqlite3') {
|
||||
await db.knex.raw('PRAGMA journal_mode = TRUNCATE;');
|
||||
}
|
||||
|
||||
// Reset the URL service generators
|
||||
// @TODO: Prob B: why/how is this different to urlService.reset?
|
||||
// @TODO: why would we do this on a fresh boot?!
|
||||
urlService.resetGenerators();
|
||||
|
||||
// Actually boot Ghost
|
||||
await bootGhost(options);
|
||||
|
||||
// Wait for the URL service to be ready, which happens after boot
|
||||
await urlServiceUtils.isFinished();
|
||||
};
|
||||
|
||||
const startGhost = async (options) => {
|
||||
console.time('Start Ghost'); // eslint-disable-line no-console
|
||||
options = _.merge({
|
||||
redirectsFile: true,
|
||||
redirectsFileExt: '.json',
|
||||
forceStart: false,
|
||||
copyThemes: true,
|
||||
copySettings: true,
|
||||
contentFolder: path.join(os.tmpdir(), uuid.v4(), 'ghost-test'),
|
||||
subdir: false
|
||||
}, options);
|
||||
|
||||
// Ensure we have tmp content folders populated ready for testing
|
||||
// @TODO: tidy up the tmp folders after tests
|
||||
prepareContentFolder(options);
|
||||
|
||||
if (ghostServer && ghostServer.httpServer && !options.forceStart) {
|
||||
await restartModeGhostStart(options);
|
||||
} else {
|
||||
await freshModeGhostStart(options);
|
||||
}
|
||||
|
||||
// Expose fixture data, wrap-up and return
|
||||
await exposeFixtures();
|
||||
console.timeEnd('Start Ghost'); // eslint-disable-line no-console
|
||||
return ghostServer;
|
||||
};
|
||||
|
||||
const stopGhost = async () => {
|
||||
if (ghostServer && ghostServer.httpServer) {
|
||||
await ghostServer.stop();
|
||||
delete require.cache[require.resolve('../../core/app')];
|
||||
urlService.resetGenerators();
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
startGhost: startGhost,
|
||||
stopGhost: stopGhost,
|
||||
startGhost: acceptanceUtils.startGhost,
|
||||
stopGhost: acceptanceUtils.stopGhost,
|
||||
getExistingData: acceptanceUtils.getExistingData,
|
||||
|
||||
teardownDb: dbUtils.teardown,
|
||||
truncate: dbUtils.truncate,
|
||||
|
|
Loading…
Add table
Reference in a new issue