完善抓大鹅创作入口与运行态表现

This commit is contained in:
2026-05-01 22:07:55 +08:00
parent 8c03ec95c6
commit 9a3db67e13
25 changed files with 1320 additions and 183 deletions

View File

@@ -10,6 +10,9 @@ import type {
CustomWorldAgentSessionSnapshot,
CustomWorldWorkSummary,
} from '../../../packages/shared/src/contracts/customWorldAgent';
import type {
Match3DAgentSessionSnapshot,
} from '../../../packages/shared/src/contracts/match3dAgent';
import type { Match3DRunSnapshot } from '../../../packages/shared/src/contracts/match3dRuntime';
import type { Match3DWorkSummary } from '../../../packages/shared/src/contracts/match3dWorks';
import type { PuzzleRunSnapshot } from '../../../packages/shared/src/contracts/puzzleRuntimeSession';
@@ -124,17 +127,6 @@ async function openCreationHub(user: ReturnType<typeof userEvent.setup>) {
expect(await screen.findByText('角色扮演')).toBeTruthy();
}
async function expectRpgCreationLocked(
user: ReturnType<typeof userEvent.setup>,
) {
await openCreationHub(user);
const rpgButton = screen.getByRole('button', { name: //u });
expect((rpgButton as HTMLButtonElement).disabled).toBe(true);
expect(within(rpgButton).getAllByText('敬请期待').length).toBeGreaterThan(0);
await user.click(rpgButton);
expect(createRpgCreationSession).not.toHaveBeenCalled();
}
async function openExistingRpgDraft(
user: ReturnType<typeof userEvent.setup>,
actionName: string | RegExp = /(?:|)/u,
@@ -433,6 +425,21 @@ vi.mock('../big-fish-result/BigFishResultView', () => ({
),
}));
vi.mock('../match3d-creation/Match3DAgentWorkspace', () => ({
Match3DAgentWorkspace: ({
session,
}: {
session: { sessionId: string; messages: Array<{ text: string }> } | null;
}) => (
<div className="match3d-agent-workspace-mock">
<div>{session?.sessionId ?? 'missing-session'}</div>
{session?.messages.map((message) => (
<div key={`${session.sessionId}-${message.text}`}>{message.text}</div>
))}
</div>
),
}));
vi.mock('../match3d-runtime/Match3DRuntimeShell', () => ({
Match3DRuntimeShell: ({
run,
@@ -670,6 +677,59 @@ function buildMockMatch3DRun(profileId: string): Match3DRunSnapshot {
};
}
function buildMockMatch3DAgentSession(
overrides: Partial<Match3DAgentSessionSnapshot> = {},
): Match3DAgentSessionSnapshot {
const sessionId = overrides.sessionId ?? 'match3d-agent-session-1';
return {
sessionId,
currentTurn: 0,
progressPercent: 20,
stage: 'collecting',
anchorPack: {
theme: {
key: 'theme',
label: '题材主题',
value: '水果消除',
status: 'confirmed',
},
clearCount: {
key: 'clearCount',
label: '需要消除次数',
value: '4',
status: 'confirmed',
},
difficulty: {
key: 'difficulty',
label: '难度',
value: '5',
status: 'confirmed',
},
},
config: {
themeText: '水果消除',
referenceImageSrc: null,
clearCount: 4,
difficulty: 5,
},
draft: null,
messages: [
{
id: 'match3d-message-1',
role: 'assistant',
kind: 'chat',
text: '我们先确定抓大鹅题材、消除次数和难度。',
createdAt: '2026-05-01T10:00:00.000Z',
},
],
lastAssistantReply: '我们先确定抓大鹅题材、消除次数和难度。',
publishedProfileId: null,
updatedAt: '2026-05-01T10:00:00.000Z',
...overrides,
};
}
function buildMockRpgGalleryDetail(
entry: CustomWorldGalleryCard,
): CustomWorldLibraryEntry {
@@ -2500,6 +2560,38 @@ test('puzzle creation timeout exits busy state and shows a readable error', asyn
expect(screen.queryByText(//u)).toBeNull();
});
test('match3d creation card opens workspace even when public galleries fail', async () => {
const user = userEvent.setup();
const match3dSession = buildMockMatch3DAgentSession();
vi.mocked(listRpgEntryWorldGallery).mockRejectedValueOnce(
new Error('读取作品广场失败'),
);
vi.mocked(listMatch3DGallery).mockRejectedValueOnce(
new Error('读取抓大鹅广场失败'),
);
vi.mocked(match3dCreationClient.createSession).mockResolvedValueOnce({
session: match3dSession,
});
render(<TestWrapper withAuth />);
await openCreationHub(user);
expect(screen.queryByText('读取作品广场失败')).toBeNull();
expect(screen.queryByText('读取抓大鹅广场失败')).toBeNull();
const button = screen.getByRole('button', {
name: /.*/u,
});
expect(button as HTMLButtonElement).toHaveProperty('disabled', false);
await user.click(button);
await waitFor(() => {
expect(match3dCreationClient.createSession).toHaveBeenCalledWith({});
});
expect(await screen.findByText('抓大鹅工作区match3d-agent-session-1')).toBeTruthy();
});
test('puzzle draft card restores the bound agent session and opens the result view', async () => {
const user = userEvent.setup();