修正(会员弹层):升级报价未到时不再把标准价显示为本次补付
- 新增 amountPending:升级报价缺失时金额区显示占位符,CTA 只显示「补差升级」 - 补一条回归测试覆盖报价加载中的确认页
This commit is contained in:
@@ -261,6 +261,49 @@ describe('PlatformProfileRechargeModal', () => {
|
||||
expect(onSubmitMembershipCheckout).toHaveBeenCalledWith('max', 'yearly');
|
||||
});
|
||||
|
||||
test('shows a placeholder instead of the list price while the upgrade quote is loading', async () => {
|
||||
const user = userEvent.setup();
|
||||
|
||||
render(
|
||||
<PlatformProfileRechargeModal
|
||||
center={{
|
||||
mudPointBalance: buildMudPointBalance(615),
|
||||
membership: buildActiveMembership('plus', 'yearly'),
|
||||
pointProducts: buildPointProducts(),
|
||||
membershipPlans: [STARTER_PLAN, PLUS_PLAN, MAX_PLAN],
|
||||
latestOrder: null,
|
||||
hasPointsRecharged: true,
|
||||
}}
|
||||
isLoading={false}
|
||||
error={null}
|
||||
submittingProductId={null}
|
||||
nativePayment={null}
|
||||
membershipQuote={null}
|
||||
isLoadingMembershipQuote={true}
|
||||
membershipQuoteError={null}
|
||||
onClose={vi.fn()}
|
||||
onRetry={vi.fn()}
|
||||
onBuy={vi.fn()}
|
||||
onRequestMembershipQuote={vi.fn()}
|
||||
onSubmitMembershipCheckout={vi.fn()}
|
||||
onConfirmNativePayment={vi.fn()}
|
||||
onCloseNativePayment={vi.fn()}
|
||||
/>,
|
||||
);
|
||||
|
||||
await user.click(screen.getByRole('button', { name: 'Max 年付 补差升级' }));
|
||||
|
||||
const checkout = screen.getByRole('dialog', { name: '确认套餐变更' });
|
||||
// 报价未到:金额占位,不能把 Max 标准年价(¥6990)当成「本次补付」。
|
||||
expect(within(checkout).getByText('—')).toBeTruthy();
|
||||
expect(
|
||||
within(checkout).queryByRole('button', { name: /^补差升级 ¥/ }),
|
||||
).toBeNull();
|
||||
expect(
|
||||
within(checkout).getByRole('button', { name: '补差升级' }),
|
||||
).toHaveProperty('disabled', true);
|
||||
});
|
||||
|
||||
test('recharge tab picks a point product and forwards the buy action', async () => {
|
||||
const user = userEvent.setup();
|
||||
const onBuy = vi.fn();
|
||||
|
||||
@@ -1013,9 +1013,20 @@ function PlatformRechargeCheckoutDialog({
|
||||
membershipQuote.cycleKind === target.cycleKind
|
||||
? membershipQuote
|
||||
: null;
|
||||
// 升级金额只能来自服务端报价:报价未到 / 失败时不能拿新套餐标准价冒充「本次补付」。
|
||||
const amountPending = isUpgrade && !quoteForTarget;
|
||||
const amountCents = quoteForTarget
|
||||
? quoteForTarget.amountCents
|
||||
: listPriceCents;
|
||||
const amountText = amountPending ? '—' : formatRechargePrice(amountCents);
|
||||
let ctaLabel: string;
|
||||
if (!isUpgrade) {
|
||||
ctaLabel = `支付 ${amountText}`;
|
||||
} else if (amountPending) {
|
||||
ctaLabel = '补差升级';
|
||||
} else {
|
||||
ctaLabel = `补差升级 ${amountText}`;
|
||||
}
|
||||
const canSubmit =
|
||||
Boolean(plan) &&
|
||||
!submitting &&
|
||||
@@ -1072,12 +1083,9 @@ function PlatformRechargeCheckoutDialog({
|
||||
title={isUpgrade ? '确认套餐变更' : '确认订单'}
|
||||
submitting={submitting}
|
||||
amountCents={amountCents}
|
||||
amountPending={amountPending}
|
||||
amountLabel={isUpgrade ? '本次补付' : '本次支付'}
|
||||
ctaLabel={
|
||||
isUpgrade
|
||||
? `补差升级 ${formatRechargePrice(amountCents)}`
|
||||
: `支付 ${formatRechargePrice(amountCents)}`
|
||||
}
|
||||
ctaLabel={ctaLabel}
|
||||
ctaDisabled={!canSubmit}
|
||||
onClose={onClose}
|
||||
onSubmit={() => {
|
||||
@@ -1103,6 +1111,7 @@ function PlatformRechargeCheckoutDialog({
|
||||
function PlatformRechargeCheckoutShell({
|
||||
title,
|
||||
amountCents,
|
||||
amountPending = false,
|
||||
amountLabel = '本次支付',
|
||||
ctaLabel,
|
||||
ctaDisabled = false,
|
||||
@@ -1115,6 +1124,8 @@ function PlatformRechargeCheckoutShell({
|
||||
}: {
|
||||
title: string;
|
||||
amountCents: number;
|
||||
/** 金额未知(升级报价未到 / 失败)时只显示占位符,避免拿标准价冒充补差金额。 */
|
||||
amountPending?: boolean;
|
||||
amountLabel?: string;
|
||||
ctaLabel: string;
|
||||
ctaDisabled?: boolean;
|
||||
@@ -1142,7 +1153,7 @@ function PlatformRechargeCheckoutShell({
|
||||
{amountLabel}
|
||||
</div>
|
||||
<div className="mt-1 text-3xl font-black tabular-nums text-[var(--platform-text-strong)]">
|
||||
{formatRechargePrice(amountCents)}
|
||||
{amountPending ? '—' : formatRechargePrice(amountCents)}
|
||||
</div>
|
||||
</div>
|
||||
{errorState ? <div className="mt-4">{errorState}</div> : null}
|
||||
|
||||
Reference in New Issue
Block a user