Files
Genarrative/src/components/puzzle-agent/PuzzleAgentWorkspace.interaction.test.tsx
2026-04-30 17:49:07 +08:00

213 lines
6.1 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 { act, fireEvent, render, screen } from '@testing-library/react';
import { afterEach, beforeEach, expect, test, vi } from 'vitest';
import type { PuzzleAgentSessionSnapshot } from '../../../packages/shared/src/contracts/puzzleAgentSession';
import { PuzzleAgentWorkspace } from './PuzzleAgentWorkspace';
const baseSession: PuzzleAgentSessionSnapshot = {
sessionId: 'puzzle-session-1',
currentTurn: 3,
progressPercent: 62,
stage: 'collecting_anchors',
anchorPack: {
themePromise: {
key: 'themePromise',
label: '题材承诺',
value: '雾港遗迹拼图',
status: 'confirmed',
},
visualSubject: {
key: 'visualSubject',
label: '画面主体',
value: '潮雾中的灯塔与断桥',
status: 'confirmed',
},
visualMood: {
key: 'visualMood',
label: '视觉气质',
value: '',
status: 'missing',
},
compositionHooks: {
key: 'compositionHooks',
label: '拼图记忆点',
value: '',
status: 'missing',
},
tagsAndForbidden: {
key: 'tagsAndForbidden',
label: '标签与禁忌',
value: '',
status: 'missing',
},
},
draft: null,
messages: [
{
id: 'message-1',
role: 'assistant',
kind: 'chat',
text: '旧会话消息不再渲染为聊天入口。',
createdAt: '2026-04-24T10:00:00.000Z',
},
],
lastAssistantReply: '旧会话消息不再渲染为聊天入口。',
publishedProfileId: null,
suggestedActions: [],
resultPreview: null,
updatedAt: '2026-04-24T10:00:00.000Z',
};
beforeEach(() => {
if (!Element.prototype.scrollIntoView) {
Element.prototype.scrollIntoView = () => {};
}
});
afterEach(() => {
vi.useRealTimers();
});
test('puzzle workspace submits the work form instead of agent chat', () => {
const onCreateFromForm = vi.fn();
render(
<PuzzleAgentWorkspace
session={null}
onBack={() => {}}
onSubmitMessage={() => {}}
onExecuteAction={() => {}}
onCreateFromForm={onCreateFromForm}
/>,
);
fireEvent.change(screen.getByLabelText('作品名称'), {
target: { value: '暖灯猫街' },
});
fireEvent.change(screen.getByLabelText('作品描述'), {
target: { value: '一套雨夜猫街主题拼图。' },
});
fireEvent.change(screen.getByLabelText('画面描述'), {
target: { value: '一只猫在雨夜灯牌下回头。' },
});
fireEvent.click(screen.getByRole('button', { name: /稿/u }));
expect(onCreateFromForm).toHaveBeenCalledWith({
seedText: '暖灯猫街',
workTitle: '暖灯猫街',
workDescription: '一套雨夜猫街主题拼图。',
pictureDescription: '一只猫在雨夜灯牌下回头。',
referenceImageSrc: null,
});
expect(screen.queryByRole('button', { name: '补充剩余设定' })).toBeNull();
expect(screen.queryByText('旧会话消息不再渲染为聊天入口。')).toBeNull();
});
test('puzzle workspace falls back to compile action for restored sessions', () => {
const onExecuteAction = vi.fn();
const onCreateFromForm = vi.fn();
render(
<PuzzleAgentWorkspace
session={baseSession}
onBack={() => {}}
onSubmitMessage={() => {}}
onExecuteAction={onExecuteAction}
onCreateFromForm={onCreateFromForm}
/>,
);
fireEvent.click(screen.getByRole('button', { name: /稿/u }));
expect(onCreateFromForm).not.toHaveBeenCalled();
expect(onExecuteAction).toHaveBeenCalledWith({
action: 'compile_puzzle_draft',
promptText: '潮雾中的灯塔与断桥',
workTitle: '雾港遗迹拼图',
workDescription: '雾港遗迹拼图',
pictureDescription: '潮雾中的灯塔与断桥',
referenceImageSrc: null,
candidateCount: 1,
});
});
test('puzzle workspace restores form draft fields and autosaves edits', () => {
vi.useFakeTimers();
const onAutoSaveForm = vi.fn();
const formDraftSession: PuzzleAgentSessionSnapshot = {
...baseSession,
seedText:
'作品名称:旧街拼图\n作品描述旧街雨夜的拼图草稿。\n画面描述旧街灯牌下的猫。',
draft: {
workTitle: '旧街拼图',
workDescription: '旧街雨夜的拼图草稿。',
levelName: '旧街灯牌',
summary: '旧街雨夜的拼图草稿。',
themeTags: ['旧街', '雨夜', '猫'],
forbiddenDirectives: [],
creatorIntent: null,
anchorPack: baseSession.anchorPack,
candidates: [],
selectedCandidateId: null,
coverImageSrc: null,
coverAssetId: null,
generationStatus: 'idle',
levels: [
{
levelId: 'puzzle-level-1',
levelName: '旧街灯牌',
pictureDescription: '旧街灯牌下的猫。',
candidates: [],
selectedCandidateId: null,
coverImageSrc: null,
coverAssetId: null,
generationStatus: 'idle',
},
],
formDraft: {
workTitle: '旧街拼图',
workDescription: '旧街雨夜的拼图草稿。',
pictureDescription: '旧街灯牌下的猫。',
},
},
};
render(
<PuzzleAgentWorkspace
session={formDraftSession}
onBack={() => {}}
onSubmitMessage={() => {}}
onExecuteAction={() => {}}
onAutoSaveForm={onAutoSaveForm}
/>,
);
expect((screen.getByLabelText('作品名称') as HTMLInputElement).value).toBe(
'旧街拼图',
);
expect((screen.getByLabelText('作品描述') as HTMLTextAreaElement).value).toBe(
'旧街雨夜的拼图草稿。',
);
expect((screen.getByLabelText('画面描述') as HTMLTextAreaElement).value).toBe(
'旧街灯牌下的猫。',
);
fireEvent.change(screen.getByLabelText('画面描述'), {
target: { value: '旧街灯牌下的猫和发光雨伞。' },
});
act(() => {
vi.advanceTimersByTime(700);
});
expect(onAutoSaveForm).toHaveBeenCalledWith({
seedText: '旧街拼图',
workTitle: '旧街拼图',
workDescription: '旧街雨夜的拼图草稿。',
pictureDescription: '旧街灯牌下的猫和发光雨伞。',
referenceImageSrc: null,
});
});