Ghost/ghost/core/test/e2e-api/members/create-stripe-checkout-session.test.js

214 lines
8.0 KiB
JavaScript
Raw Normal View History

const {agentProvider, mockManager, fixtureManager, matchers} = require('../../utils/e2e-framework');
const nock = require('nock');
Added member attribution events and storage (#15243) refs https://github.com/TryGhost/Team/issues/1808 refs https://github.com/TryGhost/Team/issues/1809 refs https://github.com/TryGhost/Team/issues/1820 refs https://github.com/TryGhost/Team/issues/1814 ### Changes in `member-events` package - Added MemberCreatedEvent (event, not model) - Added SubscriptionCreatedEvent (event, not model) ### Added `member-attribution` package (new) - Added the AttributionBuilder class which is able to convert a url history to an attribution object (exposed as getAttribution on the service itself, which handles the dependencies) ``` [{ "path": "/", "time": 123 }] ``` to ``` { "url": "/", "id": null, "type": "url" } ``` - event handler listens for MemberCreatedEvent and SubscriptionCreatedEvent and creates the corresponding models in the database. ### Changes in `members-api` package - Added urlHistory to `sendMagicLink` endpoint body + convert the urlHistory to an attribution object that is stored in the tokenData of the magic link (sent by Portal in this PR: https://github.com/TryGhost/Portal/pull/256). - Added urlHistory to `createCheckoutSession` endpoint + convert the urlHistory to attribution keys that are saved in the Stripe Session metadata (sent by Portal in this PR: https://github.com/TryGhost/Portal/pull/256). - Added attribution data property to member repository's create method (when a member is created) - Dispatch MemberCreatedEvent with attribution ### Changes in `members-stripe-service` package (`ghost/stripe`) - Dispatch SubscriptionCreatedEvent in WebhookController on subscription checkout (with attribution from session metadata)
2022-08-18 18:38:42 +03:00
const should = require('should');
const models = require('../../../core/server/models');
const urlService = require('../../../core/server/services/url');
let membersAgent, adminAgent, membersService;
Added member attribution events and storage (#15243) refs https://github.com/TryGhost/Team/issues/1808 refs https://github.com/TryGhost/Team/issues/1809 refs https://github.com/TryGhost/Team/issues/1820 refs https://github.com/TryGhost/Team/issues/1814 ### Changes in `member-events` package - Added MemberCreatedEvent (event, not model) - Added SubscriptionCreatedEvent (event, not model) ### Added `member-attribution` package (new) - Added the AttributionBuilder class which is able to convert a url history to an attribution object (exposed as getAttribution on the service itself, which handles the dependencies) ``` [{ "path": "/", "time": 123 }] ``` to ``` { "url": "/", "id": null, "type": "url" } ``` - event handler listens for MemberCreatedEvent and SubscriptionCreatedEvent and creates the corresponding models in the database. ### Changes in `members-api` package - Added urlHistory to `sendMagicLink` endpoint body + convert the urlHistory to an attribution object that is stored in the tokenData of the magic link (sent by Portal in this PR: https://github.com/TryGhost/Portal/pull/256). - Added urlHistory to `createCheckoutSession` endpoint + convert the urlHistory to attribution keys that are saved in the Stripe Session metadata (sent by Portal in this PR: https://github.com/TryGhost/Portal/pull/256). - Added attribution data property to member repository's create method (when a member is created) - Dispatch MemberCreatedEvent with attribution ### Changes in `members-stripe-service` package (`ghost/stripe`) - Dispatch SubscriptionCreatedEvent in WebhookController on subscription checkout (with attribution from session metadata)
2022-08-18 18:38:42 +03:00
async function getPost(id) {
// eslint-disable-next-line dot-notation
return await models['Post'].where('id', id).fetch({require: true});
}
describe('Create Stripe Checkout Session', function () {
before(async function () {
const agents = await agentProvider.getAgentsForMembers();
membersAgent = agents.membersAgent;
adminAgent = agents.adminAgent;
membersService = require('../../../core/server/services/members');
Added member attribution events and storage (#15243) refs https://github.com/TryGhost/Team/issues/1808 refs https://github.com/TryGhost/Team/issues/1809 refs https://github.com/TryGhost/Team/issues/1820 refs https://github.com/TryGhost/Team/issues/1814 ### Changes in `member-events` package - Added MemberCreatedEvent (event, not model) - Added SubscriptionCreatedEvent (event, not model) ### Added `member-attribution` package (new) - Added the AttributionBuilder class which is able to convert a url history to an attribution object (exposed as getAttribution on the service itself, which handles the dependencies) ``` [{ "path": "/", "time": 123 }] ``` to ``` { "url": "/", "id": null, "type": "url" } ``` - event handler listens for MemberCreatedEvent and SubscriptionCreatedEvent and creates the corresponding models in the database. ### Changes in `members-api` package - Added urlHistory to `sendMagicLink` endpoint body + convert the urlHistory to an attribution object that is stored in the tokenData of the magic link (sent by Portal in this PR: https://github.com/TryGhost/Portal/pull/256). - Added urlHistory to `createCheckoutSession` endpoint + convert the urlHistory to attribution keys that are saved in the Stripe Session metadata (sent by Portal in this PR: https://github.com/TryGhost/Portal/pull/256). - Added attribution data property to member repository's create method (when a member is created) - Dispatch MemberCreatedEvent with attribution ### Changes in `members-stripe-service` package (`ghost/stripe`) - Dispatch SubscriptionCreatedEvent in WebhookController on subscription checkout (with attribution from session metadata)
2022-08-18 18:38:42 +03:00
await fixtureManager.init('posts', 'members');
await adminAgent.loginAsOwner();
});
beforeEach(function () {
mockManager.mockMail();
mockManager.mockStripe();
});
afterEach(function () {
mockManager.restore();
});
it('Does not allow to create a checkout session if the customerEmail is associated with a paid member', async function () {
const {body: {tiers}} = await adminAgent.get('/tiers/?include=monthly_price&yearly_price');
const paidTier = tiers.find(tier => tier.type === 'paid');
await membersAgent.post('/api/create-stripe-checkout-session/')
.body({
customerEmail: 'paid@test.com',
tierId: paidTier.id,
cadence: 'month'
})
.expectStatus(403)
.matchBodySnapshot({
errors: [{
id: matchers.anyUuid,
code: 'CANNOT_CHECKOUT_WITH_EXISTING_SUBSCRIPTION'
}]
})
.matchHeaderSnapshot({
etag: matchers.anyEtag
});
});
it('Does allow to create a checkout session if the customerEmail is not associated with a paid member', async function () {
const {body: {tiers}} = await adminAgent.get('/tiers/?include=monthly_price&yearly_price');
const paidTier = tiers.find(tier => tier.type === 'paid');
nock('https://api.stripe.com')
.persist()
.post(/v1\/.*/)
.reply((uri, body) => {
if (uri === '/v1/checkout/sessions') {
return [200, {id: 'cs_123'}];
}
return [500];
});
await membersAgent.post('/api/create-stripe-checkout-session/')
.body({
customerEmail: 'free@test.com',
tierId: paidTier.id,
cadence: 'month'
})
.expectStatus(200)
.matchBodySnapshot()
.matchHeaderSnapshot();
});
Added member attribution events and storage (#15243) refs https://github.com/TryGhost/Team/issues/1808 refs https://github.com/TryGhost/Team/issues/1809 refs https://github.com/TryGhost/Team/issues/1820 refs https://github.com/TryGhost/Team/issues/1814 ### Changes in `member-events` package - Added MemberCreatedEvent (event, not model) - Added SubscriptionCreatedEvent (event, not model) ### Added `member-attribution` package (new) - Added the AttributionBuilder class which is able to convert a url history to an attribution object (exposed as getAttribution on the service itself, which handles the dependencies) ``` [{ "path": "/", "time": 123 }] ``` to ``` { "url": "/", "id": null, "type": "url" } ``` - event handler listens for MemberCreatedEvent and SubscriptionCreatedEvent and creates the corresponding models in the database. ### Changes in `members-api` package - Added urlHistory to `sendMagicLink` endpoint body + convert the urlHistory to an attribution object that is stored in the tokenData of the magic link (sent by Portal in this PR: https://github.com/TryGhost/Portal/pull/256). - Added urlHistory to `createCheckoutSession` endpoint + convert the urlHistory to attribution keys that are saved in the Stripe Session metadata (sent by Portal in this PR: https://github.com/TryGhost/Portal/pull/256). - Added attribution data property to member repository's create method (when a member is created) - Dispatch MemberCreatedEvent with attribution ### Changes in `members-stripe-service` package (`ghost/stripe`) - Dispatch SubscriptionCreatedEvent in WebhookController on subscription checkout (with attribution from session metadata)
2022-08-18 18:38:42 +03:00
/**
* When a checkout session is created with an urlHistory, we should convert it to an
* attribution and check if that is set in the metadata of the stripe session
*/
describe('Member attribution', function () {
it('Does pass url attribution source to session metadata', async function () {
const {body: {tiers}} = await adminAgent.get('/tiers/?include=monthly_price&yearly_price');
const paidTier = tiers.find(tier => tier.type === 'paid');
const scope = nock('https://api.stripe.com')
.persist()
.post(/v1\/.*/)
.reply((uri, body) => {
if (uri === '/v1/checkout/sessions') {
const parsed = new URLSearchParams(body);
should(parsed.get('metadata[attribution_url]')).eql('/test');
should(parsed.get('metadata[attribution_type]')).eql('url');
should(parsed.get('metadata[attribution_id]')).be.null();
return [200, {id: 'cs_123'}];
}
throw new Error('Should not get called');
});
await membersAgent.post('/api/create-stripe-checkout-session/')
.body({
customerEmail: 'attribution@test.com',
tierId: paidTier.id,
cadence: 'month',
metadata: {
urlHistory: [
{
path: '/test',
time: Date.now()
Added member attribution events and storage (#15243) refs https://github.com/TryGhost/Team/issues/1808 refs https://github.com/TryGhost/Team/issues/1809 refs https://github.com/TryGhost/Team/issues/1820 refs https://github.com/TryGhost/Team/issues/1814 ### Changes in `member-events` package - Added MemberCreatedEvent (event, not model) - Added SubscriptionCreatedEvent (event, not model) ### Added `member-attribution` package (new) - Added the AttributionBuilder class which is able to convert a url history to an attribution object (exposed as getAttribution on the service itself, which handles the dependencies) ``` [{ "path": "/", "time": 123 }] ``` to ``` { "url": "/", "id": null, "type": "url" } ``` - event handler listens for MemberCreatedEvent and SubscriptionCreatedEvent and creates the corresponding models in the database. ### Changes in `members-api` package - Added urlHistory to `sendMagicLink` endpoint body + convert the urlHistory to an attribution object that is stored in the tokenData of the magic link (sent by Portal in this PR: https://github.com/TryGhost/Portal/pull/256). - Added urlHistory to `createCheckoutSession` endpoint + convert the urlHistory to attribution keys that are saved in the Stripe Session metadata (sent by Portal in this PR: https://github.com/TryGhost/Portal/pull/256). - Added attribution data property to member repository's create method (when a member is created) - Dispatch MemberCreatedEvent with attribution ### Changes in `members-stripe-service` package (`ghost/stripe`) - Dispatch SubscriptionCreatedEvent in WebhookController on subscription checkout (with attribution from session metadata)
2022-08-18 18:38:42 +03:00
}
]
}
})
.expectStatus(200)
.matchBodySnapshot()
.matchHeaderSnapshot();
should(scope.isDone()).eql(true);
});
it('Does pass post attribution source to session metadata', async function () {
const post = await getPost(fixtureManager.get('posts', 0).id);
const url = urlService.getUrlByResourceId(post.id, {absolute: false});
const {body: {tiers}} = await adminAgent.get('/tiers/?include=monthly_price&yearly_price');
const paidTier = tiers.find(tier => tier.type === 'paid');
const scope = nock('https://api.stripe.com')
.persist()
.post(/v1\/.*/)
.reply((uri, body) => {
if (uri === '/v1/checkout/sessions') {
const parsed = new URLSearchParams(body);
should(parsed.get('metadata[attribution_url]')).eql(url);
should(parsed.get('metadata[attribution_type]')).eql('post');
should(parsed.get('metadata[attribution_id]')).eql(post.id);
return [200, {id: 'cs_123'}];
}
throw new Error('Should not get called');
});
await membersAgent.post('/api/create-stripe-checkout-session/')
.body({
customerEmail: 'attribution-post@test.com',
tierId: paidTier.id,
cadence: 'month',
metadata: {
urlHistory: [
{
path: url,
time: Date.now()
Added member attribution events and storage (#15243) refs https://github.com/TryGhost/Team/issues/1808 refs https://github.com/TryGhost/Team/issues/1809 refs https://github.com/TryGhost/Team/issues/1820 refs https://github.com/TryGhost/Team/issues/1814 ### Changes in `member-events` package - Added MemberCreatedEvent (event, not model) - Added SubscriptionCreatedEvent (event, not model) ### Added `member-attribution` package (new) - Added the AttributionBuilder class which is able to convert a url history to an attribution object (exposed as getAttribution on the service itself, which handles the dependencies) ``` [{ "path": "/", "time": 123 }] ``` to ``` { "url": "/", "id": null, "type": "url" } ``` - event handler listens for MemberCreatedEvent and SubscriptionCreatedEvent and creates the corresponding models in the database. ### Changes in `members-api` package - Added urlHistory to `sendMagicLink` endpoint body + convert the urlHistory to an attribution object that is stored in the tokenData of the magic link (sent by Portal in this PR: https://github.com/TryGhost/Portal/pull/256). - Added urlHistory to `createCheckoutSession` endpoint + convert the urlHistory to attribution keys that are saved in the Stripe Session metadata (sent by Portal in this PR: https://github.com/TryGhost/Portal/pull/256). - Added attribution data property to member repository's create method (when a member is created) - Dispatch MemberCreatedEvent with attribution ### Changes in `members-stripe-service` package (`ghost/stripe`) - Dispatch SubscriptionCreatedEvent in WebhookController on subscription checkout (with attribution from session metadata)
2022-08-18 18:38:42 +03:00
}
]
}
})
.expectStatus(200)
.matchBodySnapshot()
.matchHeaderSnapshot();
should(scope.isDone()).eql(true);
});
it('Ignores attribution_* values in metadata', async function () {
const {body: {tiers}} = await adminAgent.get('/tiers/?include=monthly_price&yearly_price');
const paidTier = tiers.find(tier => tier.type === 'paid');
const scope = nock('https://api.stripe.com')
.persist()
.post(/v1\/.*/)
.reply((uri, body) => {
if (uri === '/v1/checkout/sessions') {
const parsed = new URLSearchParams(body);
should(parsed.get('metadata[attribution_url]')).be.null();
should(parsed.get('metadata[attribution_type]')).be.null();
should(parsed.get('metadata[attribution_id]')).be.null();
return [200, {id: 'cs_123'}];
}
throw new Error('Should not get called');
});
await membersAgent.post('/api/create-stripe-checkout-session/')
.body({
customerEmail: 'attribution-2@test.com',
tierId: paidTier.id,
cadence: 'month',
metadata: {
attribution_type: 'url',
attribution_url: '/',
attribution_id: null
}
})
.expectStatus(200)
.matchBodySnapshot()
.matchHeaderSnapshot();
should(scope.isDone()).eql(true);
});
});
});