mirror of
https://github.com/TryGhost/Ghost.git
synced 2025-02-10 23:36:14 -05:00
Added e2e framework
refs 24505db918
- The code is heavily borrowed from the referenced commit by @ErisDS. It starts a fresh abstraction layer for all e2e tests to use, provides simle interface for request agent initialization and state management (read the e2e-framework top file description for more)
- Main methods the framework exposes are:
- getAgent - to initialize request agent with a fresh Ghost instance
- initFixtures - to initializer a fresh db state
- resetDb - cleans up the db state if there were state manipulations during the test suite run (POST, PUT requests or non-default fixtures)
This commit is contained in:
parent
6762e2a60d
commit
2ae0d8ef32
2 changed files with 130 additions and 7 deletions
|
@ -2,7 +2,7 @@
|
|||
// The e2e tests usually consist of following building blocks:
|
||||
// - request agent
|
||||
// - state builder
|
||||
// - output state checker
|
||||
// - output state checker (in case we don't get jest snapshots working)
|
||||
//
|
||||
// The request agetnt is responsible for making HTTP-like requests to an application (express app in case of Ghost).
|
||||
// Note there's no actual need to make an HTTP request to an actual server, bypassing HTTP and hooking into the application
|
||||
|
@ -12,12 +12,15 @@
|
|||
// Can include building a DB state, file system state (themes, config files), building configuration state (config files) etc.
|
||||
//
|
||||
// The output state checker is responsible for checking the response from the app after performing a request.
|
||||
|
||||
const supertest = require('supertest');
|
||||
const _ = require('lodash');
|
||||
const {sequence} = require('@tryghost/promise');
|
||||
const fixtures = require('./fixture-utils');
|
||||
|
||||
const boot = require('../../core/boot');
|
||||
const TestAgent = require('./test-agent');
|
||||
const db = require('./db-utils');
|
||||
|
||||
const startGhost = () => {
|
||||
const startGhost = async () => {
|
||||
const defaults = {
|
||||
backend: true,
|
||||
frontend: false,
|
||||
|
@ -27,10 +30,47 @@ const startGhost = () => {
|
|||
return boot(defaults);
|
||||
};
|
||||
|
||||
const getAgent = async () => {
|
||||
const app = await startGhost();
|
||||
/**
|
||||
* Database state builder. By default inserts an owner user into the database.
|
||||
* @param {...any} [options]
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
const initFixtures = async (...options) => {
|
||||
// No DB setup, but override the owner
|
||||
options = _.merge({'owner:post': true}, _.transform(options, function (result, val) {
|
||||
if (val) {
|
||||
result[val] = true;
|
||||
}
|
||||
}));
|
||||
|
||||
return supertest.agent(app);
|
||||
const fixtureOps = fixtures.getFixtureOps(options);
|
||||
|
||||
return sequence(fixtureOps);
|
||||
};
|
||||
|
||||
const getFixture = (type, index = 0) => {
|
||||
return fixtures.DataGenerator.forKnex[type][index];
|
||||
};
|
||||
|
||||
const resetDb = async () => {
|
||||
await db.teardown();
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates a TestAgent which is a drop-in substitution for supertest hooked into Ghost.
|
||||
* @param {String} apiURL
|
||||
* @returns {TestAgent}
|
||||
*/
|
||||
const getAgent = async (apiURL) => {
|
||||
const app = await startGhost();
|
||||
|
||||
return new TestAgent(apiURL, app);
|
||||
};
|
||||
|
||||
// request agent
|
||||
module.exports.getAgent = getAgent;
|
||||
|
||||
// state building
|
||||
module.exports.initFixtures = initFixtures;
|
||||
module.exports.getFixture = getFixture;
|
||||
module.exports.resetDb = resetDb;
|
||||
|
|
83
test/utils/test-agent.js
Normal file
83
test/utils/test-agent.js
Normal file
|
@ -0,0 +1,83 @@
|
|||
const supertest = require('supertest');
|
||||
const errors = require('@tryghost/errors');
|
||||
|
||||
class TestAgent {
|
||||
/**
|
||||
* @constructor
|
||||
* @param {String} API_URL
|
||||
* @param {Object} app Ghost express app instance
|
||||
*/
|
||||
constructor(API_URL, app) {
|
||||
this.API_URL = API_URL;
|
||||
this.app = app;
|
||||
this.request = supertest.agent(app);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to concatenate urls
|
||||
* @NOTE: this is essentially a duplicate of our internal urljoin tool that is stuck in the too-big url-utils package atm
|
||||
* @param {string} url
|
||||
* @returns
|
||||
*/
|
||||
makeUrl(url) {
|
||||
// Join the base URL and the main url and remove any duplicate slashes
|
||||
return `${this.API_URL}/${url}`.replace(/(^|[^:])\/\/+/g, '$1/');
|
||||
}
|
||||
|
||||
// Forward get(), post(), put(), and delete() straight to the request agent & handle the URL
|
||||
get(url) {
|
||||
return this.request.get(this.makeUrl(url));
|
||||
}
|
||||
|
||||
post(url) {
|
||||
return this.request.post(this.makeUrl(url));
|
||||
}
|
||||
|
||||
put(url) {
|
||||
return this.request.put(this.makeUrl(url));
|
||||
}
|
||||
|
||||
delete(url) {
|
||||
return this.request.delete(this.makeUrl(url));
|
||||
}
|
||||
|
||||
async loginAs(email, password) {
|
||||
await this.post('/session/')
|
||||
.send({
|
||||
grant_type: 'password',
|
||||
username: email,
|
||||
password: password
|
||||
})
|
||||
.then(function then(res) {
|
||||
if (res.statusCode === 302) {
|
||||
// This can happen if you already have an instance running e.g. if you've been using Ghost CLI recently
|
||||
throw new errors.IncorrectUsageError({
|
||||
message: 'Ghost is redirecting, do you have an instance already running on port 2369?'
|
||||
});
|
||||
} else if (res.statusCode !== 200 && res.statusCode !== 201) {
|
||||
throw new errors.IncorrectUsageError({
|
||||
message: res.body.errors[0].message
|
||||
});
|
||||
}
|
||||
|
||||
return res.headers['set-cookie'];
|
||||
});
|
||||
}
|
||||
|
||||
async loginAsOwner() {
|
||||
// temporary copy-pasta
|
||||
let user = {
|
||||
// owner (owner is still id 1 because of permissions)
|
||||
id: '1',
|
||||
name: 'Joe Bloggs',
|
||||
slug: 'joe-bloggs',
|
||||
email: 'jbloggs@example.com',
|
||||
password: 'Sl1m3rson99',
|
||||
profile_image: 'https://example.com/super_photo.jpg'
|
||||
};
|
||||
|
||||
await this.loginAs(user.email, user.password);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = TestAgent;
|
Loading…
Add table
Reference in a new issue