refactor: 收口个人资金展示模型
This commit is contained in:
@@ -0,0 +1,161 @@
|
||||
import { expect, test } from 'vitest';
|
||||
|
||||
import type {
|
||||
ProfileMembership,
|
||||
ProfileRechargeProduct,
|
||||
ProfileWalletLedgerEntry,
|
||||
} from '../../../packages/shared/src/contracts/runtime';
|
||||
import {
|
||||
buildMembershipLabel,
|
||||
buildRechargeProductValueLabel,
|
||||
buildWalletLedgerPresentation,
|
||||
formatRechargePrice,
|
||||
formatWalletLedgerAmount,
|
||||
getWalletLedgerSourceLabel,
|
||||
} from './rpgEntryProfileFundsViewModel';
|
||||
|
||||
function buildLedgerEntry(
|
||||
overrides: Partial<ProfileWalletLedgerEntry> = {},
|
||||
): ProfileWalletLedgerEntry {
|
||||
return {
|
||||
id: 'ledger-1',
|
||||
amountDelta: 30,
|
||||
balanceAfter: 80,
|
||||
sourceType: 'invite_invitee_reward',
|
||||
createdAt: '2026-06-03T00:00:00.000Z',
|
||||
...overrides,
|
||||
};
|
||||
}
|
||||
|
||||
function buildRechargeProduct(
|
||||
overrides: Partial<ProfileRechargeProduct> = {},
|
||||
): ProfileRechargeProduct {
|
||||
return {
|
||||
productId: 'points_60',
|
||||
title: '60泥点',
|
||||
priceCents: 600,
|
||||
kind: 'points',
|
||||
pointsAmount: 60,
|
||||
bonusPoints: 60,
|
||||
durationDays: 0,
|
||||
badgeLabel: '首充双倍',
|
||||
description: '首充送60泥点',
|
||||
tier: 'normal',
|
||||
...overrides,
|
||||
};
|
||||
}
|
||||
|
||||
function buildMembership(
|
||||
overrides: Partial<ProfileMembership> = {},
|
||||
): ProfileMembership {
|
||||
return {
|
||||
status: 'normal',
|
||||
tier: 'normal',
|
||||
startedAt: null,
|
||||
expiresAt: null,
|
||||
updatedAt: null,
|
||||
...overrides,
|
||||
};
|
||||
}
|
||||
|
||||
test('profile funds ViewModel formats ledger amount labels', () => {
|
||||
expect(formatWalletLedgerAmount(-1)).toBe('-1');
|
||||
expect(formatWalletLedgerAmount(0)).toBe('0');
|
||||
expect(formatWalletLedgerAmount(30)).toBe('+30');
|
||||
});
|
||||
|
||||
test('profile funds ViewModel resolves ledger source labels with raw fallback', () => {
|
||||
expect(getWalletLedgerSourceLabel('asset_operation_consume')).toBe(
|
||||
'资产操作消耗',
|
||||
);
|
||||
expect(getWalletLedgerSourceLabel('puzzle_author_incentive_claim')).toBe(
|
||||
'拼图作者奖励',
|
||||
);
|
||||
expect(getWalletLedgerSourceLabel('future_source')).toBe('future_source');
|
||||
expect(getWalletLedgerSourceLabel('')).toBe('未知来源');
|
||||
});
|
||||
|
||||
test('profile funds ViewModel builds wallet ledger presentation', () => {
|
||||
const incomeEntry = buildLedgerEntry({
|
||||
id: 'ledger-income',
|
||||
amountDelta: 30,
|
||||
balanceAfter: 80,
|
||||
sourceType: 'puzzle_author_incentive_claim',
|
||||
});
|
||||
const outcomeEntry = buildLedgerEntry({
|
||||
id: 'ledger-outcome',
|
||||
amountDelta: -1,
|
||||
balanceAfter: 79,
|
||||
sourceType: 'asset_operation_consume',
|
||||
});
|
||||
|
||||
expect(
|
||||
buildWalletLedgerPresentation(
|
||||
{ entries: [incomeEntry, outcomeEntry] },
|
||||
12,
|
||||
),
|
||||
).toEqual({
|
||||
balance: 80,
|
||||
balanceLabel: '80泥点',
|
||||
entries: [
|
||||
{
|
||||
amountLabel: '+30',
|
||||
balanceLabel: '余额 80',
|
||||
createdAt: '2026-06-03T00:00:00.000Z',
|
||||
id: 'ledger-income',
|
||||
isIncome: true,
|
||||
sourceLabel: '拼图作者奖励',
|
||||
},
|
||||
{
|
||||
amountLabel: '-1',
|
||||
balanceLabel: '余额 79',
|
||||
createdAt: '2026-06-03T00:00:00.000Z',
|
||||
id: 'ledger-outcome',
|
||||
isIncome: false,
|
||||
sourceLabel: '资产操作消耗',
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
expect(buildWalletLedgerPresentation({ entries: [] }, 12)).toEqual({
|
||||
balance: 12,
|
||||
balanceLabel: '12泥点',
|
||||
entries: [],
|
||||
});
|
||||
});
|
||||
|
||||
test('profile funds ViewModel formats recharge product and membership labels', () => {
|
||||
expect(formatRechargePrice(600)).toBe('¥6');
|
||||
expect(formatRechargePrice(650)).toBe('¥6.50');
|
||||
expect(buildRechargeProductValueLabel(buildRechargeProduct())).toBe(
|
||||
'60+60泥点',
|
||||
);
|
||||
expect(
|
||||
buildRechargeProductValueLabel(
|
||||
buildRechargeProduct({
|
||||
kind: 'membership',
|
||||
pointsAmount: 0,
|
||||
bonusPoints: 0,
|
||||
durationDays: 30,
|
||||
}),
|
||||
),
|
||||
).toBe('30天');
|
||||
expect(buildMembershipLabel(buildMembership(), (value) => value)).toBe(
|
||||
'普通用户',
|
||||
);
|
||||
expect(
|
||||
buildMembershipLabel(
|
||||
buildMembership({ status: 'active', expiresAt: null }),
|
||||
(value) => value,
|
||||
),
|
||||
).toBe('会员已生效');
|
||||
expect(
|
||||
buildMembershipLabel(
|
||||
buildMembership({
|
||||
status: 'active',
|
||||
expiresAt: '2026-06-03T00:00:00.000Z',
|
||||
}),
|
||||
() => '06/03 08:00',
|
||||
),
|
||||
).toBe('会员至 06/03 08:00');
|
||||
});
|
||||
Reference in New Issue
Block a user