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 = { STRIPE_SECRET_KEY: 'sk_test_fake123', STRIPE_WEBHOOK_SECRET: 'whsec_test123', }; return config[key]; }), }, }, ], }).compile(); service = module.get(StripeService); configService = module.get(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' }); }); }); });