import { ForbiddenException } from '@nestjs/common'; import { ApiKey } from '@domain/entities/api-key.entity'; import { Subscription } from '@domain/entities/subscription.entity'; import { SubscriptionPlan } from '@domain/value-objects/subscription-plan.vo'; import { SubscriptionStatus, SubscriptionStatusType, } from '@domain/value-objects/subscription-status.vo'; import { ApiKeyRepository } from '@domain/ports/out/api-key.repository'; import { UserRepository } from '@domain/ports/out/user.repository'; import { SubscriptionRepository } from '@domain/ports/out/subscription.repository'; import { ApiKeysService } from './api-keys.service'; describe('API key current entitlement', () => { const setup = () => { let subscription = Subscription.create({ id: 'sub', organizationId: 'org', plan: SubscriptionPlan.gold(), }); const key = ApiKey.create({ id: 'key', userId: 'user', organizationId: 'org', name: 'test', keyHash: 'hash', keyPrefix: 'xped_live_test', }); const keys = { findByKeyHash: jest.fn().mockResolvedValue(key), save: jest.fn().mockImplementation(async value => value), }; const users = { findById: jest .fn() .mockResolvedValue({ id: 'user', organizationId: 'org', isActive: true, role: 'MANAGER' }), }; const subscriptions = { findByOrganizationId: jest.fn().mockImplementation(async () => subscription), }; return { service: new ApiKeysService( keys as unknown as ApiKeyRepository, users as unknown as UserRepository, subscriptions as unknown as SubscriptionRepository ), keys, setStatus: (status: SubscriptionStatusType) => { subscription = subscription.updateStatus(SubscriptionStatus.create(status)); }, }; }; it.each([ 'UNPAID', 'PAUSED', 'INCOMPLETE', 'INCOMPLETE_EXPIRED', 'CANCELED', ])('%s invalidates an existing key and forbids creation', async status => { const { service, keys, setStatus } = setup(); await expect(service.validateAndGetUser('xped_live_test')).resolves.toMatchObject({ plan: 'GOLD', }); keys.save.mockClear(); setStatus(status); await expect(service.validateAndGetUser('xped_live_test')).resolves.toBeNull(); await expect(service.generateApiKey('user', 'org', { name: 'new' })).rejects.toBeInstanceOf( ForbiddenException ); expect(keys.save).not.toHaveBeenCalled(); }); it.each(['ACTIVE', 'TRIALING', 'PAST_DUE'])( '%s permits keys', async status => { const { service, setStatus } = setup(); setStatus(status); await expect(service.validateAndGetUser('xped_live_test')).resolves.toMatchObject({ plan: 'GOLD', }); await expect(service.generateApiKey('user', 'org', { name: 'new' })).resolves.toMatchObject({ name: 'new', isActive: true, }); } ); });