"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const testing_1 = require("@nestjs/testing"); const typeorm_1 = require("@nestjs/typeorm"); const common_1 = require("@nestjs/common"); const plans_service_1 = require("../services/plans.service"); const plan_entity_1 = require("../entities/plan.entity"); describe('PlansService', () => { let service; let planRepo; const mockPlan = { id: '550e8400-e29b-41d4-a716-446655440001', name: 'Professional', slug: 'professional', description: 'For growing businesses', tagline: 'Best for teams', price_monthly: 79, price_yearly: 790, currency: 'USD', features: [ { name: 'Up to 50 users', value: true, highlight: false }, { name: 'Storage', value: '100 GB', highlight: true }, { name: 'API access', value: true }, ], included_features: ['Priority support', 'Custom integrations'], limits: { max_users: 50, storage_gb: 100 }, is_popular: true, is_enterprise: false, is_active: true, is_visible: true, sort_order: 2, trial_days: 14, metadata: { promotion: 'summer2026' }, created_at: new Date('2026-01-01'), updated_at: new Date('2026-01-01'), }; const mockFreePlan = { id: '550e8400-e29b-41d4-a716-446655440002', name: 'Free', slug: 'free', description: 'Perfect for getting started', tagline: null, price_monthly: 0, price_yearly: 0, currency: 'USD', features: [ { name: 'Up to 3 users', value: true }, { name: 'Basic features', value: true }, ], included_features: ['Community support'], limits: { max_users: 3, storage_gb: 1 }, is_popular: false, is_enterprise: false, is_active: true, is_visible: true, sort_order: 1, trial_days: 0, metadata: null, created_at: new Date('2026-01-01'), updated_at: new Date('2026-01-01'), }; const mockEnterprisePlan = { id: '550e8400-e29b-41d4-a716-446655440003', name: 'Enterprise', slug: 'enterprise', description: 'For large organizations', tagline: 'Custom solutions', price_monthly: null, price_yearly: null, currency: 'USD', features: [ { name: 'Unlimited users', value: true }, { name: 'SSO/SAML', value: true }, ], included_features: ['Dedicated support', 'SLA guarantee'], limits: {}, is_popular: false, is_enterprise: true, is_active: true, is_visible: true, sort_order: 4, trial_days: 30, metadata: null, created_at: new Date('2026-01-01'), updated_at: new Date('2026-01-01'), }; beforeEach(async () => { const mockPlanRepo = { find: jest.fn(), findOne: jest.fn(), }; const module = await testing_1.Test.createTestingModule({ providers: [ plans_service_1.PlansService, { provide: (0, typeorm_1.getRepositoryToken)(plan_entity_1.Plan), useValue: mockPlanRepo }, ], }).compile(); service = module.get(plans_service_1.PlansService); planRepo = module.get((0, typeorm_1.getRepositoryToken)(plan_entity_1.Plan)); }); afterEach(() => { jest.clearAllMocks(); }); describe('findAll', () => { it('should return all visible and active plans', async () => { const plans = [mockFreePlan, mockPlan, mockEnterprisePlan]; planRepo.find.mockResolvedValue(plans); const result = await service.findAll(); expect(result).toHaveLength(3); expect(planRepo.find).toHaveBeenCalledWith({ where: { is_active: true, is_visible: true, }, order: { sort_order: 'ASC', }, }); }); it('should return empty array when no plans exist', async () => { planRepo.find.mockResolvedValue([]); const result = await service.findAll(); expect(result).toHaveLength(0); expect(result).toEqual([]); }); it('should transform plan entity to response DTO correctly', async () => { planRepo.find.mockResolvedValue([mockPlan]); const result = await service.findAll(); expect(result[0]).toMatchObject({ id: mockPlan.id, name: mockPlan.name, slug: mockPlan.slug, display_name: mockPlan.name, description: mockPlan.description, tagline: mockPlan.tagline, price_monthly: 79, price_yearly: 790, currency: 'USD', is_popular: true, trial_days: 14, }); }); it('should extract features as string array', async () => { planRepo.find.mockResolvedValue([mockPlan]); const result = await service.findAll(); expect(result[0].features).toContain('Up to 50 users'); expect(result[0].features).toContain('Storage: 100 GB'); expect(result[0].features).toContain('API access'); expect(result[0].features).toContain('Priority support'); expect(result[0].features).toContain('Custom integrations'); }); it('should handle null prices correctly', async () => { planRepo.find.mockResolvedValue([mockEnterprisePlan]); const result = await service.findAll(); expect(result[0].price_monthly).toBe(0); expect(result[0].price_yearly).toBe(0); }); it('should include limits in response', async () => { planRepo.find.mockResolvedValue([mockPlan]); const result = await service.findAll(); expect(result[0].limits).toEqual({ max_users: 50, storage_gb: 100 }); }); }); describe('findOne', () => { it('should return plan by ID', async () => { planRepo.findOne.mockResolvedValue(mockPlan); const result = await service.findOne(mockPlan.id); expect(result).toBeDefined(); expect(result.id).toBe(mockPlan.id); expect(planRepo.findOne).toHaveBeenCalledWith({ where: { id: mockPlan.id }, }); }); it('should throw NotFoundException when plan not found', async () => { planRepo.findOne.mockResolvedValue(null); await expect(service.findOne('non-existent-id')).rejects.toThrow(common_1.NotFoundException); await expect(service.findOne('non-existent-id')).rejects.toThrow('Plan with ID "non-existent-id" not found'); }); it('should return detailed DTO with additional fields', async () => { planRepo.findOne.mockResolvedValue(mockPlan); const result = await service.findOne(mockPlan.id); expect(result.is_enterprise).toBeUndefined(); expect(result.detailed_features).toEqual(mockPlan.features); expect(result.metadata).toEqual({ promotion: 'summer2026' }); }); it('should include is_enterprise flag for enterprise plans', async () => { planRepo.findOne.mockResolvedValue(mockEnterprisePlan); const result = await service.findOne(mockEnterprisePlan.id); expect(result.is_enterprise).toBe(true); }); }); describe('findBySlug', () => { it('should return plan by slug', async () => { planRepo.findOne.mockResolvedValue(mockPlan); const result = await service.findBySlug('professional'); expect(result).toBeDefined(); expect(result.slug).toBe('professional'); expect(planRepo.findOne).toHaveBeenCalledWith({ where: { slug: 'professional' }, }); }); it('should throw NotFoundException when plan not found by slug', async () => { planRepo.findOne.mockResolvedValue(null); await expect(service.findBySlug('non-existent')).rejects.toThrow(common_1.NotFoundException); await expect(service.findBySlug('non-existent')).rejects.toThrow('Plan with slug "non-existent" not found'); }); }); describe('feature extraction', () => { it('should handle empty features array', async () => { const planWithNoFeatures = { ...mockPlan, features: [], included_features: [], }; planRepo.find.mockResolvedValue([planWithNoFeatures]); const result = await service.findAll(); expect(result[0].features).toEqual([]); }); it('should handle boolean feature values', async () => { const planWithBooleanFeatures = { ...mockPlan, features: [ { name: 'Feature enabled', value: true }, { name: 'Feature disabled', value: false }, ], included_features: [], }; planRepo.find.mockResolvedValue([planWithBooleanFeatures]); const result = await service.findAll(); expect(result[0].features).toContain('Feature enabled'); expect(result[0].features).not.toContain('Feature disabled'); }); it('should handle string feature values', async () => { const planWithStringFeatures = { ...mockPlan, features: [{ name: 'Storage', value: '500 GB' }], included_features: [], }; planRepo.find.mockResolvedValue([planWithStringFeatures]); const result = await service.findAll(); expect(result[0].features).toContain('Storage: 500 GB'); }); it('should handle null tagline', async () => { planRepo.find.mockResolvedValue([mockFreePlan]); const result = await service.findAll(); expect(result[0].tagline).toBeUndefined(); }); }); }); //# sourceMappingURL=plans.service.spec.js.map