Files
Genarrative/packages/shared/src/components/PlatformMudPointWalletEntry.test.tsx
T
kdletters ea8d0ef064 修复泥点余额自动刷新
顶部泥点总余额优先展示实时钱包余额,避免缓存明细覆盖刷新结果。

补充缓存明细场景的余额变更回归测试。

同步主站与图片画布的泥点余额数据口径文档。
2026-07-15 22:01:25 +08:00

146 lines
4.7 KiB
TypeScript

/* @vitest-environment jsdom */
import {
act,
fireEvent,
render,
screen,
within,
} from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { expect, test, vi } from 'vitest';
import { formatMudPointCount } from '../utils/format';
import { PlatformMudPointWalletEntry } from './PlatformMudPointWalletEntry.tsx';
const breakdown = {
totalPoints: 207,
permanentPoints: 100,
limitedPoints: 80,
limitedExpiresAt: '2026-07-06T16:00:00Z',
dailyFreePoints: 27,
dailyFreeResetPoints: 20,
dailyFreeResetsAt: '2026-07-12T16:00:00Z',
};
test('formats mud point counts consistently', () => {
expect(formatMudPointCount(12_345)).toBe('12,345');
expect(formatMudPointCount(12_345, true)).toBe('1.2万');
});
test('shows only permanent and daily free points in the shared wallet panel', async () => {
const user = userEvent.setup();
const onRequestDetails = vi.fn();
const onRecharge = vi.fn();
const onOpenLedger = vi.fn();
render(
<PlatformMudPointWalletEntry
balance={207}
breakdown={breakdown}
onRequestDetails={onRequestDetails}
onRecharge={onRecharge}
onOpenLedger={onOpenLedger}
/>,
);
const balanceButton = screen.getByRole('button', { name: '泥点 207' });
await user.hover(balanceButton);
const details = screen.getByRole('dialog', { name: '泥点账户详情' });
expect(details.className).toContain('rounded-[1.12rem]');
expect(within(details).getByText('不限时泥点')).toBeTruthy();
expect(within(details).getByText('按量充值、兑换码获得')).toBeTruthy();
expect(within(details).getByText('100')).toBeTruthy();
expect(within(details).queryByText('限时泥点')).toBeNull();
expect(within(details).queryByText('2026-07-07 到期')).toBeNull();
expect(within(details).getByText('每日免费泥点')).toBeTruthy();
expect(within(details).getByText('27')).toBeTruthy();
expect(within(details).getByText('每天重置为 20 泥点')).toBeTruthy();
expect(onRequestDetails).not.toHaveBeenCalled();
await user.click(within(details).getByRole('button', { name: '使用详情' }));
expect(onOpenLedger).toHaveBeenCalledTimes(1);
await user.click(screen.getByRole('button', { name: '充值' }));
expect(onRecharge).toHaveBeenCalledTimes(1);
});
test('keeps the chip on the live balance when cached details are stale', () => {
const props = {
breakdown,
onRequestDetails: vi.fn(),
onRecharge: vi.fn(),
onOpenLedger: vi.fn(),
};
const { rerender } = render(
<PlatformMudPointWalletEntry balance={207} {...props} />,
);
expect(screen.getByRole('button', { name: '泥点 207' })).toBeTruthy();
rerender(<PlatformMudPointWalletEntry balance={195} {...props} />);
expect(screen.getByRole('button', { name: '泥点 195' })).toBeTruthy();
expect(screen.queryByRole('button', { name: '泥点 207' })).toBeNull();
});
test('keeps the desktop panel open while moving across the gap without click pinning', () => {
vi.useFakeTimers();
try {
render(
<PlatformMudPointWalletEntry
balance={207}
breakdown={breakdown}
onRequestDetails={vi.fn()}
onRecharge={vi.fn()}
onOpenLedger={vi.fn()}
/>,
);
const balanceButton = screen.getByRole('button', { name: '泥点 207' });
const root = balanceButton.closest('.platform-mud-point-wallet-entry');
expect(root).toBeTruthy();
fireEvent.mouseEnter(balanceButton);
const details = screen.getByRole('dialog', { name: '泥点账户详情' });
fireEvent.mouseLeave(root as HTMLElement, { relatedTarget: null });
fireEvent.mouseEnter(details);
act(() => vi.advanceTimersByTime(120));
expect(screen.getByRole('dialog', { name: '泥点账户详情' })).toBeTruthy();
balanceButton.focus();
fireEvent.click(balanceButton);
expect(screen.getByRole('dialog', { name: '泥点账户详情' })).toBeTruthy();
fireEvent.mouseLeave(root as HTMLElement, { relatedTarget: null });
act(() => vi.advanceTimersByTime(120));
expect(screen.queryByRole('dialog', { name: '泥点账户详情' })).toBeNull();
} finally {
vi.useRealTimers();
}
});
test('requests the balance breakdown when a compact entry opens', async () => {
const user = userEvent.setup();
const onRequestDetails = vi.fn();
render(
<PlatformMudPointWalletEntry
balance={20}
breakdown={null}
isLoading={false}
variant="mobile"
onRequestDetails={onRequestDetails}
onRecharge={vi.fn()}
onOpenLedger={vi.fn()}
/>,
);
await user.click(screen.getByRole('button', { name: '泥点 20' }));
expect(onRequestDetails).toHaveBeenCalledTimes(1);
expect(screen.getByText('余额明细暂不可用')).toBeTruthy();
});