隔离账号切换后的兑换回调

奖励码与邀请码兑换记录发起账号和账号生命周期 revision,忽略切换账号后的成功、失败与收尾回调。

账号切换时同步结束兑换提交态,并补充两类兑换回归测试。
This commit is contained in:
2026-08-05 17:49:52 +08:00
parent 314c861b0f
commit 7e78e1bdaa
2 changed files with 134 additions and 2 deletions
@@ -0,0 +1,86 @@
/* @vitest-environment jsdom */
import { act } from '@testing-library/react';
import { beforeEach, describe, expect, test, vi } from 'vitest';
import { usePlatformWalletStore } from '../../stores/usePlatformWalletStore';
import {
profileClientMocks,
renderController,
userA,
userB,
} from './usePlatformProfileCenterController.testSupport';
describe('usePlatformProfileCenterController redemption lifecycle', () => {
beforeEach(() => {
window.history.replaceState(null, '', '/profile');
usePlatformWalletStore.getState().resetWalletBalance();
vi.clearAllMocks();
});
test('ignores a reward-code response after the account changes', async () => {
let resolveReward!: (value: {
walletBalance: number;
amountGranted: number;
ledgerEntry: never;
}) => void;
profileClientMocks.redeemPlatformProfileRewardCode.mockImplementation(
() =>
new Promise((resolve) => {
resolveReward = resolve;
}),
);
const onRechargeSuccess = vi.fn();
const { result, rerender } = renderController(userA, onRechargeSuccess);
act(() => result.current.setRewardCodeInput('reward-code'));
act(() => result.current.submitRewardCode());
rerender({ user: userB });
await act(async () => {
resolveReward({
walletBalance: 100,
amountGranted: 20,
ledgerEntry: undefined as never,
});
});
expect(result.current.rewardCodeSuccess).toBeNull();
expect(result.current.isSubmittingRewardCode).toBe(false);
expect(onRechargeSuccess).not.toHaveBeenCalled();
});
test('ignores an invite-code response after the account changes', async () => {
let resolveReferral!: (value: {
center: never;
inviteeRewardGranted: boolean;
inviterRewardGranted: boolean;
inviteeBalanceAfter: number;
inviterBalanceAfter: number;
}) => void;
profileClientMocks.redeemPlatformProfileReferralInviteCode.mockImplementation(
() =>
new Promise((resolve) => {
resolveReferral = resolve;
}),
);
const onRechargeSuccess = vi.fn();
const { result, rerender } = renderController(userA, onRechargeSuccess);
act(() => result.current.setReferralRedeemCode('invite-code'));
act(() => result.current.submitReferralRedeemCode());
rerender({ user: userB });
await act(async () => {
resolveReferral({
center: undefined as never,
inviteeRewardGranted: true,
inviterRewardGranted: false,
inviteeBalanceAfter: 100,
inviterBalanceAfter: 0,
});
});
expect(result.current.referralSuccess).toBeNull();
expect(result.current.isSubmittingReferralRedeem).toBe(false);
expect(onRechargeSuccess).not.toHaveBeenCalled();
});
});
@@ -397,8 +397,10 @@ export function usePlatformProfileCenterController({
setIsLoadingWalletLedger(false);
setIsRewardCodeOpen(false);
setRewardCodeInput('');
setIsSubmittingRewardCode(false);
setRewardCodeError(null);
setRewardCodeSuccess(null);
setIsSubmittingReferralRedeem(false);
}, [currentUserId]);
// 中文注释:支持带邀请码 query 的直达场景,登录成功后自动打开兑换面板并复用同一套输入状态。
@@ -1136,8 +1138,16 @@ export function usePlatformProfileCenterController({
setIsSubmittingReferralRedeem(true);
setReferralError(null);
setReferralSuccess(null);
const snapshotOwnerUserId = currentUserId;
const accountRevision = accountLifecycleRevisionRef.current;
void redeemPlatformProfileReferralInviteCode(inviteCode)
.then((response) => {
if (
accountRevision !== accountLifecycleRevisionRef.current ||
currentUserIdRef.current !== snapshotOwnerUserId
) {
return;
}
setReferralCenter(response.center);
setReferralRedeemCode('');
setReferralSuccess('已填写');
@@ -1145,12 +1155,26 @@ export function usePlatformProfileCenterController({
void onRechargeSuccess?.();
})
.catch((error: unknown) => {
if (
accountRevision !== accountLifecycleRevisionRef.current ||
currentUserIdRef.current !== snapshotOwnerUserId
) {
return;
}
setReferralError(
error instanceof Error ? error.message : '填写邀请码失败',
);
})
.finally(() => setIsSubmittingReferralRedeem(false));
.finally(() => {
if (
accountRevision === accountLifecycleRevisionRef.current &&
currentUserIdRef.current === snapshotOwnerUserId
) {
setIsSubmittingReferralRedeem(false);
}
});
}, [
currentUserId,
isSubmittingReferralRedeem,
onRechargeSuccess,
onWalletBalanceMayHaveChanged,
@@ -1165,18 +1189,40 @@ export function usePlatformProfileCenterController({
setIsSubmittingRewardCode(true);
setRewardCodeError(null);
setRewardCodeSuccess(null);
const snapshotOwnerUserId = currentUserId;
const accountRevision = accountLifecycleRevisionRef.current;
void redeemPlatformProfileRewardCode(rewardCodeInput)
.then((response: RedeemProfileRewardCodeResponse) => {
if (
accountRevision !== accountLifecycleRevisionRef.current ||
currentUserIdRef.current !== snapshotOwnerUserId
) {
return;
}
setRewardCodeInput('');
setRewardCodeSuccess(`已到账 ${response.amountGranted} 泥点`);
void onWalletBalanceMayHaveChanged();
void onRechargeSuccess?.();
})
.catch((error: unknown) => {
if (
accountRevision !== accountLifecycleRevisionRef.current ||
currentUserIdRef.current !== snapshotOwnerUserId
) {
return;
}
setRewardCodeError(error instanceof Error ? error.message : '兑换失败');
})
.finally(() => setIsSubmittingRewardCode(false));
.finally(() => {
if (
accountRevision === accountLifecycleRevisionRef.current &&
currentUserIdRef.current === snapshotOwnerUserId
) {
setIsSubmittingRewardCode(false);
}
});
}, [
currentUserId,
isSubmittingRewardCode,
onRechargeSuccess,
onWalletBalanceMayHaveChanged,