收口统一创作流程一期
This commit is contained in:
@@ -0,0 +1,215 @@
|
||||
/* @vitest-environment jsdom */
|
||||
|
||||
import { fireEvent, render, screen, within } from '@testing-library/react';
|
||||
import { expect, test, vi } from 'vitest';
|
||||
|
||||
import type { Match3DAgentSessionSnapshot } from '../../../../packages/shared/src/contracts/match3dAgent';
|
||||
import { Match3DCreationWorkspace } from './Match3DCreationWorkspace';
|
||||
|
||||
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: 'cel-cartoon',
|
||||
assetStyleLabel: '赛璐璐卡通',
|
||||
assetStylePrompt:
|
||||
'明亮赛璐璐卡通 2D 游戏道具风格,清晰线稿,硬边阴影,饱和配色,轮廓醒目。',
|
||||
generateClickSound: false,
|
||||
},
|
||||
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',
|
||||
};
|
||||
|
||||
function confirmMatch3DPointCost() {
|
||||
const confirmDialog = screen.getByRole('dialog', {
|
||||
name: '确认消耗泥点',
|
||||
});
|
||||
expect(within(confirmDialog).getByText('消耗 10 泥点')).toBeTruthy();
|
||||
fireEvent.click(within(confirmDialog).getByRole('button', { name: '确定' }));
|
||||
}
|
||||
|
||||
test('match3d workspace submits derived entry form payload instead of agent chat', () => {
|
||||
const onCreateFromForm = vi.fn();
|
||||
const onExecuteAction = vi.fn();
|
||||
|
||||
render(
|
||||
<Match3DCreationWorkspace
|
||||
session={null}
|
||||
onBack={() => {}}
|
||||
onExecuteAction={onExecuteAction}
|
||||
onCreateFromForm={onCreateFromForm}
|
||||
/>,
|
||||
);
|
||||
|
||||
expect(screen.getByText('想做个什么玩法?')).toBeTruthy();
|
||||
expect(screen.getByLabelText('想做一个什么题材的抓大鹅?')).toBeTruthy();
|
||||
expect(screen.queryByText('2D素材风格')).toBeNull();
|
||||
expect(screen.queryByRole('button', { name: '扁平图标' })).toBeNull();
|
||||
expect(screen.queryByRole('button', { name: '自定义' })).toBeNull();
|
||||
expect(screen.getByText('消耗10泥点')).toBeTruthy();
|
||||
expect(screen.queryByRole('button', { name: '生成音效' })).toBeNull();
|
||||
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).not.toHaveBeenCalled();
|
||||
confirmMatch3DPointCost();
|
||||
|
||||
expect(onCreateFromForm).toHaveBeenCalledWith({
|
||||
seedText: '赛博水果摊题材,消除16次,难度6',
|
||||
themeText: '赛博水果摊',
|
||||
referenceImageSrc: null,
|
||||
clearCount: 16,
|
||||
difficulty: 6,
|
||||
generateClickSound: false,
|
||||
});
|
||||
expect(onExecuteAction).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
test('match3d workspace can defer visible chrome to the unified creation page', () => {
|
||||
const { container } = render(
|
||||
<Match3DCreationWorkspace
|
||||
session={null}
|
||||
onBack={() => {}}
|
||||
onExecuteAction={() => {}}
|
||||
onCreateFromForm={() => {}}
|
||||
title={null}
|
||||
unifiedChrome
|
||||
/>,
|
||||
);
|
||||
|
||||
const workspace = container.querySelector('.match3d-agent-workspace');
|
||||
expect(workspace?.getAttribute('data-unified-chrome')).toBe('true');
|
||||
expect(workspace?.className).toContain('max-w-none');
|
||||
expect(workspace?.className).not.toContain('h-full');
|
||||
expect(workspace?.className).not.toContain('overflow-hidden');
|
||||
expect(workspace?.className).not.toContain('platform-remap-surface');
|
||||
expect(screen.queryByRole('heading', { name: '想做个什么玩法?' })).toBeNull();
|
||||
expect(screen.getByLabelText('想做一个什么题材的抓大鹅?')).toBeTruthy();
|
||||
});
|
||||
|
||||
test('match3d workspace omits legacy asset style fields from entry payload', () => {
|
||||
const onCreateFromForm = vi.fn();
|
||||
|
||||
render(
|
||||
<Match3DCreationWorkspace
|
||||
session={null}
|
||||
onBack={() => {}}
|
||||
onExecuteAction={() => {}}
|
||||
onCreateFromForm={onCreateFromForm}
|
||||
/>,
|
||||
);
|
||||
|
||||
fireEvent.change(screen.getByLabelText('想做一个什么题材的抓大鹅?'), {
|
||||
target: { value: '复古水果铺' },
|
||||
});
|
||||
fireEvent.click(screen.getByRole('button', { name: /生成抓大鹅草稿/u }));
|
||||
confirmMatch3DPointCost();
|
||||
|
||||
const payload = onCreateFromForm.mock.calls[0]?.[0] ?? {};
|
||||
expect('assetStyleId' in payload).toBe(false);
|
||||
expect('assetStyleLabel' in payload).toBe(false);
|
||||
expect('assetStylePrompt' in payload).toBe(false);
|
||||
});
|
||||
|
||||
test('match3d workspace keeps click sound generation disabled from entry form', () => {
|
||||
const onCreateFromForm = vi.fn();
|
||||
|
||||
render(
|
||||
<Match3DCreationWorkspace
|
||||
session={null}
|
||||
onBack={() => {}}
|
||||
onExecuteAction={() => {}}
|
||||
onCreateFromForm={onCreateFromForm}
|
||||
/>,
|
||||
);
|
||||
|
||||
fireEvent.change(screen.getByLabelText('想做一个什么题材的抓大鹅?'), {
|
||||
target: { value: '海岛甜品' },
|
||||
});
|
||||
fireEvent.click(screen.getByRole('button', { name: /生成抓大鹅草稿/u }));
|
||||
confirmMatch3DPointCost();
|
||||
|
||||
expect(onCreateFromForm).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
themeText: '海岛甜品',
|
||||
generateClickSound: false,
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
test('match3d workspace falls back to compile action when restored from the legacy route', () => {
|
||||
const onExecuteAction = vi.fn();
|
||||
|
||||
render(
|
||||
<Match3DCreationWorkspace
|
||||
session={baseSession}
|
||||
onBack={() => {}}
|
||||
onExecuteAction={onExecuteAction}
|
||||
/>,
|
||||
);
|
||||
|
||||
expect(
|
||||
(screen.getByLabelText('想做一个什么题材的抓大鹅?') as HTMLTextAreaElement)
|
||||
.value,
|
||||
).toBe('水果摊');
|
||||
expect(
|
||||
screen.getByRole('button', { name: '轻松' }).getAttribute('aria-pressed'),
|
||||
).toBe('true');
|
||||
expect(screen.queryByText('2D素材风格')).toBeNull();
|
||||
expect(screen.queryByRole('button', { name: '赛璐璐卡通' })).toBeNull();
|
||||
|
||||
fireEvent.click(screen.getByRole('button', { name: /生成抓大鹅草稿/u }));
|
||||
confirmMatch3DPointCost();
|
||||
|
||||
expect(onExecuteAction).toHaveBeenCalledWith({
|
||||
action: 'match3d_compile_draft',
|
||||
generateClickSound: false,
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user