import { describe, expect, it } from 'vitest'; import { calcBenefitAmount, calcRedeemSettleAmount, validateMinPurchase, validateRedeemAmount, allocateBenefitCoupons, calcBenefitSummary, orderTabToStatuses, } from './index'; describe('calcBenefitAmount', () => { it('uses benefitAmount when set', () => { expect(calcBenefitAmount({ price: 599, benefitAmount: 200 })).toBe(200); }); it('falls back to price', () => { expect(calcBenefitAmount({ price: 599 })).toBe(599); }); }); describe('validateMinPurchase', () => { it('local requires 2 bottles', () => { expect(validateMinPurchase('LOCAL', 1, 2, 6).ok).toBe(false); expect(validateMinPurchase('LOCAL', 2, 2, 6).ok).toBe(true); }); it('cross city requires 6 bottles', () => { expect(validateMinPurchase('CROSS_CITY', 5, 2, 6).ok).toBe(false); expect(validateMinPurchase('CROSS_CITY', 6, 2, 6).ok).toBe(true); }); }); describe('validateRedeemAmount', () => { it('rejects over balance or non-positive amount', () => { expect(validateRedeemAmount(100, 50).ok).toBe(true); expect(validateRedeemAmount(100, 100).ok).toBe(true); expect(validateRedeemAmount(50, 60).ok).toBe(false); expect(validateRedeemAmount(100, 0).ok).toBe(false); }); it('allows direct redeem up to total balance without a document cap', () => { expect(validateRedeemAmount(700, 650).ok).toBe(true); expect(validateRedeemAmount(700, 701).ok).toBe(false); }); it('caps document-based redeem by document amount', () => { expect(validateRedeemAmount(700, 300, 300).ok).toBe(true); expect(validateRedeemAmount(700, 301, 300)).toEqual({ ok: false, message: '核销金额不能超过该核销单可用金额', }); }); }); describe('calcRedeemSettleAmount', () => { it('applies settlement rate', () => { expect(calcRedeemSettleAmount(100, 0.6)).toBe(60); }); }); describe('allocateBenefitCoupons', () => { const coupons = [ { id: '1', balance: 300, createdAt: 1 }, { id: '2', balance: 400, createdAt: 2 }, ]; it('allocates FIFO across coupons', () => { const result = allocateBenefitCoupons(coupons, 500); expect(result.ok).toBe(true); if (result.ok) { expect(result.allocations).toEqual([ { couponId: '1', amount: 300 }, { couponId: '2', amount: 200 }, ]); } }); it('rejects when total balance insufficient', () => { expect(allocateBenefitCoupons(coupons, 800).ok).toBe(false); }); it('rejects when a document cap is lower than requested amount', () => { expect(allocateBenefitCoupons(coupons, 301, 300)).toEqual({ ok: false, message: '核销金额不能超过该核销单可用金额', }); }); }); describe('orderTabToStatuses', () => { it('maps V3.0 three user tabs', () => { expect(orderTabToStatuses('pending_pay')).toEqual(['PENDING_PAY']); expect(orderTabToStatuses('paid')).toEqual([ 'PENDING_SHIP', 'OUT_WAREHOUSE', 'SHIPPING', 'PENDING_RECEIVE', ]); expect(orderTabToStatuses('completed')).toEqual(['COMPLETED']); }); it('keeps legacy tab keys mapped to paid', () => { expect(orderTabToStatuses('pending_ship')).toEqual(orderTabToStatuses('paid')); expect(orderTabToStatuses('pending_receive')).toEqual(orderTabToStatuses('paid')); }); }); describe('calcBenefitSummary', () => { it('max redeem equals total balance', () => { expect(calcBenefitSummary([300, 400])).toEqual({ totalBalance: 700, maxRedeemAmount: 700, activeCouponCount: 2, }); expect(calcBenefitSummary([100])).toEqual({ totalBalance: 100, maxRedeemAmount: 100, activeCouponCount: 1, }); }); });