xpeditis2.0/apps/backend/src/domain/entities/subscription.entity.spec.ts
David 72141c5f68
Some checks failed
CD Preprod / Backend — Lint (push) Successful in 10m27s
CD Preprod / Frontend — Lint & Type-check (push) Successful in 10m55s
CD Preprod / Backend — Unit Tests (push) Successful in 10m10s
CD Preprod / Frontend — Unit Tests (push) Successful in 10m33s
CD Preprod / Backend — Integration Tests (push) Successful in 10m6s
CD Preprod / Build Backend (push) Successful in 16m5s
CD Preprod / Build Frontend (push) Successful in 35m0s
CD Preprod / Deploy to Preprod (push) Failing after 1s
CD Preprod / Smoke Tests (push) Has been skipped
CD Preprod / Notify Success (push) Has been skipped
CD Preprod / Notify Failure (push) Has been skipped
fix preprod
2026-04-04 17:58:36 +02:00

405 lines
13 KiB
TypeScript

/**
* Subscription Entity Tests
*
* Unit tests for the Subscription domain entity
*/
import { Subscription } from './subscription.entity';
import { SubscriptionPlan } from '../value-objects/subscription-plan.vo';
import { SubscriptionStatus } from '../value-objects/subscription-status.vo';
import {
InvalidSubscriptionDowngradeException,
SubscriptionNotActiveException,
} from '../exceptions/subscription.exceptions';
describe('Subscription Entity', () => {
const createValidSubscription = () => {
return Subscription.create({
id: 'sub-123',
organizationId: 'org-123',
});
};
describe('create', () => {
it('should create a subscription with default BRONZE plan', () => {
const subscription = createValidSubscription();
expect(subscription.id).toBe('sub-123');
expect(subscription.organizationId).toBe('org-123');
expect(subscription.plan.value).toBe('BRONZE');
expect(subscription.status.value).toBe('ACTIVE');
expect(subscription.cancelAtPeriodEnd).toBe(false);
});
it('should create a subscription with custom plan', () => {
const subscription = Subscription.create({
id: 'sub-123',
organizationId: 'org-123',
plan: SubscriptionPlan.silver(),
});
expect(subscription.plan.value).toBe('SILVER');
});
it('should create a subscription with Stripe IDs', () => {
const subscription = Subscription.create({
id: 'sub-123',
organizationId: 'org-123',
stripeCustomerId: 'cus_123',
stripeSubscriptionId: 'sub_stripe_123',
});
expect(subscription.stripeCustomerId).toBe('cus_123');
expect(subscription.stripeSubscriptionId).toBe('sub_stripe_123');
});
});
describe('fromPersistence', () => {
it('should reconstitute a subscription from persistence data', () => {
const subscription = Subscription.fromPersistence({
id: 'sub-123',
organizationId: 'org-123',
plan: 'GOLD',
status: 'ACTIVE',
stripeCustomerId: 'cus_123',
stripeSubscriptionId: 'sub_stripe_123',
currentPeriodStart: new Date('2024-01-01'),
currentPeriodEnd: new Date('2024-02-01'),
cancelAtPeriodEnd: true,
createdAt: new Date('2024-01-01'),
updatedAt: new Date('2024-01-15'),
});
expect(subscription.id).toBe('sub-123');
expect(subscription.plan.value).toBe('GOLD');
expect(subscription.status.value).toBe('ACTIVE');
expect(subscription.cancelAtPeriodEnd).toBe(true);
});
});
describe('maxLicenses', () => {
it('should return correct limits for BRONZE plan', () => {
const subscription = createValidSubscription();
expect(subscription.maxLicenses).toBe(1);
});
it('should return correct limits for SILVER plan', () => {
const subscription = Subscription.create({
id: 'sub-123',
organizationId: 'org-123',
plan: SubscriptionPlan.silver(),
});
expect(subscription.maxLicenses).toBe(5);
});
it('should return correct limits for GOLD plan', () => {
const subscription = Subscription.create({
id: 'sub-123',
organizationId: 'org-123',
plan: SubscriptionPlan.gold(),
});
expect(subscription.maxLicenses).toBe(20);
});
it('should return -1 for PLATINIUM plan (unlimited)', () => {
const subscription = Subscription.create({
id: 'sub-123',
organizationId: 'org-123',
plan: SubscriptionPlan.platinium(),
});
expect(subscription.maxLicenses).toBe(-1);
});
});
describe('isUnlimited', () => {
it('should return false for BRONZE plan', () => {
const subscription = createValidSubscription();
expect(subscription.isUnlimited()).toBe(false);
});
it('should return true for PLATINIUM plan', () => {
const subscription = Subscription.create({
id: 'sub-123',
organizationId: 'org-123',
plan: SubscriptionPlan.platinium(),
});
expect(subscription.isUnlimited()).toBe(true);
});
});
describe('isActive', () => {
it('should return true for ACTIVE status', () => {
const subscription = createValidSubscription();
expect(subscription.isActive()).toBe(true);
});
it('should return true for TRIALING status', () => {
const subscription = Subscription.fromPersistence({
id: 'sub-123',
organizationId: 'org-123',
plan: 'BRONZE',
status: 'TRIALING',
stripeCustomerId: null,
stripeSubscriptionId: null,
currentPeriodStart: null,
currentPeriodEnd: null,
cancelAtPeriodEnd: false,
createdAt: new Date(),
updatedAt: new Date(),
});
expect(subscription.isActive()).toBe(true);
});
it('should return false for CANCELED status', () => {
const subscription = Subscription.fromPersistence({
id: 'sub-123',
organizationId: 'org-123',
plan: 'BRONZE',
status: 'CANCELED',
stripeCustomerId: null,
stripeSubscriptionId: null,
currentPeriodStart: null,
currentPeriodEnd: null,
cancelAtPeriodEnd: false,
createdAt: new Date(),
updatedAt: new Date(),
});
expect(subscription.isActive()).toBe(false);
});
});
describe('canAllocateLicenses', () => {
it('should return true when licenses are available', () => {
const subscription = createValidSubscription(); // BRONZE = 1 license
expect(subscription.canAllocateLicenses(0, 1)).toBe(true);
});
it('should return false when no licenses available', () => {
const subscription = createValidSubscription();
expect(subscription.canAllocateLicenses(1, 1)).toBe(false); // BRONZE has 1 license max
});
it('should always return true for PLATINIUM plan', () => {
const subscription = Subscription.create({
id: 'sub-123',
organizationId: 'org-123',
plan: SubscriptionPlan.platinium(),
});
expect(subscription.canAllocateLicenses(1000, 100)).toBe(true);
});
it('should return false when subscription is not active', () => {
const subscription = Subscription.fromPersistence({
id: 'sub-123',
organizationId: 'org-123',
plan: 'BRONZE',
status: 'CANCELED',
stripeCustomerId: null,
stripeSubscriptionId: null,
currentPeriodStart: null,
currentPeriodEnd: null,
cancelAtPeriodEnd: false,
createdAt: new Date(),
updatedAt: new Date(),
});
expect(subscription.canAllocateLicenses(0, 1)).toBe(false);
});
});
describe('canUpgradeTo', () => {
it('should allow upgrade from BRONZE to SILVER', () => {
const subscription = createValidSubscription();
expect(subscription.canUpgradeTo(SubscriptionPlan.silver())).toBe(true);
});
it('should allow upgrade from BRONZE to GOLD', () => {
const subscription = createValidSubscription();
expect(subscription.canUpgradeTo(SubscriptionPlan.gold())).toBe(true);
});
it('should not allow downgrade via canUpgradeTo', () => {
const subscription = Subscription.create({
id: 'sub-123',
organizationId: 'org-123',
plan: SubscriptionPlan.silver(),
});
expect(subscription.canUpgradeTo(SubscriptionPlan.bronze())).toBe(false);
});
});
describe('canDowngradeTo', () => {
it('should allow downgrade when user count fits', () => {
const subscription = Subscription.create({
id: 'sub-123',
organizationId: 'org-123',
plan: SubscriptionPlan.silver(),
});
expect(subscription.canDowngradeTo(SubscriptionPlan.bronze(), 1)).toBe(true);
});
it('should prevent downgrade when user count exceeds new plan', () => {
const subscription = Subscription.create({
id: 'sub-123',
organizationId: 'org-123',
plan: SubscriptionPlan.silver(),
});
expect(subscription.canDowngradeTo(SubscriptionPlan.bronze(), 5)).toBe(false);
});
});
describe('updatePlan', () => {
it('should update to new plan when valid', () => {
const subscription = createValidSubscription();
const updated = subscription.updatePlan(SubscriptionPlan.silver(), 1);
expect(updated.plan.value).toBe('SILVER');
});
it('should throw when subscription is not active', () => {
const subscription = Subscription.fromPersistence({
id: 'sub-123',
organizationId: 'org-123',
plan: 'BRONZE',
status: 'CANCELED',
stripeCustomerId: null,
stripeSubscriptionId: null,
currentPeriodStart: null,
currentPeriodEnd: null,
cancelAtPeriodEnd: false,
createdAt: new Date(),
updatedAt: new Date(),
});
expect(() => subscription.updatePlan(SubscriptionPlan.silver(), 0)).toThrow(
SubscriptionNotActiveException
);
});
it('should throw when downgrading with too many users', () => {
const subscription = Subscription.create({
id: 'sub-123',
organizationId: 'org-123',
plan: SubscriptionPlan.gold(),
});
expect(() => subscription.updatePlan(SubscriptionPlan.silver(), 10)).toThrow(
InvalidSubscriptionDowngradeException
);
});
});
describe('updateStatus', () => {
it('should update subscription status', () => {
const subscription = createValidSubscription();
const updated = subscription.updateStatus(SubscriptionStatus.pastDue());
expect(updated.status.value).toBe('PAST_DUE');
});
});
describe('updateStripeCustomerId', () => {
it('should update Stripe customer ID', () => {
const subscription = createValidSubscription();
const updated = subscription.updateStripeCustomerId('cus_new_123');
expect(updated.stripeCustomerId).toBe('cus_new_123');
});
});
describe('updateStripeSubscription', () => {
it('should update Stripe subscription details', () => {
const subscription = createValidSubscription();
const periodStart = new Date('2024-02-01');
const periodEnd = new Date('2024-03-01');
const updated = subscription.updateStripeSubscription({
stripeSubscriptionId: 'sub_new_123',
currentPeriodStart: periodStart,
currentPeriodEnd: periodEnd,
cancelAtPeriodEnd: true,
});
expect(updated.stripeSubscriptionId).toBe('sub_new_123');
expect(updated.currentPeriodStart).toEqual(periodStart);
expect(updated.currentPeriodEnd).toEqual(periodEnd);
expect(updated.cancelAtPeriodEnd).toBe(true);
});
});
describe('scheduleCancellation', () => {
it('should mark subscription for cancellation', () => {
const subscription = createValidSubscription();
const updated = subscription.scheduleCancellation();
expect(updated.cancelAtPeriodEnd).toBe(true);
});
});
describe('unscheduleCancellation', () => {
it('should unmark subscription for cancellation', () => {
const subscription = Subscription.fromPersistence({
id: 'sub-123',
organizationId: 'org-123',
plan: 'SILVER',
status: 'ACTIVE',
stripeCustomerId: 'cus_123',
stripeSubscriptionId: 'sub_123',
currentPeriodStart: new Date(),
currentPeriodEnd: new Date(),
cancelAtPeriodEnd: true,
createdAt: new Date(),
updatedAt: new Date(),
});
const updated = subscription.unscheduleCancellation();
expect(updated.cancelAtPeriodEnd).toBe(false);
});
});
describe('cancel', () => {
it('should cancel the subscription immediately', () => {
const subscription = createValidSubscription();
const updated = subscription.cancel();
expect(updated.status.value).toBe('CANCELED');
expect(updated.cancelAtPeriodEnd).toBe(false);
});
});
describe('isFree and isPaid', () => {
it('should return true for isFree when BRONZE plan', () => {
const subscription = createValidSubscription();
expect(subscription.isFree()).toBe(true);
expect(subscription.isPaid()).toBe(false);
});
it('should return true for isPaid when SILVER plan', () => {
const subscription = Subscription.create({
id: 'sub-123',
organizationId: 'org-123',
plan: SubscriptionPlan.silver(),
});
expect(subscription.isFree()).toBe(false);
expect(subscription.isPaid()).toBe(true);
});
});
describe('toObject', () => {
it('should convert to plain object for persistence', () => {
const subscription = Subscription.create({
id: 'sub-123',
organizationId: 'org-123',
stripeCustomerId: 'cus_123',
});
const obj = subscription.toObject();
expect(obj.id).toBe('sub-123');
expect(obj.organizationId).toBe('org-123');
expect(obj.plan).toBe('BRONZE');
expect(obj.status).toBe('ACTIVE');
expect(obj.stripeCustomerId).toBe('cus_123');
});
});
});