Files
dukang/packages/domain/src/index.test.ts
T
2026-07-04 20:36:26 +08:00

104 lines
3.0 KiB
TypeScript

import { describe, expect, it } from 'vitest';
import {
calcBenefitAmount,
calcRedeemSettleAmount,
validateMinPurchase,
validateRedeemAmount,
allocateBenefitCoupons,
calcBenefitSummary,
} 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('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,
});
});
});