3D 提交失败路径也刷新钱包余额
- src/components/image-editor/model3d-generation/useModel3dGenerationTask.ts:请求失败与「2xx 但没有任务状态」两条路径都调用 onWalletBalanceMayHaveChanged,与其它画布生成链路的 runEditorGenerationWithWalletRefresh 同一口径(超时或空 body 的 2xx 都可能已经扣费) - src/components/image-editor/model3d-generation/useModel3dGenerationTask.test.tsx:补两条失败路径各刷新一次钱包的断言
This commit is contained in:
@@ -99,11 +99,13 @@ function renderTask({
|
||||
projectId = 'project-1',
|
||||
assetFolderId,
|
||||
applyQueuedGeneration = vi.fn(async () => true),
|
||||
onWalletBalanceMayHaveChanged = vi.fn(),
|
||||
}: {
|
||||
dialog: GenerateDialogState;
|
||||
projectId?: string | null;
|
||||
assetFolderId?: string | null;
|
||||
applyQueuedGeneration?: (...args: unknown[]) => Promise<boolean>;
|
||||
onWalletBalanceMayHaveChanged?: () => void;
|
||||
}) {
|
||||
const onQueuedGenerationTask = vi.fn();
|
||||
const view = renderHook(() => {
|
||||
@@ -126,6 +128,7 @@ function renderTask({
|
||||
currentDialog.placeholder ?? null,
|
||||
applyQueuedGeneration: applyQueuedGeneration as never,
|
||||
onQueuedGenerationTask,
|
||||
onWalletBalanceMayHaveChanged,
|
||||
});
|
||||
return {
|
||||
submitModel3dGeneration,
|
||||
@@ -133,7 +136,7 @@ function renderTask({
|
||||
dialog: dialogs[0] as GenerateDialogState,
|
||||
};
|
||||
});
|
||||
return { ...view, onQueuedGenerationTask };
|
||||
return { ...view, onQueuedGenerationTask, onWalletBalanceMayHaveChanged };
|
||||
}
|
||||
|
||||
describe('useModel3dGenerationTask', () => {
|
||||
@@ -293,6 +296,32 @@ describe('useModel3dGenerationTask', () => {
|
||||
expect(submitModel3dTextToModelRequestMock).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('提交失败与「2xx 无任务状态」都按可能已扣费刷新钱包', async () => {
|
||||
submitModel3dTextToModelRequestMock.mockRejectedValue(
|
||||
new ApiClientError({
|
||||
message: '3D 模型生成失败,请稍后重试。',
|
||||
status: 502,
|
||||
code: 'tripo-upstream-error',
|
||||
}),
|
||||
);
|
||||
const failed = renderTask({ dialog: createDialog() });
|
||||
|
||||
await act(async () => {
|
||||
await failed.result.current.submitModel3dGeneration(createDialog());
|
||||
});
|
||||
|
||||
expect(failed.onWalletBalanceMayHaveChanged).toHaveBeenCalledTimes(1);
|
||||
|
||||
submitModel3dTextToModelRequestMock.mockResolvedValue(null);
|
||||
const emptyBody = renderTask({ dialog: createDialog() });
|
||||
|
||||
await act(async () => {
|
||||
await emptyBody.result.current.submitModel3dGeneration(createDialog());
|
||||
});
|
||||
|
||||
expect(emptyBody.onWalletBalanceMayHaveChanged).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it('定价段缺失时不发请求,只把不可提交的原因写回面板', async () => {
|
||||
applyEditorGenerationPricingConfig({
|
||||
models: EDITOR_MODEL_MUD_POINT_CONFIG,
|
||||
|
||||
@@ -127,6 +127,8 @@ export function useModel3dGenerationTask({
|
||||
if (!queueState) {
|
||||
// 2xx 但没有任务状态(空 body 或缺 status 的 payload)不能当成功静默复位:
|
||||
// 用户既看不到任务也没有任何提示,服务端细节被丢掉。
|
||||
// 服务端在这条路上也可能已经扣过费,钱包余额同样要按「可能变了」刷新。
|
||||
onWalletBalanceMayHaveChanged?.();
|
||||
updateCanvasGenerationDialogById(dialogId, (currentDialog) => ({
|
||||
...currentDialog,
|
||||
status: 'failed',
|
||||
@@ -155,6 +157,9 @@ export function useModel3dGenerationTask({
|
||||
errorMessage: undefined,
|
||||
}));
|
||||
} catch (error) {
|
||||
// 超时等失败也可能意味着服务端已经扣费(与其它生成链路的
|
||||
// runEditorGenerationWithWalletRefresh 同一口径),失败路径也要刷新钱包。
|
||||
onWalletBalanceMayHaveChanged?.();
|
||||
updateCanvasGenerationDialogById(dialogId, (currentDialog) => ({
|
||||
...currentDialog,
|
||||
status: 'failed',
|
||||
|
||||
Reference in New Issue
Block a user