/* @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( {}} 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( {}} 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( {}} 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, }); });