0
Fork 0
mirror of https://github.com/TryGhost/Ghost.git synced 2025-02-03 23:00:14 -05:00

Added awaiting jobs and events by default to all tests (#16505)

no issue

This change waits for domain events and jobs before continuing with the
next test. This prevents issues where background tasks in tests are
executed when the next test is running and the configurations have
changed, causing random error logs and test failures.

It also includes a change in Stripe mocking in one E2E test to make use
of the new StripeMocker instead of custom mocking in each test (also to
reduce error logs).
This commit is contained in:
Simon Backx 2023-04-06 09:05:16 +02:00 committed by GitHub
parent 16c625a630
commit ba8f082d41
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 110 additions and 101 deletions

View file

@ -1,71 +1,26 @@
const statsService = require('../../../../core/server/services/stats');
const {agentProvider, fixtureManager, mockManager} = require('../../../utils/e2e-framework');
const moment = require('moment');
require('should');
const nock = require('nock');
const {stripeMocker} = require('../../../utils/e2e-framework-mock-manager');
const moment = require('moment');
let agent;
let counter = 0;
async function createMemberWithSubscription(interval, amount, currency, date) {
counter += 1;
const fakePrice = {
id: 'price_' + counter,
product: '',
active: true,
nickname: 'Paid',
unit_amount: amount,
const tier = await stripeMocker.createTier({
currency,
type: 'recurring',
recurring: {
interval
}
};
const fakeSubscription = {
id: 'sub_' + counter,
customer: 'cus_' + counter,
status: 'active',
cancel_at_period_end: false,
metadata: {},
current_period_end: Date.now() / 1000 + 1000,
start_date: moment(date).unix(),
plan: fakePrice,
items: {
data: [{
price: fakePrice
}]
}
};
const fakeCustomer = {
id: 'cus_' + counter,
name: 'Test Member',
email: 'create-member-subscription-' + counter + '@email.com',
subscriptions: {
type: 'list',
data: [fakeSubscription]
}
};
nock('https://api.stripe.com')
.persist()
.get(/v1\/.*/)
.reply((uri) => {
const [match, resource] = uri.match(/\/?v1\/(\w+)\/?(\w+)/) || [null];
if (!match) {
return [500];
}
if (resource === 'customers') {
return [200, fakeCustomer];
}
if (resource === 'subscriptions') {
return [200, fakeSubscription];
}
});
monthly_price: amount,
yearly_price: amount
});
const price = await stripeMocker.getPriceForTier(tier.get('slug'), interval);
const fakeCustomer = stripeMocker.createCustomer({});
await stripeMocker.createSubscription({
customer: fakeCustomer,
price,
start_date: moment(date).unix()
}, {
sendWebhook: false
});
const initialMember = {
name: fakeCustomer.name,
@ -78,8 +33,6 @@ async function createMemberWithSubscription(interval, amount, currency, date) {
.post(`/members/`)
.body({members: [initialMember]})
.expectStatus(201);
nock.cleanAll();
}
describe('MRR Stats Service', function () {
@ -87,15 +40,15 @@ describe('MRR Stats Service', function () {
agent = await agentProvider.getAdminAPIAgent();
await fixtureManager.init();
await agent.loginAsOwner();
mockManager.mockMail();
});
after(async function () {
mockManager.restore();
beforeEach(function () {
mockManager.mockMail();
mockManager.mockStripe();
});
afterEach(function () {
nock.cleanAll();
mockManager.restore();
});
describe('getCurrentMrr', function () {
@ -103,7 +56,7 @@ describe('MRR Stats Service', function () {
const result = await statsService.mrr.getCurrentMrr();
result.should.eql([
{
currency: 'usd',
currency: 'usd', // need to check capital usage here!
mrr: 0
}
]);
@ -114,7 +67,7 @@ describe('MRR Stats Service', function () {
const result = await statsService.mrr.getCurrentMrr();
result.should.eql([
{
currency: 'eur',
currency: 'EUR',
mrr: 500
}
]);
@ -125,11 +78,11 @@ describe('MRR Stats Service', function () {
const result = await statsService.mrr.getCurrentMrr();
result.should.eql([
{
currency: 'eur',
currency: 'EUR',
mrr: 500
},
{
currency: 'usd',
currency: 'USD',
mrr: 1
}
]);
@ -140,11 +93,11 @@ describe('MRR Stats Service', function () {
const result = await statsService.mrr.getCurrentMrr();
result.should.eql([
{
currency: 'eur',
currency: 'EUR',
mrr: 500
},
{
currency: 'usd',
currency: 'USD',
mrr: 2
}
]);
@ -155,11 +108,11 @@ describe('MRR Stats Service', function () {
let result = await statsService.mrr.getCurrentMrr();
result.should.eql([
{
currency: 'eur',
currency: 'EUR',
mrr: 500
},
{
currency: 'usd',
currency: 'USD',
mrr: 3
}
]);
@ -169,11 +122,11 @@ describe('MRR Stats Service', function () {
result = await statsService.mrr.getCurrentMrr();
result.should.eql([
{
currency: 'eur',
currency: 'EUR',
mrr: 500
},
{
currency: 'usd',
currency: 'USD',
mrr: 3
}
]);
@ -183,11 +136,11 @@ describe('MRR Stats Service', function () {
result = await statsService.mrr.getCurrentMrr();
result.should.eql([
{
currency: 'eur',
currency: 'EUR',
mrr: 500
},
{
currency: 'usd',
currency: 'USD',
mrr: 3
}
]);
@ -197,11 +150,11 @@ describe('MRR Stats Service', function () {
result = await statsService.mrr.getCurrentMrr();
result.should.eql([
{
currency: 'eur',
currency: 'EUR',
mrr: 500
},
{
currency: 'usd',
currency: 'USD',
mrr: 4
}
]);
@ -216,22 +169,22 @@ describe('MRR Stats Service', function () {
{
date: '2000-01-10',
delta: 500,
currency: 'eur'
currency: 'EUR'
},
{
date: '2000-01-10',
delta: 1,
currency: 'usd'
currency: 'USD'
},
{
date: '2000-01-11',
delta: 1,
currency: 'usd'
currency: 'USD'
},
{
date: '2000-01-12',
delta: 2,
currency: 'usd'
currency: 'USD'
}
]);
});

View file

@ -17,3 +17,21 @@ mochaHooks.beforeAll = async function () {
// Disable network in tests to prevent any accidental requests
mockManager.disableNetwork();
};
const originalAfterEach = mochaHooks.afterEach;
mochaHooks.afterEach = async function () {
const domainEvents = require('@tryghost/domain-events');
const mentionsJobsService = require('../../core/server/services/mentions-jobs');
const jobsService = require('../../core/server/services/jobs');
await domainEvents.allSettled();
await mentionsJobsService.allSettled();
await jobsService.allSettled();
// Last time for events emitted during jobs
await domainEvents.allSettled();
if (originalAfterEach) {
await originalAfterEach();
}
};

View file

@ -19,6 +19,8 @@ class StripeMocker {
prices = [];
products = [];
nockInterceptors = [];
constructor(data = {}) {
this.customers = data.customers ?? [];
this.subscriptions = data.subscriptions ?? [];
@ -80,6 +82,25 @@ class StripeMocker {
return this.#getData(this.prices, id)[1];
}
/**
*
* @param {object} data
* @param {string} [data.name]
* @param {string} data.currency
* @param {number} data.monthly_price
* @param {number} data.yearly_price
* @returns
*/
async createTier({name, currency, monthly_price, yearly_price}) {
return await models.Product.add({
name: name ?? ('Tier ' + this.#generateRandomId()),
type: 'paid',
currency: currency.toUpperCase(),
monthly_price,
yearly_price
});
}
async createTrialSubscription({customer, price, ...overrides}) {
return await this.createSubscription({
customer,
@ -113,7 +134,7 @@ class StripeMocker {
await DomainEvents.allSettled();
}
async createSubscription({customer, price, ...overrides}) {
async createSubscription({customer, price, ...overrides}, options = {sendWebhook: true}) {
const subscriptionId = `sub_${this.#generateRandomId()}`;
const subscription = {
@ -140,18 +161,20 @@ class StripeMocker {
customer.subscriptions.data.push(subscription);
// Announce
await this.sendWebhook({
type: 'checkout.session.completed',
data: {
object: {
mode: 'subscription',
customer: customer.id,
metadata: {
checkoutType: 'signup'
if (options.sendWebhook) {
await this.sendWebhook({
type: 'checkout.session.completed',
data: {
object: {
mode: 'subscription',
customer: customer.id,
metadata: {
checkoutType: 'signup'
}
}
}
}
});
});
}
return subscription;
}
@ -266,10 +289,21 @@ class StripeMocker {
return [200, subscription];
}
remove() {
for (const interceptor of this.nockInterceptors) {
nock.removeInterceptor(interceptor);
}
this.nockInterceptors = [];
}
stub() {
nock('https://api.stripe.com')
this.remove();
let interceptor = nock('https://api.stripe.com')
.persist()
.get(/v1\/.*/)
.get(/v1\/.*/);
this.nockInterceptors.push(interceptor);
interceptor
.reply((uri) => {
const [match, resource, id] = uri.match(/\/?v1\/(\w+)\/?(\w+)/) || [null];
@ -308,9 +342,11 @@ class StripeMocker {
return [500];
});
nock('https://api.stripe.com')
interceptor = nock('https://api.stripe.com')
.persist()
.post(/v1\/.*/)
.post(/v1\/.*/);
this.nockInterceptors.push(interceptor);
interceptor
.reply((uri, body) => {
const [match, resource, id] = uri.match(/\/?v1\/(\w+)(?:\/?(\w+)){0,2}/) || [null];
@ -345,9 +381,11 @@ class StripeMocker {
return [500];
});
nock('https://api.stripe.com')
interceptor = nock('https://api.stripe.com')
.persist()
.delete(/v1\/.*/)
.delete(/v1\/.*/);
this.nockInterceptors.push(interceptor);
interceptor
.reply((uri) => {
const [match, resource, id] = uri.match(/\/?v1\/(\w+)(?:\/?(\w+)){0,2}/) || [null];