This commit is contained in:
2026-05-15 06:36:48 +08:00
620 changed files with 126075 additions and 6322 deletions

View File

@@ -675,6 +675,10 @@ function renderProfileView(
);
}
async function openRechargeModal(user: ReturnType<typeof userEvent.setup>) {
await user.click(screen.getByRole('button', { name: /\s*\//u }));
}
function renderLoggedOutHomeView(
openLoginModal = vi.fn(),
overrides: Partial<
@@ -924,7 +928,9 @@ afterEach(() => {
vi.unstubAllGlobals();
window.wx = undefined;
document
.querySelectorAll('script[src="https://res.wx.qq.com/open/js/jweixin-1.6.0.js"]')
.querySelectorAll(
'script[src="https://res.wx.qq.com/open/js/jweixin-1.6.0.js"]',
)
.forEach((script) => script.remove());
mockGetRpgProfileReferralInviteCenter.mockResolvedValue(
mockBuildReferralCenter(),
@@ -1016,10 +1022,7 @@ test('profile recharge modal buys points through mock channel outside mini progr
const onRechargeSuccess = vi.fn();
renderProfileView(onRechargeSuccess);
const shortcutRegion = screen.getByRole('region', { name: '常用功能' });
await user.click(
within(shortcutRegion).getByRole('button', { name: //u }),
);
await openRechargeModal(user);
expect(await screen.findByText('账户充值')).toBeTruthy();
expect(mockGetRpgProfileRechargeCenter).toHaveBeenCalledTimes(1);
@@ -1031,13 +1034,52 @@ test('profile recharge modal buys points through mock channel outside mini progr
'mock',
);
});
expect(
await screen.findByRole('dialog', { name: '支付成功' }),
).toBeTruthy();
expect(await screen.findByRole('dialog', { name: '支付成功' })).toBeTruthy();
expect(screen.getByText('已到账,账户状态已刷新。')).toBeTruthy();
expect(onRechargeSuccess).toHaveBeenCalledTimes(1);
});
test('profile recharge modal trusts per-product first bonus display after points recharge', async () => {
const user = userEvent.setup();
mockGetRpgProfileRechargeCenter.mockResolvedValueOnce({
walletBalance: 60,
membership: {
status: 'normal',
tier: 'normal',
startedAt: null,
expiresAt: null,
updatedAt: null,
},
pointProducts: [
{
productId: 'points_60',
title: '60泥点',
priceCents: 600,
kind: 'points',
pointsAmount: 60,
bonusPoints: 60,
durationDays: 0,
badgeLabel: '首充双倍',
description: '首充送60泥点',
tier: 'normal',
},
],
membershipProducts: [],
benefits: [],
latestOrder: null,
hasPointsRecharged: true,
});
renderProfileView();
await openRechargeModal(user);
const rechargeDialog = await screen.findByText('账户充值');
expect(rechargeDialog).toBeTruthy();
expect(screen.getByRole('button', { name: /60/u })).toBeTruthy();
expect(screen.getByText('首充双倍')).toBeTruthy();
expect(screen.getByText('60+60泥点')).toBeTruthy();
});
test('profile recharge modal posts requestPayment params in mini program web-view', async () => {
const user = userEvent.setup();
const onRechargeSuccess = vi.fn();
@@ -1090,10 +1132,7 @@ test('profile recharge modal posts requestPayment params in mini program web-vie
});
renderProfileView(onRechargeSuccess);
const shortcutRegion = screen.getByRole('region', { name: '常用功能' });
await user.click(
within(shortcutRegion).getByRole('button', { name: //u }),
);
await openRechargeModal(user);
await user.click(await screen.findByRole('button', { name: /60/u }));
await waitFor(() => {
@@ -1118,9 +1157,7 @@ test('profile recharge modal posts requestPayment params in mini program web-vie
});
expect(navigateUrl).toContain('order-wechat-1');
expect(decodeURIComponent(navigateUrl)).toContain('prepay_id=wx-prepay');
expect(
await screen.findByRole('dialog', { name: '支付成功' }),
).toBeTruthy();
expect(await screen.findByRole('dialog', { name: '支付成功' })).toBeTruthy();
expect(screen.getByText('已到账,账户状态已刷新。')).toBeTruthy();
expect(mockConfirmWechatRpgProfileRechargeOrder).toHaveBeenCalledWith(
'order-wechat-1',
@@ -1243,10 +1280,7 @@ test('profile recharge modal waits for paid confirmation before refreshing dashb
});
renderProfileView(onRechargeSuccess);
const shortcutRegion = screen.getByRole('region', { name: '常用功能' });
await user.click(
within(shortcutRegion).getByRole('button', { name: //u }),
);
await openRechargeModal(user);
await user.click(await screen.findByRole('button', { name: /60/u }));
const navigateUrl = navigateTo.mock.calls[0]?.[0].url ?? '';
@@ -1266,9 +1300,7 @@ test('profile recharge modal waits for paid confirmation before refreshing dashb
expect(mockConfirmWechatRpgProfileRechargeOrder).toHaveBeenCalledTimes(2);
});
expect(
await screen.findByRole('dialog', { name: '支付成功' }),
).toBeTruthy();
expect(await screen.findByRole('dialog', { name: '支付成功' })).toBeTruthy();
expect(onRechargeSuccess).toHaveBeenCalledTimes(1);
});
@@ -1319,10 +1351,7 @@ test('profile recharge modal loads wechat js sdk before mini program payment bri
});
renderProfileView();
const shortcutRegion = screen.getByRole('region', { name: '常用功能' });
await user.click(
within(shortcutRegion).getByRole('button', { name: //u }),
);
await openRechargeModal(user);
await user.click(await screen.findByRole('button', { name: /60/u }));
await waitFor(() => {
@@ -1354,9 +1383,7 @@ test('profile recharge modal loads wechat js sdk before mini program payment bri
window.location.hash = `wx_pay_result=${requestId}:success`;
window.dispatchEvent(new HashChangeEvent('hashchange'));
});
expect(
await screen.findByRole('dialog', { name: '支付成功' }),
).toBeTruthy();
expect(await screen.findByRole('dialog', { name: '支付成功' })).toBeTruthy();
});
test('profile recharge modal releases submitting state after cancelled wechat pay result', async () => {
@@ -1410,10 +1437,7 @@ test('profile recharge modal releases submitting state after cancelled wechat pa
});
renderProfileView();
const shortcutRegion = screen.getByRole('region', { name: '常用功能' });
await user.click(
within(shortcutRegion).getByRole('button', { name: //u }),
);
await openRechargeModal(user);
const buyButton = await screen.findByRole('button', { name: /60/u });
await user.click(buyButton);

View File

@@ -2711,9 +2711,11 @@ function RechargeProductCard({
onBuy: (product: ProfileRechargeProduct) => void;
}) {
const submitting = submittingProductId === product.productId;
const effectiveBonusPoints = product.bonusPoints;
const badgeLabel = product.badgeLabel;
const value =
product.kind === 'points'
? `${product.pointsAmount}${product.bonusPoints > 0 ? `+${product.bonusPoints}` : ''}泥点`
? `${product.pointsAmount}${effectiveBonusPoints > 0 ? `+${effectiveBonusPoints}` : ''}泥点`
: `${product.durationDays}`;
return (
@@ -2723,9 +2725,9 @@ function RechargeProductCard({
disabled={Boolean(submittingProductId)}
className="platform-subpanel platform-interactive-card relative min-h-[7.25rem] rounded-[1.15rem] px-3.5 py-3.5 text-left disabled:cursor-not-allowed disabled:opacity-60"
>
{product.badgeLabel ? (
{badgeLabel ? (
<span className="platform-pill platform-pill--warm absolute right-3 top-3 max-w-[7rem] truncate px-2 py-0.5 text-[10px]">
{product.badgeLabel}
{badgeLabel}
</span>
) : null}
<div className="pr-20 text-sm font-black text-[var(--platform-text-strong)]">
@@ -4159,14 +4161,11 @@ export function RpgEntryHomeView({
})
.finally(() => setIsLoadingRechargeCenter(false));
}, []);
const refreshRechargeState = useCallback(
() => {
loadRechargeCenter();
setSubmittingRechargeProductId(null);
pendingWechatRechargeOrderIdRef.current = null;
},
[loadRechargeCenter],
);
const refreshRechargeState = useCallback(() => {
loadRechargeCenter();
setSubmittingRechargeProductId(null);
pendingWechatRechargeOrderIdRef.current = null;
}, [loadRechargeCenter]);
const handleWechatPayResult = useCallback(() => {
const payResult = readWechatPayResultFromHash();
if (!payResult) {

View File

@@ -91,4 +91,3 @@ export function getPuzzleHistoryAssetReferenceLabel(
return `历史素材 · ${displayName}`;
}