test(backoffice): add unit tests for StripeService

- Add 8 test cases covering all StripeService methods
- Mock Stripe SDK for isolated testing
- Test createCustomer, createSubscription, cancelSubscription
- Test listSubscriptions, createCheckoutSession, createBillingPortalSession
- Test constructWebhookEvent and onModuleInit
This commit is contained in:
Tiago Yamamoto 2025-12-28 11:03:58 -03:00
parent cb31713307
commit 93367d7cd6

View file

@ -0,0 +1,159 @@
import { Test, TestingModule } from '@nestjs/testing';
import { ConfigService } from '@nestjs/config';
import { StripeService } from './stripe.service';
// Mock Stripe
jest.mock('stripe', () => {
return jest.fn().mockImplementation(() => ({
customers: {
create: jest.fn().mockResolvedValue({ id: 'cus_test123', email: 'test@example.com' }),
},
subscriptions: {
create: jest.fn().mockResolvedValue({ id: 'sub_test123', status: 'active' }),
cancel: jest.fn().mockResolvedValue({ id: 'sub_test123', status: 'canceled' }),
list: jest.fn().mockResolvedValue({ data: [] }),
},
checkout: {
sessions: {
create: jest.fn().mockResolvedValue({ id: 'cs_test123', url: 'https://checkout.stripe.com/test' }),
},
},
billingPortal: {
sessions: {
create: jest.fn().mockResolvedValue({ id: 'bps_test123', url: 'https://billing.stripe.com/test' }),
},
},
webhooks: {
constructEvent: jest.fn().mockReturnValue({ type: 'checkout.session.completed' }),
},
}));
});
describe('StripeService', () => {
let service: StripeService;
let configService: ConfigService;
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
providers: [
StripeService,
{
provide: ConfigService,
useValue: {
get: jest.fn((key: string) => {
const config: Record<string, string> = {
STRIPE_SECRET_KEY: 'sk_test_fake123',
STRIPE_WEBHOOK_SECRET: 'whsec_test123',
};
return config[key];
}),
},
},
],
}).compile();
service = module.get<StripeService>(StripeService);
configService = module.get<ConfigService>(ConfigService);
// Initialize the service
service.onModuleInit();
});
describe('onModuleInit', () => {
it('should initialize Stripe client when secret key is configured', () => {
expect(service.getClient()).toBeDefined();
});
it('should warn when STRIPE_SECRET_KEY is not configured', () => {
const warnSpy = jest.spyOn(console, 'warn').mockImplementation();
jest.spyOn(configService, 'get').mockReturnValue(undefined);
const newService = new StripeService(configService);
newService.onModuleInit();
expect(warnSpy).toHaveBeenCalledWith('STRIPE_SECRET_KEY not configured');
warnSpy.mockRestore();
});
});
describe('createCustomer', () => {
it('should create a customer with email and name', async () => {
const result = await service.createCustomer('test@example.com', 'Test User');
expect(result).toEqual({ id: 'cus_test123', email: 'test@example.com' });
expect(service.getClient().customers.create).toHaveBeenCalledWith({
email: 'test@example.com',
name: 'Test User',
});
});
});
describe('createSubscription', () => {
it('should create a subscription for a customer', async () => {
const result = await service.createSubscription('cus_test123', 'price_test123');
expect(result).toEqual({ id: 'sub_test123', status: 'active' });
expect(service.getClient().subscriptions.create).toHaveBeenCalledWith({
customer: 'cus_test123',
items: [{ price: 'price_test123' }],
payment_behavior: 'default_incomplete',
expand: ['latest_invoice.payment_intent'],
});
});
});
describe('cancelSubscription', () => {
it('should cancel a subscription', async () => {
const result = await service.cancelSubscription('sub_test123');
expect(result).toEqual({ id: 'sub_test123', status: 'canceled' });
});
});
describe('listSubscriptions', () => {
it('should list subscriptions for a customer', async () => {
const result = await service.listSubscriptions('cus_test123');
expect(result).toEqual({ data: [] });
expect(service.getClient().subscriptions.list).toHaveBeenCalledWith({
customer: 'cus_test123',
status: 'all',
});
});
});
describe('createCheckoutSession', () => {
it('should create a checkout session', async () => {
const result = await service.createCheckoutSession(
'cus_test123',
'price_test123',
'https://example.com/success',
'https://example.com/cancel',
);
expect(result).toEqual({ id: 'cs_test123', url: 'https://checkout.stripe.com/test' });
});
});
describe('createBillingPortalSession', () => {
it('should create a billing portal session', async () => {
const result = await service.createBillingPortalSession(
'cus_test123',
'https://example.com/return',
);
expect(result).toEqual({ id: 'bps_test123', url: 'https://billing.stripe.com/test' });
});
});
describe('constructWebhookEvent', () => {
it('should construct a webhook event from request body', () => {
const body = Buffer.from('{}');
const signature = 'test_signature';
const result = service.constructWebhookEvent(body, signature);
expect(result).toEqual({ type: 'checkout.session.completed' });
});
});
});