Ghost/ghost/members-api/test/unit/lib/services/stripe-webhook.test.js
Rishabh Garg dec16bd27c 🐛 Fixed 500 webhook errors for subscription with multiple prices (#350)
closes https://github.com/TryGhost/Team/issues/1238

- previously returned 500 errors when a subscription had multiple prices due to external tampering on Stripe directly
- instead now returns 400 Bad Request error when subscriptions don't have right number of prices
2021-12-01 20:09:55 +05:30

119 lines
4.1 KiB
JavaScript

const {describe, it} = require('mocha');
const should = require('should');
const sinon = require('sinon');
const StripeAPIService = require('@tryghost/members-stripe-service');
const StripeWebhookService = require('../../../../lib/services/stripe-webhook');
const ProductRepository = require('../../../../lib/repositories/product');
const MemberRepository = require('../../../../lib/repositories/member');
function mock(Class) {
return sinon.stub(Object.create(Class.prototype));
}
describe('StripeWebhookService', function () {
describe('invoice.payment_succeeded webhooks', function () {
it('Should throw a 404 error when a member is not found for a valid Ghost Members invoice', async function () {
const stripeWebhookService = new StripeWebhookService({
stripeAPIService: mock(StripeAPIService),
productRepository: mock(ProductRepository),
memberRepository: mock(MemberRepository)
});
stripeWebhookService._stripeAPIService.getSubscription.resolves({
customer: 'customer_id',
plan: {
product: 'product_id'
}
});
stripeWebhookService._memberRepository.get.resolves(null);
stripeWebhookService._productRepository.get.resolves({
id: 'product_id'
});
try {
await stripeWebhookService.invoiceEvent({
subscription: 'sub_id'
});
should.fail();
} catch (err) {
should.equal(err.statusCode, 404);
}
});
});
describe('customer.subscription.updated webhooks', function () {
it('Should throw a 400 error when a subscription has multiple prices', async function () {
const stripeWebhookService = new StripeWebhookService({
stripeAPIService: mock(StripeAPIService),
productRepository: mock(ProductRepository),
memberRepository: mock(MemberRepository)
});
stripeWebhookService._stripeAPIService.getSubscription.resolves({
customer: 'customer_id',
plan: {
product: 'product_id'
}
});
stripeWebhookService._memberRepository.get.resolves(null);
stripeWebhookService._productRepository.get.resolves({
id: 'product_id'
});
try {
await stripeWebhookService.subscriptionEvent({
items: {
data: [
{
id: 'si_1',
price: {}
},
{
id: 'si_2',
price: {}
}
]
}
});
should.fail();
} catch (err) {
should.equal(err.statusCode, 400);
}
});
it('Should throw a 400 error when a subscription has 0 prices', async function () {
const stripeWebhookService = new StripeWebhookService({
stripeAPIService: mock(StripeAPIService),
productRepository: mock(ProductRepository),
memberRepository: mock(MemberRepository)
});
stripeWebhookService._stripeAPIService.getSubscription.resolves({
customer: 'customer_id',
plan: {
product: 'product_id'
}
});
stripeWebhookService._memberRepository.get.resolves(null);
stripeWebhookService._productRepository.get.resolves({
id: 'product_id'
});
try {
await stripeWebhookService.subscriptionEvent({
items: {
data: []
}
});
should.fail();
} catch (err) {
should.equal(err.statusCode, 400);
}
});
});
});