mirror of
https://github.com/TryGhost/Ghost.git
synced 2025-02-10 23:36: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:
parent
16c625a630
commit
ba8f082d41
3 changed files with 110 additions and 101 deletions
|
@ -1,71 +1,26 @@
|
||||||
const statsService = require('../../../../core/server/services/stats');
|
const statsService = require('../../../../core/server/services/stats');
|
||||||
const {agentProvider, fixtureManager, mockManager} = require('../../../utils/e2e-framework');
|
const {agentProvider, fixtureManager, mockManager} = require('../../../utils/e2e-framework');
|
||||||
const moment = require('moment');
|
|
||||||
require('should');
|
require('should');
|
||||||
const nock = require('nock');
|
const {stripeMocker} = require('../../../utils/e2e-framework-mock-manager');
|
||||||
|
const moment = require('moment');
|
||||||
|
|
||||||
let agent;
|
let agent;
|
||||||
let counter = 0;
|
|
||||||
|
|
||||||
async function createMemberWithSubscription(interval, amount, currency, date) {
|
async function createMemberWithSubscription(interval, amount, currency, date) {
|
||||||
counter += 1;
|
const tier = await stripeMocker.createTier({
|
||||||
|
|
||||||
const fakePrice = {
|
|
||||||
id: 'price_' + counter,
|
|
||||||
product: '',
|
|
||||||
active: true,
|
|
||||||
nickname: 'Paid',
|
|
||||||
unit_amount: amount,
|
|
||||||
currency,
|
currency,
|
||||||
type: 'recurring',
|
monthly_price: amount,
|
||||||
recurring: {
|
yearly_price: amount
|
||||||
interval
|
});
|
||||||
}
|
const price = await stripeMocker.getPriceForTier(tier.get('slug'), interval);
|
||||||
};
|
const fakeCustomer = stripeMocker.createCustomer({});
|
||||||
|
await stripeMocker.createSubscription({
|
||||||
const fakeSubscription = {
|
customer: fakeCustomer,
|
||||||
id: 'sub_' + counter,
|
price,
|
||||||
customer: 'cus_' + counter,
|
start_date: moment(date).unix()
|
||||||
status: 'active',
|
}, {
|
||||||
cancel_at_period_end: false,
|
sendWebhook: 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];
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const initialMember = {
|
const initialMember = {
|
||||||
name: fakeCustomer.name,
|
name: fakeCustomer.name,
|
||||||
|
@ -78,8 +33,6 @@ async function createMemberWithSubscription(interval, amount, currency, date) {
|
||||||
.post(`/members/`)
|
.post(`/members/`)
|
||||||
.body({members: [initialMember]})
|
.body({members: [initialMember]})
|
||||||
.expectStatus(201);
|
.expectStatus(201);
|
||||||
|
|
||||||
nock.cleanAll();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
describe('MRR Stats Service', function () {
|
describe('MRR Stats Service', function () {
|
||||||
|
@ -87,15 +40,15 @@ describe('MRR Stats Service', function () {
|
||||||
agent = await agentProvider.getAdminAPIAgent();
|
agent = await agentProvider.getAdminAPIAgent();
|
||||||
await fixtureManager.init();
|
await fixtureManager.init();
|
||||||
await agent.loginAsOwner();
|
await agent.loginAsOwner();
|
||||||
mockManager.mockMail();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
after(async function () {
|
beforeEach(function () {
|
||||||
mockManager.restore();
|
mockManager.mockMail();
|
||||||
|
mockManager.mockStripe();
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(function () {
|
afterEach(function () {
|
||||||
nock.cleanAll();
|
mockManager.restore();
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('getCurrentMrr', function () {
|
describe('getCurrentMrr', function () {
|
||||||
|
@ -103,7 +56,7 @@ describe('MRR Stats Service', function () {
|
||||||
const result = await statsService.mrr.getCurrentMrr();
|
const result = await statsService.mrr.getCurrentMrr();
|
||||||
result.should.eql([
|
result.should.eql([
|
||||||
{
|
{
|
||||||
currency: 'usd',
|
currency: 'usd', // need to check capital usage here!
|
||||||
mrr: 0
|
mrr: 0
|
||||||
}
|
}
|
||||||
]);
|
]);
|
||||||
|
@ -114,7 +67,7 @@ describe('MRR Stats Service', function () {
|
||||||
const result = await statsService.mrr.getCurrentMrr();
|
const result = await statsService.mrr.getCurrentMrr();
|
||||||
result.should.eql([
|
result.should.eql([
|
||||||
{
|
{
|
||||||
currency: 'eur',
|
currency: 'EUR',
|
||||||
mrr: 500
|
mrr: 500
|
||||||
}
|
}
|
||||||
]);
|
]);
|
||||||
|
@ -125,11 +78,11 @@ describe('MRR Stats Service', function () {
|
||||||
const result = await statsService.mrr.getCurrentMrr();
|
const result = await statsService.mrr.getCurrentMrr();
|
||||||
result.should.eql([
|
result.should.eql([
|
||||||
{
|
{
|
||||||
currency: 'eur',
|
currency: 'EUR',
|
||||||
mrr: 500
|
mrr: 500
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
currency: 'usd',
|
currency: 'USD',
|
||||||
mrr: 1
|
mrr: 1
|
||||||
}
|
}
|
||||||
]);
|
]);
|
||||||
|
@ -140,11 +93,11 @@ describe('MRR Stats Service', function () {
|
||||||
const result = await statsService.mrr.getCurrentMrr();
|
const result = await statsService.mrr.getCurrentMrr();
|
||||||
result.should.eql([
|
result.should.eql([
|
||||||
{
|
{
|
||||||
currency: 'eur',
|
currency: 'EUR',
|
||||||
mrr: 500
|
mrr: 500
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
currency: 'usd',
|
currency: 'USD',
|
||||||
mrr: 2
|
mrr: 2
|
||||||
}
|
}
|
||||||
]);
|
]);
|
||||||
|
@ -155,11 +108,11 @@ describe('MRR Stats Service', function () {
|
||||||
let result = await statsService.mrr.getCurrentMrr();
|
let result = await statsService.mrr.getCurrentMrr();
|
||||||
result.should.eql([
|
result.should.eql([
|
||||||
{
|
{
|
||||||
currency: 'eur',
|
currency: 'EUR',
|
||||||
mrr: 500
|
mrr: 500
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
currency: 'usd',
|
currency: 'USD',
|
||||||
mrr: 3
|
mrr: 3
|
||||||
}
|
}
|
||||||
]);
|
]);
|
||||||
|
@ -169,11 +122,11 @@ describe('MRR Stats Service', function () {
|
||||||
result = await statsService.mrr.getCurrentMrr();
|
result = await statsService.mrr.getCurrentMrr();
|
||||||
result.should.eql([
|
result.should.eql([
|
||||||
{
|
{
|
||||||
currency: 'eur',
|
currency: 'EUR',
|
||||||
mrr: 500
|
mrr: 500
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
currency: 'usd',
|
currency: 'USD',
|
||||||
mrr: 3
|
mrr: 3
|
||||||
}
|
}
|
||||||
]);
|
]);
|
||||||
|
@ -183,11 +136,11 @@ describe('MRR Stats Service', function () {
|
||||||
result = await statsService.mrr.getCurrentMrr();
|
result = await statsService.mrr.getCurrentMrr();
|
||||||
result.should.eql([
|
result.should.eql([
|
||||||
{
|
{
|
||||||
currency: 'eur',
|
currency: 'EUR',
|
||||||
mrr: 500
|
mrr: 500
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
currency: 'usd',
|
currency: 'USD',
|
||||||
mrr: 3
|
mrr: 3
|
||||||
}
|
}
|
||||||
]);
|
]);
|
||||||
|
@ -197,11 +150,11 @@ describe('MRR Stats Service', function () {
|
||||||
result = await statsService.mrr.getCurrentMrr();
|
result = await statsService.mrr.getCurrentMrr();
|
||||||
result.should.eql([
|
result.should.eql([
|
||||||
{
|
{
|
||||||
currency: 'eur',
|
currency: 'EUR',
|
||||||
mrr: 500
|
mrr: 500
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
currency: 'usd',
|
currency: 'USD',
|
||||||
mrr: 4
|
mrr: 4
|
||||||
}
|
}
|
||||||
]);
|
]);
|
||||||
|
@ -216,22 +169,22 @@ describe('MRR Stats Service', function () {
|
||||||
{
|
{
|
||||||
date: '2000-01-10',
|
date: '2000-01-10',
|
||||||
delta: 500,
|
delta: 500,
|
||||||
currency: 'eur'
|
currency: 'EUR'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
date: '2000-01-10',
|
date: '2000-01-10',
|
||||||
delta: 1,
|
delta: 1,
|
||||||
currency: 'usd'
|
currency: 'USD'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
date: '2000-01-11',
|
date: '2000-01-11',
|
||||||
delta: 1,
|
delta: 1,
|
||||||
currency: 'usd'
|
currency: 'USD'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
date: '2000-01-12',
|
date: '2000-01-12',
|
||||||
delta: 2,
|
delta: 2,
|
||||||
currency: 'usd'
|
currency: 'USD'
|
||||||
}
|
}
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
|
@ -17,3 +17,21 @@ mochaHooks.beforeAll = async function () {
|
||||||
// Disable network in tests to prevent any accidental requests
|
// Disable network in tests to prevent any accidental requests
|
||||||
mockManager.disableNetwork();
|
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();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
|
@ -19,6 +19,8 @@ class StripeMocker {
|
||||||
prices = [];
|
prices = [];
|
||||||
products = [];
|
products = [];
|
||||||
|
|
||||||
|
nockInterceptors = [];
|
||||||
|
|
||||||
constructor(data = {}) {
|
constructor(data = {}) {
|
||||||
this.customers = data.customers ?? [];
|
this.customers = data.customers ?? [];
|
||||||
this.subscriptions = data.subscriptions ?? [];
|
this.subscriptions = data.subscriptions ?? [];
|
||||||
|
@ -80,6 +82,25 @@ class StripeMocker {
|
||||||
return this.#getData(this.prices, id)[1];
|
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}) {
|
async createTrialSubscription({customer, price, ...overrides}) {
|
||||||
return await this.createSubscription({
|
return await this.createSubscription({
|
||||||
customer,
|
customer,
|
||||||
|
@ -113,7 +134,7 @@ class StripeMocker {
|
||||||
await DomainEvents.allSettled();
|
await DomainEvents.allSettled();
|
||||||
}
|
}
|
||||||
|
|
||||||
async createSubscription({customer, price, ...overrides}) {
|
async createSubscription({customer, price, ...overrides}, options = {sendWebhook: true}) {
|
||||||
const subscriptionId = `sub_${this.#generateRandomId()}`;
|
const subscriptionId = `sub_${this.#generateRandomId()}`;
|
||||||
|
|
||||||
const subscription = {
|
const subscription = {
|
||||||
|
@ -140,18 +161,20 @@ class StripeMocker {
|
||||||
customer.subscriptions.data.push(subscription);
|
customer.subscriptions.data.push(subscription);
|
||||||
|
|
||||||
// Announce
|
// Announce
|
||||||
await this.sendWebhook({
|
if (options.sendWebhook) {
|
||||||
type: 'checkout.session.completed',
|
await this.sendWebhook({
|
||||||
data: {
|
type: 'checkout.session.completed',
|
||||||
object: {
|
data: {
|
||||||
mode: 'subscription',
|
object: {
|
||||||
customer: customer.id,
|
mode: 'subscription',
|
||||||
metadata: {
|
customer: customer.id,
|
||||||
checkoutType: 'signup'
|
metadata: {
|
||||||
|
checkoutType: 'signup'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
});
|
}
|
||||||
|
|
||||||
return subscription;
|
return subscription;
|
||||||
}
|
}
|
||||||
|
@ -266,10 +289,21 @@ class StripeMocker {
|
||||||
return [200, subscription];
|
return [200, subscription];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
remove() {
|
||||||
|
for (const interceptor of this.nockInterceptors) {
|
||||||
|
nock.removeInterceptor(interceptor);
|
||||||
|
}
|
||||||
|
this.nockInterceptors = [];
|
||||||
|
}
|
||||||
|
|
||||||
stub() {
|
stub() {
|
||||||
nock('https://api.stripe.com')
|
this.remove();
|
||||||
|
|
||||||
|
let interceptor = nock('https://api.stripe.com')
|
||||||
.persist()
|
.persist()
|
||||||
.get(/v1\/.*/)
|
.get(/v1\/.*/);
|
||||||
|
this.nockInterceptors.push(interceptor);
|
||||||
|
interceptor
|
||||||
.reply((uri) => {
|
.reply((uri) => {
|
||||||
const [match, resource, id] = uri.match(/\/?v1\/(\w+)\/?(\w+)/) || [null];
|
const [match, resource, id] = uri.match(/\/?v1\/(\w+)\/?(\w+)/) || [null];
|
||||||
|
|
||||||
|
@ -308,9 +342,11 @@ class StripeMocker {
|
||||||
return [500];
|
return [500];
|
||||||
});
|
});
|
||||||
|
|
||||||
nock('https://api.stripe.com')
|
interceptor = nock('https://api.stripe.com')
|
||||||
.persist()
|
.persist()
|
||||||
.post(/v1\/.*/)
|
.post(/v1\/.*/);
|
||||||
|
this.nockInterceptors.push(interceptor);
|
||||||
|
interceptor
|
||||||
.reply((uri, body) => {
|
.reply((uri, body) => {
|
||||||
const [match, resource, id] = uri.match(/\/?v1\/(\w+)(?:\/?(\w+)){0,2}/) || [null];
|
const [match, resource, id] = uri.match(/\/?v1\/(\w+)(?:\/?(\w+)){0,2}/) || [null];
|
||||||
|
|
||||||
|
@ -345,9 +381,11 @@ class StripeMocker {
|
||||||
return [500];
|
return [500];
|
||||||
});
|
});
|
||||||
|
|
||||||
nock('https://api.stripe.com')
|
interceptor = nock('https://api.stripe.com')
|
||||||
.persist()
|
.persist()
|
||||||
.delete(/v1\/.*/)
|
.delete(/v1\/.*/);
|
||||||
|
this.nockInterceptors.push(interceptor);
|
||||||
|
interceptor
|
||||||
.reply((uri) => {
|
.reply((uri) => {
|
||||||
const [match, resource, id] = uri.match(/\/?v1\/(\w+)(?:\/?(\w+)){0,2}/) || [null];
|
const [match, resource, id] = uri.match(/\/?v1\/(\w+)(?:\/?(\w+)){0,2}/) || [null];
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue