Cleaned up test utils with async/await

- I'm on a mission to make this code comprehensible so we can work it into something better with new boot
- Who else loves async/await? :D
- Dried up a block of duplicated code
This commit is contained in:
Hannah Wolfe 2021-02-17 20:37:49 +00:00
parent 2c96df42ac
commit 24bfb5567b
4 changed files with 164 additions and 147 deletions

66
test/new/magic_spec.js Normal file
View File

@ -0,0 +1,66 @@
// # Default Frontend Routing Test
// These tests check the default out-of-the-box behaviour of Ghost is working as expected.
// Test Structure
// As it stands, these tests depend on the database, and as such are integration tests.
// Mocking out the models to not touch the DB would turn these into unit tests, and should probably be done in future,
// But then again testing real code, rather than mock code, might be more useful...
const should = require('should');
const sinon = require('sinon');
const supertest = require('supertest');
const testUtils = require('./utils');
const configUtils = require('../utils/configUtils');
describe('Default Frontend routing', function () {
let request;
afterEach(function () {
sinon.restore();
});
before(async function () {
await testUtils.startGhost();
request = supertest.agent(configUtils.config.get('url'));
});
describe('Main Routes', function () {
it('/ should respond with valid HTML', async function () {
await request.get('/')
.expect((res) => {
console.log(res.text);
})
.expect(200)
.expect('Content-Type', /html/)
.expect('Cache-Control', testUtils.cacheRules.public);
// const $ = cheerio.load(res.text);
// // NOTE: "Ghost" is the title from the settings.
// $('title').text().should.equal('Ghost');
// $('body.home-template').length.should.equal(1);
// $('article.post').length.should.equal(7);
// $('article.tag-getting-started').length.should.equal(7);
// doEnd(res);
});
it('/author/ghost/ should respond with valid HTML', async function () {
await request.get('/author/ghost/')
.expect('Content-Type', /html/);
// .expect('Cache-Control', testUtils.cacheRules.public)
// .expect(200);
// const $ = cheerio.load(res.text);
// // NOTE: "Ghost" is the title from the settings.
// $('title').text().should.equal('Ghost - Ghost');
// $('body.author-template').length.should.equal(1);
// $('article.post').length.should.equal(7);
// $('article.tag-getting-started').length.should.equal(7);
// doEnd(res);
});
});
});

14
test/new/utils.js Normal file
View File

@ -0,0 +1,14 @@
const boot = require('../../core/boot');
const urlServiceUtils = require('../utils/url-service-utils');
const cacheRules = require('../utils/fixtures/cache-rules');
module.exports.startGhost = async () => {
const startTime = Date.now();
await boot();
console.log(`Ghost booted in ${(Date.now() - startTime) / 1000}s`); // eslint-disable-line no-console
await urlServiceUtils.isFinished();
console.log(`Ghost ready in ${(Date.now() - startTime) / 1000}s`); // eslint-disable-line no-console
};
module.exports.cacheRules = cacheRules;

View File

