736a1b6ac6
按 Router used_quota 累计值与首次基线结算泥点 新增原子 checkpoint 事务及 llm_router_consume 钱包流水 同步额度查询校验、前端展示、生成绑定和技术文档
135 lines
3.9 KiB
TypeScript
135 lines
3.9 KiB
TypeScript
/* @vitest-environment jsdom */
|
|
|
|
import { render, screen, within } from '@testing-library/react';
|
|
import userEvent from '@testing-library/user-event';
|
|
import { describe, expect, test, vi } from 'vitest';
|
|
|
|
import type { ProfileWalletLedgerEntry } from '../../contracts/runtime';
|
|
import { PlatformProfileWalletLedgerModal } from './index';
|
|
import {
|
|
buildWalletLedgerPresentation,
|
|
formatWalletLedgerAmount,
|
|
formatWalletLedgerDate,
|
|
getWalletLedgerSourceLabel,
|
|
} from './model';
|
|
|
|
function buildLedgerEntry(
|
|
overrides: Partial<ProfileWalletLedgerEntry> = {},
|
|
): ProfileWalletLedgerEntry {
|
|
return {
|
|
id: 'ledger-1',
|
|
amountDelta: 12,
|
|
balanceAfter: 88,
|
|
sourceType: 'daily_task_reward',
|
|
createdAt: '2026-06-10T08:00:00.000Z',
|
|
...overrides,
|
|
};
|
|
}
|
|
|
|
describe('PlatformProfileWalletLedgerModal', () => {
|
|
test('renders ledger entries with the latest balance and UTC date', () => {
|
|
render(
|
|
<PlatformProfileWalletLedgerModal
|
|
ledger={{ entries: [buildLedgerEntry()] }}
|
|
fallbackBalance={40}
|
|
isLoading={false}
|
|
error={null}
|
|
onClose={vi.fn()}
|
|
onRetry={vi.fn()}
|
|
/>,
|
|
);
|
|
|
|
const dialog = screen.getByRole('dialog', { name: '泥点账单' });
|
|
expect(within(dialog).getByText('88泥点')).toBeTruthy();
|
|
expect(within(dialog).getByText('每日任务奖励')).toBeTruthy();
|
|
expect(within(dialog).getByText('2026-06-10')).toBeTruthy();
|
|
expect(within(dialog).getByText('+12')).toBeTruthy();
|
|
expect(within(dialog).getByText('余额 88')).toBeTruthy();
|
|
});
|
|
|
|
test('supports close, loading, empty, and error retry states', async () => {
|
|
const user = userEvent.setup();
|
|
const onClose = vi.fn();
|
|
const onRetry = vi.fn();
|
|
const { rerender } = render(
|
|
<PlatformProfileWalletLedgerModal
|
|
ledger={null}
|
|
fallbackBalance={40}
|
|
isLoading
|
|
error={null}
|
|
onClose={onClose}
|
|
onRetry={onRetry}
|
|
/>,
|
|
);
|
|
|
|
expect(screen.getByRole('status', { name: '泥点账单加载中' })).toBeTruthy();
|
|
await user.click(screen.getByRole('button', { name: '关闭泥点账单' }));
|
|
expect(onClose).toHaveBeenCalledTimes(1);
|
|
|
|
rerender(
|
|
<PlatformProfileWalletLedgerModal
|
|
ledger={{ entries: [] }}
|
|
fallbackBalance={40}
|
|
isLoading={false}
|
|
error={null}
|
|
onClose={onClose}
|
|
onRetry={onRetry}
|
|
/>,
|
|
);
|
|
expect(screen.getByText('暂无账单记录')).toBeTruthy();
|
|
expect(screen.getByText('40泥点')).toBeTruthy();
|
|
|
|
rerender(
|
|
<PlatformProfileWalletLedgerModal
|
|
ledger={null}
|
|
fallbackBalance={40}
|
|
isLoading={false}
|
|
error="账单加载失败"
|
|
onClose={onClose}
|
|
onRetry={onRetry}
|
|
/>,
|
|
);
|
|
await user.click(screen.getByRole('button', { name: '重新加载' }));
|
|
expect(onRetry).toHaveBeenCalledTimes(1);
|
|
});
|
|
});
|
|
|
|
test('builds wallet ledger presentation with stable source fallbacks', () => {
|
|
expect(formatWalletLedgerAmount(-1)).toBe('-1');
|
|
expect(formatWalletLedgerAmount(0)).toBe('0');
|
|
expect(formatWalletLedgerAmount(30)).toBe('+30');
|
|
expect(getWalletLedgerSourceLabel('asset_operation_consume')).toBe(
|
|
'资产操作消耗',
|
|
);
|
|
expect(getWalletLedgerSourceLabel('future_source')).toBe('future_source');
|
|
expect(getWalletLedgerSourceLabel('llm_router_consume')).toBe('LLM 调用消耗');
|
|
expect(getWalletLedgerSourceLabel('')).toBe('未知来源');
|
|
expect(formatWalletLedgerDate('not-a-date')).toBe('not-a-date');
|
|
|
|
expect(
|
|
buildWalletLedgerPresentation(
|
|
{
|
|
entries: [
|
|
buildLedgerEntry({
|
|
amountDelta: -1,
|
|
sourceType: 'asset_operation_consume',
|
|
}),
|
|
],
|
|
},
|
|
12,
|
|
),
|
|
).toMatchObject({
|
|
balance: 88,
|
|
balanceLabel: '88泥点',
|
|
entries: [
|
|
{
|
|
amountLabel: '-1',
|
|
balanceLabel: '余额 88',
|
|
createdAtLabel: '2026-06-10',
|
|
isIncome: false,
|
|
sourceLabel: '资产操作消耗',
|
|
},
|
|
],
|
|
});
|
|
});
|