fix: show big fish publish errors in modal

This commit is contained in:
2026-04-25 14:11:26 +08:00
parent 6f35306d53
commit 8ec19e2364
7 changed files with 166 additions and 8 deletions

View File

@@ -1,6 +1,6 @@
// @vitest-environment jsdom
import { render, screen } from '@testing-library/react';
import { fireEvent, render, screen } from '@testing-library/react';
import { describe, expect, test, vi } from 'vitest';
import type { BigFishSessionSnapshotResponse } from '../../../packages/shared/src/contracts/bigFish';
@@ -146,4 +146,28 @@ describe('BigFishResultView', () => {
expect(screen.getByAltText('荧潮幼体')).toBeTruthy();
expect(screen.getByAltText('深海谜境 场地背景')).toBeTruthy();
});
test('shows publish failures in a dismissible modal', () => {
const onDismissError = vi.fn();
render(
<BigFishResultView
session={createSession()}
error="big_fish 发布校验未通过:还缺少 16 个基础动作"
onBack={() => {}}
onDismissError={onDismissError}
onExecuteAction={() => {}}
onStartTestRun={() => {}}
/>,
);
expect(screen.getByRole('dialog')).toBeTruthy();
expect(screen.getByText('发布失败')).toBeTruthy();
expect(
screen.getByText('big_fish 发布校验未通过:还缺少 16 个基础动作'),
).toBeTruthy();
fireEvent.click(screen.getByRole('button', { name: '知道了' }));
expect(onDismissError).toHaveBeenCalledTimes(1);
});
});

View File

@@ -37,6 +37,7 @@ type BigFishResultViewProps = {
isBusy?: boolean;
error?: string | null;
onBack: () => void;
onDismissError?: () => void;
onExecuteAction: (payload: ExecuteBigFishActionRequest) => void;
onStartTestRun: () => void;
};
@@ -330,6 +331,7 @@ export function BigFishResultView({
isBusy = false,
error = null,
onBack,
onDismissError,
onExecuteAction,
onStartTestRun,
}: BigFishResultViewProps) {
@@ -417,12 +419,6 @@ export function BigFishResultView({
</div>
</div>
{error ? (
<div className="rounded-[1.15rem] border border-red-200 bg-red-50 px-4 py-3 text-sm text-red-600">
{error}
</div>
) : null}
<div className="grid min-h-0 flex-1 gap-3 overflow-hidden lg:grid-cols-[minmax(0,1fr)_18rem]">
<div className="min-h-0 overflow-y-auto pr-1">
<div className="grid gap-3 sm:grid-cols-2">
@@ -520,6 +516,58 @@ export function BigFishResultView({
}}
/>
) : null}
{error ? (
<BigFishResultErrorModal
message={error}
onClose={() => {
onDismissError?.();
}}
/>
) : null}
</div>
);
}
function BigFishResultErrorModal({
message,
onClose,
}: {
message: string;
onClose: () => void;
}) {
return (
<div className="fixed inset-0 z-[160] flex items-center justify-center bg-slate-950/58 px-4 py-6 backdrop-blur-sm">
<div
role="dialog"
aria-modal="true"
aria-labelledby="big-fish-result-error-title"
className="w-full max-w-sm rounded-[1.6rem] border border-red-100/80 bg-white p-5 text-slate-950 shadow-2xl"
>
<div className="flex items-start gap-3">
<div className="mt-0.5 inline-flex h-9 w-9 shrink-0 items-center justify-center rounded-full bg-red-50 text-red-600">
<Waves className="h-4 w-4" />
</div>
<div className="min-w-0 flex-1">
<div
id="big-fish-result-error-title"
className="text-base font-black text-slate-950"
>
</div>
<div className="mt-2 text-sm leading-6 text-slate-600">
{message}
</div>
</div>
</div>
<button
type="button"
onClick={onClose}
className="mt-5 inline-flex w-full items-center justify-center rounded-full bg-slate-950 px-4 py-2.5 text-sm font-bold text-white"
>
</button>
</div>
</div>
);
}

View File

@@ -1820,6 +1820,9 @@ export function PlatformEntryFlowShellImpl({
onBack={() => {
setSelectionStage('big-fish-agent-workspace');
}}
onDismissError={() => {
setBigFishError(null);
}}
onExecuteAction={(payload) => {
void executeBigFishAction(payload);
}}

View File

@@ -3,6 +3,29 @@ import {describe, expect, it} from 'vitest';
import {parseApiErrorMessage} from './jsonClient';
describe('parseApiErrorMessage', () => {
it('prefers api error detail messages for business failures', () => {
expect(
parseApiErrorMessage(
JSON.stringify({
ok: false,
data: null,
error: {
code: 'BAD_REQUEST',
message: '请求参数不合法',
details: {
message: 'big_fish 发布校验未通过:还缺少 16 个基础动作',
provider: 'spacetimedb',
},
},
meta: {
apiVersion: '2026-04-08',
},
}),
'Fallback failure',
),
).toBe('big_fish 发布校验未通过:还缺少 16 个基础动作');
});
it('prefers nested api error messages', () => {
expect(
parseApiErrorMessage(