Ghost/ghost/core/test/e2e-api/admin/stats.test.js
Simon Backx 80cec29144
Added Stripe Mocker to make testing easier (#16396)
no issue

The Stripe Mocker mocks the Stripe API in memory, to make it much easier
to test subscription flows. Currently it is more a POC to see if it
works well. It probably needs a bit more work to support more scenarios.
- Added new tests for the subscription stats endpoint for 3D secure +
free trial flows using the new Stripe Mocker
- Updated members admin api tests to use Stripe Mocker (+ added new test
for deleting members with Stripe cancellation)
- Some tests called mockStripe at the beginning, but that method did
nothing apart from disabling network (which is the default now), then
they mocked Stripe inside the tests file... so I've removed those
because those conflict with the new mocker that is enabled when calling
mockStripe. We'll need to port those over later.
2023-03-10 18:43:35 +01:00

231 lines
7.7 KiB
JavaScript

const {agentProvider, fixtureManager, matchers, mockManager} = require('../../utils/e2e-framework');
const {mockStripe, stripeMocker} = require('../../utils/e2e-framework-mock-manager');
const {anyContentVersion, anyEtag, anyISODate, anyObjectId} = matchers;
const assert = require('assert');
let agent;
const matchSubscriptionStats = {
stats: [{
date: anyISODate,
tier: anyObjectId
}, {
date: anyISODate,
tier: anyObjectId
}],
meta: {
tiers: [anyObjectId],
totals: [{
tier: anyObjectId
}]
}
};
describe('Stats API', function () {
before(async function () {
agent = await agentProvider.getAdminAPIAgent();
await fixtureManager.init('posts', 'members');
await agent.loginAsOwner();
});
beforeEach(async function () {
mockStripe();
});
afterEach(async function () {
await mockManager.restore();
});
it('Can fetch member count history', async function () {
await agent
.get(`/stats/member_count`)
.expectStatus(200)
.matchBodySnapshot({
stats: [{
date: anyISODate
}]
})
.matchHeaderSnapshot({
'content-version': anyContentVersion,
etag: anyEtag
});
});
it('Can fetch MRR history', async function () {
await agent
.get(`/stats/mrr`)
.expectStatus(200)
.matchBodySnapshot({
stats: [{
date: anyISODate
}, {
date: anyISODate
}]
})
.matchHeaderSnapshot({
'content-version': anyContentVersion,
etag: anyEtag
});
});
describe('Subscriptions history', function () {
it('Can fetch subscriptions history', async function () {
await agent
.get(`/stats/subscriptions`)
.expectStatus(200)
.matchBodySnapshot(matchSubscriptionStats)
.matchHeaderSnapshot({
'content-version': anyContentVersion,
etag: anyEtag
});
});
it('Can fetch history for free trials', async function () {
// Get stats before tests
const {body: before} = await agent
.get(`/stats/subscriptions`)
.expectStatus(200);
const customer = stripeMocker.createCustomer();
const price = await stripeMocker.getPriceForTier('default-product', 'month');
const subscription = await stripeMocker.createTrialSubscription({
customer,
price
});
// Check the stats have not changed
await agent
.get(`/stats/subscriptions`)
.expectStatus(200)
.matchBodySnapshot(matchSubscriptionStats)
.matchHeaderSnapshot({
'content-version': anyContentVersion,
etag: anyEtag
})
.expect(({body}) => {
assert.deepStrictEqual(body, before, 'A free trial should not be counted as a paid subscriber');
});
// Activate the subscription
await stripeMocker.updateSubscription({
id: subscription.id,
status: 'active',
trial_end_at: null
});
// Check the stats have changed
await agent
.get(`/stats/subscriptions`)
.expectStatus(200)
.matchBodySnapshot(matchSubscriptionStats)
.matchHeaderSnapshot({
'content-version': anyContentVersion,
etag: anyEtag
})
.expect(({body}) => {
assert.notDeepStrictEqual(body, before, 'The stats should change after a free trial is activated');
});
});
it('Can fetch history for 3D secure payments', async function () {
// Get stats before tests
const {body: before} = await agent
.get(`/stats/subscriptions`)
.expectStatus(200);
const customer = stripeMocker.createCustomer();
const price = await stripeMocker.getPriceForTier('default-product', 'month');
const subscription = await stripeMocker.createIncompleteSubscription({
customer,
price
});
// Check the stats have not changed
await agent
.get(`/stats/subscriptions`)
.expectStatus(200)
.matchBodySnapshot(matchSubscriptionStats)
.matchHeaderSnapshot({
'content-version': anyContentVersion,
etag: anyEtag
})
.expect(({body}) => {
assert.deepStrictEqual(body, before, 'An incomplete subscription should not be counted as a paid subscriber');
});
// Activate the subscription
await stripeMocker.updateSubscription({
id: subscription.id,
status: 'active'
});
// Check the stats have changed
await agent
.get(`/stats/subscriptions`)
.expectStatus(200)
.matchBodySnapshot(matchSubscriptionStats)
.matchHeaderSnapshot({
'content-version': anyContentVersion,
etag: anyEtag
})
.expect(({body}) => {
assert.notDeepStrictEqual(body, before, 'The stats should change after an incomplete subscription is activated');
});
});
});
describe('Post attribution stats', function () {
it('Can fetch attribution stats', async function () {
await agent
.get(`/stats/referrers/posts/${fixtureManager.get('posts', 1).id}/`)
.expectStatus(200)
.matchBodySnapshot({
stats: [
{
source: 'Direct',
signups: 2,
paid_conversions: 1
},
{
source: 'Twitter',
signups: 1,
paid_conversions: 0
}
],
meta: {}
});
});
});
describe('Referrer source history stats', function () {
it('Can fetch attribution stats', async function () {
await agent
.get(`/stats/referrers/`)
.expectStatus(200)
.matchBodySnapshot({
stats: [
{
date: anyISODate,
source: null,
signups: 2,
paid_conversions: 2
},
{
date: anyISODate,
source: 'Direct',
signups: 4,
paid_conversions: 1
},
{
date: anyISODate,
source: 'Twitter',
signups: 4,
paid_conversions: 2
}
],
meta: {}
});
});
});
});