@ -15,38 +15,27 @@ const schemaTables = Object.keys(schema);
// Other Test Utilities
const urlServiceUtils = require('./url-service-utils');
module.exports.initData = () => {
return knexMigrator.init()
.then(function () {
return urlServiceUtils.isFinished();
});
module.exports.initData = async () => {
await knexMigrator.init();
await urlServiceUtils.isFinished();
};
module.exports.clearBruteData = () => {
return db.knex('brute').truncate();
};
module.exports.truncate = (tableName) => {
module.exports.truncate = async (tableName) => {
if (config.get('database:client') === 'sqlite3') {
return db.knex(tableName).truncate();
await db.knex(tableName).truncate();
return;
}
return db.knex.raw('SET FOREIGN_KEY_CHECKS=0;')
.then(function () {
return db.knex(tableName).truncate();
})
.then(function () {
return db.knex.raw('SET FOREIGN_KEY_CHECKS=1;');
});
await db.knex.raw('SET FOREIGN_KEY_CHECKS=0;');
await db.knex(tableName).truncate();
await db.knex.raw('SET FOREIGN_KEY_CHECKS=1;');
};
// we must always try to delete all tables
module.exports.clearData = () => {
module.exports.clearData = async () => {
debug('Database reset');
return knexMigrator.reset({force: true})
.then(function () {
urlServiceUtils.reset();
});
await knexMigrator.reset({force: true});
urlServiceUtils.reset();
};
/**

View File

@ -115,6 +115,34 @@ const createEmailedPost = async function createEmailedPost({postOptions, emailOp
let ghostServer;
const dirtyDataFunction = () => {
/**
* @TODO: this is dirty, but makes routing testing a lot easier for now, because the routing test
* has no easy way to access existing resource id's, which are added from the Ghost fixtures.
* I can do `testUtils.existingData.roles[0].id`.
*/
module.exports.existingData = {};
return models.Role.findAll({columns: ['id']})
.then((roles) => {
module.exports.existingData.roles = roles.toJSON();
return models.User.findAll({columns: ['id', 'email']});
})
.then((users) => {
module.exports.existingData.users = users.toJSON(context.internal);
return models.Tag.findAll({columns: ['id']});
})
.then((tags) => {
module.exports.existingData.tags = tags.toJSON();
return models.ApiKey.findAll({withRelated: 'integration'});
})
.then((keys) => {
module.exports.existingData.apiKeys = keys.toJSON(context.internal);
});
};
/**
* 1. reset & init db
* 2. start the server once
@ -166,149 +194,70 @@ const startGhost = async function startGhost(options) {
// truncate database and re-run fixtures
// we have to ensure that some components in Ghost are reloaded
if (ghostServer && ghostServer.httpServer && !options.forceStart) {
return dbUtils.teardown()
.then(function () {
return knexMigrator.init({only: 2});
})
.then(function () {
settingsCache.shutdown();
return settingsService.init();
})
.then(function () {
return frontendSettingsService.init();
})
.then(function () {
return themes.init();
})
.then(function () {
urlServiceUtils.reset();
return urlServiceUtils.isFinished();
})
.then(function () {
web.shared.middlewares.customRedirects.reload();
await dbUtils.teardown();
events.emit('server.start');
await knexMigrator.init({only: 2});
/**
* @TODO: this is dirty, but makes routing testing a lot easier for now, because the routing test
* has no easy way to access existing resource id's, which are added from the Ghost fixtures.
* I can do `testUtils.existingData.roles[0].id`.
*/
module.exports.existingData = {};
return models.Role.findAll({columns: ['id']})
.then((roles) => {
module.exports.existingData.roles = roles.toJSON();
settingsCache.shutdown();
await settingsService.init();
return models.User.findAll({columns: ['id', 'email']});
})
.then((users) => {
module.exports.existingData.users = users.toJSON(context.internal);
await frontendSettingsService.init();
await themes.init();
return models.Tag.findAll({columns: ['id']});
})
.then((tags) => {
module.exports.existingData.tags = tags.toJSON();
return models.ApiKey.findAll({withRelated: 'integration'});
})
.then((keys) => {
module.exports.existingData.apiKeys = keys.toJSON(context.internal);
console.timeEnd('Start Ghost'); // eslint-disable-line no-console
})
.return(ghostServer);
});
urlServiceUtils.reset();
await urlServiceUtils.isFinished();
web.shared.middlewares.customRedirects.reload();
events.emit('server.start');
await dirtyDataFunction();
console.log('Restart Mode'); // eslint-disable-line no-console
console.timeEnd('Start Ghost'); // eslint-disable-line no-console
return ghostServer;
}
return knexMigrator.reset({force: true})
.then(function () {
if (ghostServer && ghostServer.httpServer) {
return ghostServer.stop();
}
})
.then(function initialiseDatabase() {
settingsCache.shutdown();
settingsCache.reset();
return knexMigrator.init();
})
.then(function setPragma() {
if (config.get('database:client') === 'sqlite3') {
return db.knex.raw('PRAGMA journal_mode = TRUNCATE;');
} else {
return Promise.resolve();
}
})
.then(function initializeGhost() {
urlService.resetGenerators();
await knexMigrator.reset({force: true});
return ghost();
})
.then(function startGhostServer(_ghostServer) {
ghostServer = _ghostServer;
if (ghostServer && ghostServer.httpServer) {
await ghostServer.stop();
}
if (options.subdir) {
parentApp = express('test parent');
parentApp.use(urlUtils.getSubdir(), ghostServer.rootApp);
return ghostServer.start(parentApp);
}
settingsCache.shutdown();
settingsCache.reset();
await knexMigrator.init();
return ghostServer.start();
})
.then(function () {
let timeout;
if (config.get('database:client') === 'sqlite3') {
await db.knex.raw('PRAGMA journal_mode = TRUNCATE;');
}
GhostServer.announceServerReadiness();
urlService.resetGenerators();
return new Promise(function (resolve) {
(function retry() {
clearTimeout(timeout);
ghostServer = await ghost();
if (urlService.hasFinished()) {
return resolve();
}
if (options.subdir) {
parentApp = express('test parent');
parentApp.use(urlUtils.getSubdir(), ghostServer.rootApp);
await ghostServer.start(parentApp);
} else {
await ghostServer.start();
}
timeout = setTimeout(retry, 50);
})();
});
})
.then(function returnGhost() {
/**
* @TODO: this is dirty, but makes routing testing a lot easier for now, because the routing test
* has no easy way to access existing resource id's, which are added from the Ghost fixtures.
* I can do `testUtils.existingData.roles[0].id`.
*/
module.exports.existingData = {};
return models.Role.findAll({columns: ['id']})
.then((roles) => {
module.exports.existingData.roles = roles.toJSON();
GhostServer.announceServerReadiness();
await urlServiceUtils.isFinished({disableDbReadyEvent: true});
return models.User.findAll({columns: ['id', 'email']});
})
.then((users) => {
module.exports.existingData.users = users.toJSON(context.internal);
return models.Tag.findAll({columns: ['id']});
})
.then((tags) => {
module.exports.existingData.tags = tags.toJSON();
return models.ApiKey.findAll({withRelated: 'integration'});
})
.then((keys) => {
module.exports.existingData.apiKeys = keys.toJSON();
console.timeEnd('Start Ghost'); // eslint-disable-line no-console
})
.return(ghostServer);
});
await dirtyDataFunction();
console.log('Fresh Start Mode'); // eslint-disable-line no-console
console.timeEnd('Start Ghost'); // eslint-disable-line no-console
return ghostServer;
};
module.exports = {
startGhost: startGhost,
stopGhost: () => {
stopGhost: async () => {
if (ghostServer && ghostServer.httpServer) {
return ghostServer.stop()
.then(() => {
urlService.resetGenerators();
});
await ghostServer.stop();
urlService.resetGenerators();
}
},
teardownDb: dbUtils.teardown,
@ -351,7 +300,6 @@ module.exports = {
initFixtures: initFixtures,
initData: dbUtils.initData,
clearData: dbUtils.clearData,
clearBruteData: dbUtils.clearBruteData,
setupRedirectsFile: redirects.setupFile,
fixtures: fixtureUtils.fixtures,