This commit is contained in:
2026-05-10 22:20:54 +08:00
parent d6219f1a0c
commit 192accd796
92 changed files with 7045 additions and 1559 deletions

View File

@@ -0,0 +1,170 @@
/* @vitest-environment jsdom */
import { fireEvent, render, screen } from '@testing-library/react';
import { expect, test, vi } from 'vitest';
import type { Match3DAgentSessionSnapshot } from '../../../packages/shared/src/contracts/match3dAgent';
import { Match3DAgentWorkspace } from './Match3DAgentWorkspace';
const baseSession: Match3DAgentSessionSnapshot = {
sessionId: 'match3d-session-1',
currentTurn: 0,
progressPercent: 0,
stage: 'collecting_config',
anchorPack: {
theme: {
key: 'theme',
label: '题材主题',
value: '水果摊',
status: 'confirmed',
},
clearCount: {
key: 'clearCount',
label: '需要消除次数',
value: '8',
status: 'confirmed',
},
difficulty: {
key: 'difficulty',
label: '难度',
value: '3',
status: 'confirmed',
},
},
config: {
themeText: '水果摊',
referenceImageSrc: null,
clearCount: 8,
difficulty: 3,
assetStyleId: 'low-poly',
assetStyleLabel: '低多边形',
assetStylePrompt:
'块面清晰、轮廓简洁、颜色分区明确的低多边形 3D 素材风格。',
},
draft: null,
messages: [
{
id: 'message-1',
role: 'assistant',
kind: 'chat',
text: '旧会话固定追问不再作为主入口。',
createdAt: '2026-05-10T10:00:00.000Z',
},
],
lastAssistantReply: '旧会话固定追问不再作为主入口。',
publishedProfileId: null,
updatedAt: '2026-05-10T10:00:00.000Z',
};
test('match3d workspace submits derived entry form payload instead of agent chat', () => {
const onCreateFromForm = vi.fn();
const onExecuteAction = vi.fn();
render(
<Match3DAgentWorkspace
session={null}
onBack={() => {}}
onExecuteAction={onExecuteAction}
onCreateFromForm={onCreateFromForm}
/>,
);
expect(screen.getByText('想做个什么玩法?')).toBeTruthy();
expect(screen.getByLabelText('想做一个什么题材的抓大鹅?')).toBeTruthy();
expect(screen.getByText('3D素材风格')).toBeTruthy();
expect(screen.getByRole('button', { name: '黏土手作' })).toBeTruthy();
expect(screen.getByRole('button', { name: '自定义' })).toBeTruthy();
expect(screen.getByText('消耗20光点')).toBeTruthy();
expect(screen.queryByText('参考图')).toBeNull();
expect(screen.queryByLabelText('上传抓大鹅参考图')).toBeNull();
expect(screen.queryByLabelText('需要消除次数')).toBeNull();
expect(screen.queryByLabelText('难度数值')).toBeNull();
expect(screen.queryByText('物品')).toBeNull();
expect(screen.queryByText('旧会话固定追问不再作为主入口。')).toBeNull();
fireEvent.change(screen.getByLabelText('想做一个什么题材的抓大鹅?'), {
target: { value: '赛博水果摊' },
});
fireEvent.click(screen.getByRole('button', { name: '进阶' }));
fireEvent.click(screen.getByRole('button', { name: /稿/u }));
expect(onCreateFromForm).toHaveBeenCalledWith({
seedText: '赛博水果摊题材消除16次难度6',
themeText: '赛博水果摊',
referenceImageSrc: null,
clearCount: 16,
difficulty: 6,
assetStyleId: 'clay-toy',
assetStyleLabel: '黏土手作',
assetStylePrompt: '圆润、哑光、带轻微手捏痕迹的黏土手作 3D 素材风格。',
});
expect(onExecuteAction).not.toHaveBeenCalled();
});
test('match3d workspace supports custom 3d asset style prompt', () => {
const onCreateFromForm = vi.fn();
render(
<Match3DAgentWorkspace
session={null}
onBack={() => {}}
onExecuteAction={() => {}}
onCreateFromForm={onCreateFromForm}
/>,
);
fireEvent.change(screen.getByLabelText('想做一个什么题材的抓大鹅?'), {
target: { value: '海底甜品店' },
});
fireEvent.click(screen.getByRole('button', { name: '自定义' }));
expect(screen.getByRole('dialog', { name: '自定义风格' })).toBeTruthy();
fireEvent.change(screen.getByLabelText('自定义3D素材风格描述'), {
target: { value: '透明果冻材质,边缘有柔和蓝色荧光' },
});
fireEvent.click(screen.getByRole('button', { name: '应用' }));
fireEvent.click(screen.getByRole('button', { name: /稿/u }));
expect(onCreateFromForm).toHaveBeenCalledWith(
expect.objectContaining({
seedText: '海底甜品店题材消除12次难度4',
themeText: '海底甜品店',
clearCount: 12,
difficulty: 4,
assetStyleId: 'custom',
assetStyleLabel: '自定义风格',
assetStylePrompt: '透明果冻材质,边缘有柔和蓝色荧光',
}),
);
});
test('match3d workspace falls back to compile action when restored from the legacy route', () => {
const onExecuteAction = vi.fn();
render(
<Match3DAgentWorkspace
session={baseSession}
onBack={() => {}}
onExecuteAction={onExecuteAction}
/>,
);
expect(
(screen.getByLabelText('想做一个什么题材的抓大鹅?') as HTMLTextAreaElement)
.value,
).toBe('水果摊');
expect(
screen.getByRole('button', { name: '轻松' }).getAttribute('aria-pressed'),
).toBe('true');
expect(
screen.getByRole('button', { name: '低多边形' }).getAttribute(
'aria-pressed',
),
).toBe('true');
fireEvent.click(screen.getByRole('button', { name: /稿/u }));
expect(onExecuteAction).toHaveBeenCalledWith({
action: 'match3d_compile_draft',
});
});