Files
Genarrative/src/components/unified-creation/workspaces/Match3DCreationWorkspace.interaction.test.tsx

218 lines
7.0 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/* @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();
const themeInput = screen.getByLabelText('想做一个什么题材的抓大鹅?');
expect(themeInput).toBeTruthy();
expect(themeInput.className).not.toContain('h-full');
});
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,
});
});