import { Balance } from './balance.vo'; import { Money } from './money.vo'; jest.mock('@/shared/exceptions/domain.exception', () => ({ DomainError: class DomainError extends Error { constructor(message: string) { super(message); this.name = 'DomainError'; } }, })); describe('Balance Value Object', () => { describe('create', () => { it('should create balance with available and frozen amounts', () => { const balance = Balance.create(Money.USDT(100), Money.USDT(20)); expect(balance.available.value).toBe(100); expect(balance.frozen.value).toBe(20); }); it('should create zero balance', () => { const balance = Balance.zero('USDT'); expect(balance.available.isZero()).toBe(true); expect(balance.frozen.isZero()).toBe(true); }); it('should throw error when currencies mismatch', () => { expect(() => Balance.create(Money.USDT(100), Money.BNB(20))).toThrow('same currency'); }); }); describe('total', () => { it('should calculate total correctly', () => { const balance = Balance.create(Money.USDT(100), Money.USDT(50)); expect(balance.total.value).toBe(150); }); }); describe('add', () => { it('should add to available balance', () => { const balance = Balance.create(Money.USDT(100), Money.USDT(20)); const newBalance = balance.add(Money.USDT(50)); expect(newBalance.available.value).toBe(150); expect(newBalance.frozen.value).toBe(20); }); }); describe('deduct', () => { it('should deduct from available balance', () => { const balance = Balance.create(Money.USDT(100), Money.USDT(20)); const newBalance = balance.deduct(Money.USDT(30)); expect(newBalance.available.value).toBe(70); }); it('should throw error when insufficient balance', () => { const balance = Balance.create(Money.USDT(50), Money.USDT(0)); expect(() => balance.deduct(Money.USDT(100))).toThrow('Insufficient'); }); }); describe('freeze', () => { it('should move from available to frozen', () => { const balance = Balance.create(Money.USDT(100), Money.USDT(20)); const newBalance = balance.freeze(Money.USDT(30)); expect(newBalance.available.value).toBe(70); expect(newBalance.frozen.value).toBe(50); }); it('should throw error when insufficient available balance to freeze', () => { const balance = Balance.create(Money.USDT(20), Money.USDT(0)); expect(() => balance.freeze(Money.USDT(50))).toThrow('Insufficient'); }); }); describe('unfreeze', () => { it('should move from frozen to available', () => { const balance = Balance.create(Money.USDT(100), Money.USDT(50)); const newBalance = balance.unfreeze(Money.USDT(30)); expect(newBalance.available.value).toBe(130); expect(newBalance.frozen.value).toBe(20); }); it('should throw error when insufficient frozen balance', () => { const balance = Balance.create(Money.USDT(100), Money.USDT(20)); expect(() => balance.unfreeze(Money.USDT(50))).toThrow('Insufficient'); }); }); });