From abea7cec1d28a4250dab8905b33788d56ab9740a Mon Sep 17 00:00:00 2001 From: kdletters <61648117+kdletters@users.noreply.github.com> Date: Tue, 26 May 2026 15:57:39 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=B9=B3=E5=8F=B0=E9=94=99=E8=AF=AF?= =?UTF-8?q?=E4=B8=8E=E5=AE=8C=E6=88=90=E5=BC=B9=E7=AA=97=E6=94=B6=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .hermes/shared-memory/decision-log.md | 8 + ...玩法创作】平å°å…¥å£ä¸ŽçŽ©æ³•é“¾è·¯-2026-05-15.md | 2 + .../PlatformEntryFlowShellImpl.tsx | 143 +++++++++++++++++- .../PlatformErrorDialog.test.tsx | 47 ++++++ .../PlatformTaskCompletionDialog.tsx | 124 +++++++++++++++ ...gEntryFlowShell.agent.interaction.test.tsx | 34 ++++- 6 files changed, 347 insertions(+), 11 deletions(-) create mode 100644 src/components/platform-entry/PlatformTaskCompletionDialog.tsx diff --git a/.hermes/shared-memory/decision-log.md b/.hermes/shared-memory/decision-log.md index 070fd6ca..51c774ff 100644 --- a/.hermes/shared-memory/decision-log.md +++ b/.hermes/shared-memory/decision-log.md @@ -24,6 +24,14 @@ - éªŒè¯æ–¹å¼ï¼š`npm run test -- src/components/platform-entry/PlatformErrorDialog.test.tsx src/components/platform-entry/PlatformEntryCreationTypeModal.test.tsx`ã€`npm run typecheck`ã€`npm run check:encoding` 通过;手测时异步失败应弹出包å«â€œé”™è¯¯æ¥æºâ€å’Œâ€œé”™è¯¯å†…容â€çš„弹窗,å¤åˆ¶æŒ‰é’®åº”å¤åˆ¶å®Œæ•´è¯Šæ–­æ–‡æœ¬ã€‚ - å…³è”æ–‡æ¡£ï¼š`docs/ã€çŽ©æ³•åˆ›ä½œã€‘å¹³å°å…¥å£ä¸ŽçŽ©æ³•é“¾è·¯-2026-05-15.md`。 +## 2026-05-26 生æˆä»»åŠ¡å®Œæˆåœ¨ç¦»å¼€ç”Ÿæˆé¡µåŽå¼¹ç‹¬ç«‹å®Œæˆå¼¹çª— + +- èƒŒæ™¯ï¼šæŠ“å¤§é¹…ã€æ‹¼å›¾ç­‰ç”Ÿæˆä»»åŠ¡å®Œæˆæ—¶ï¼Œç”¨æˆ·å¦‚果已ç»ç¦»å¼€ç”Ÿæˆé¡µï¼Œè‰ç¨¿é¡µçš„æœªè¯»çº¢ç‚¹ä¸è¶³ä»¥è¡¨è¾¾â€œè¿™æ¬¡ç”Ÿæˆå·²å®Œæˆâ€ï¼›ä½†å¦‚果用户ä»åœç•™åœ¨ç”Ÿæˆé¡µï¼Œç»“果页或试玩页本身就是完æˆå馈,ä¸éœ€è¦å†å ä¸€ä¸ªæˆåŠŸæç¤ºã€‚ +- 决策:平å°å£³å±‚在 `markDraftReady(..., viewedImmediately=false)` æ—¶é¢å¤–弹出 `PlatformTaskCompletionDialog`,完æˆå¼¹çª—å¿…é¡»å¸¦æ¥æºå’Œå¤åˆ¶æŒ‰é’®ï¼›å¦‚æžœ `viewedImmediately=true`,åªä¿ç•™ç»“果页 / 试玩页本身的完æˆå馈和è‰ç¨¿æœªè¯»æ€ï¼Œä¸é‡å¤å¼¹çª—。 +- å½±å“范围:`src/components/platform-entry/PlatformEntryFlowShellImpl.tsx`ã€`src/components/platform-entry/PlatformTaskCompletionDialog.tsx`ã€`src/components/platform-entry/PlatformErrorDialog.test.tsx`ã€`src/components/rpg-entry/RpgEntryFlowShell.agent.interaction.test.tsx`ã€`docs/ã€çŽ©æ³•åˆ›ä½œã€‘å¹³å°å…¥å£ä¸ŽçŽ©æ³•é“¾è·¯-2026-05-15.md`。 +- éªŒè¯æ–¹å¼ï¼š`npm run test -- src/components/platform-entry/PlatformErrorDialog.test.tsx`ã€`npm run test -- src/components/rpg-entry/RpgEntryFlowShell.agent.interaction.test.tsx -t "completed match3d draft"` 通过åŽï¼Œç¦»å¼€ç”Ÿæˆé¡µå†å®Œæˆçš„è‰ç¨¿åº”出现“生æˆå®Œæˆâ€å¼¹çª—,且å¤åˆ¶å†…å®¹åŒ…å«æ¥æºä¸Žçжæ€ã€‚ +- å…³è”æ–‡æ¡£ï¼š`docs/ã€çŽ©æ³•åˆ›ä½œã€‘å¹³å°å…¥å£ä¸ŽçŽ©æ³•é“¾è·¯-2026-05-15.md`。 + ## 2026-05-26 “我的â€é¡µä»»åŠ¡å¡è¯»åŽç«¯ä»»åŠ¡æ‘˜è¦å¹¶ç§»é™¤å¸¸é©»å¡«é‚€è¯·ç å…¥å£ - 背景:移动端“我的â€é¡µæ¯æ—¥ä»»åС塿›¾ç¡¬ç¼–ç  `0 / 1`,任务领å–完æˆåŽåªåˆ·æ–°å¼¹çª—内任务中心,å¡ç‰‡æœ¬èº«ä¸æ›´æ–°ï¼›é¡µé¢åº•部还ä¿ç•™æ—§çš„“填邀请ç â€æ¬¡çº§æŒ‰é’®ï¼Œå’Œå½“å‰äº”项常用功能宫格å£å¾„é‡å¤ã€‚ diff --git a/docs/ã€çŽ©æ³•åˆ›ä½œã€‘å¹³å°å…¥å£ä¸ŽçŽ©æ³•é“¾è·¯-2026-05-15.md b/docs/ã€çŽ©æ³•åˆ›ä½œã€‘å¹³å°å…¥å£ä¸ŽçŽ©æ³•é“¾è·¯-2026-05-15.md index 600e0327..9899a199 100644 --- a/docs/ã€çŽ©æ³•åˆ›ä½œã€‘å¹³å°å…¥å£ä¸ŽçŽ©æ³•é“¾è·¯-2026-05-15.md +++ b/docs/ã€çŽ©æ³•åˆ›ä½œã€‘å¹³å°å…¥å£ä¸ŽçŽ©æ³•é“¾è·¯-2026-05-15.md @@ -14,6 +14,8 @@ å¹³å°å…¥å£ã€ç”Ÿæˆé¡µã€ç»“果页ã€ä½œå“详情ã€ä½œå“æž¶å’Œè¿è¡Œæ€çš„è·¨æµç¨‹é”™è¯¯ç»Ÿä¸€æ”¶å£åˆ° `PlatformErrorDialog`ã€‚å¼¹çª—å¿…é¡»å¸¦æ˜Žç¡®é”™è¯¯æ¥æºï¼Œä¾‹å¦‚æŸä¸ªè‰ç¨¿ã€æŸæ¬¡ç”Ÿæˆã€ä½œå“详情或æŸä¸ªæ¸¸çŽ©å®žä¾‹ï¼Œå¹¶æä¾›å¤åˆ¶æŒ‰é’®å¤åˆ¶â€œé”™è¯¯æ¥æº + 错误内容â€ã€‚页é¢å†…ä¸å†é‡å¤æ¸²æŸ“裸错误 bannerï¼›è¡¨å•æ ¡éªŒã€å‘布确认弹窗里的局部业务错误å¯ä»¥ä¿ç•™åœ¨åŽŸå¼¹çª—å†…ã€‚ +生æˆä»»åŠ¡åœ¨ç”¨æˆ·ç¦»å¼€ç”Ÿæˆé¡µåŽå¼‚æ­¥å®Œæˆæ—¶ï¼Œå¹³å°å£³å±‚必须弹出 `PlatformTaskCompletionDialog`。完æˆå¼¹çª—åŒæ ·è¦å¸¦æ¥æºï¼Œä¾‹å¦‚æŸä¸ªè‰ç¨¿æˆ–生æˆä¼šè¯ï¼Œå¹¶æä¾›å¤åˆ¶æŒ‰é’®å¤åˆ¶â€œæ¥æº + 状æ€â€ï¼›å¦‚果用户ä»åœç•™åœ¨ç”Ÿæˆé¡µå¹¶è¢«è‡ªåŠ¨å¸¦å…¥ç»“æžœé¡µæˆ–è¯•çŽ©é¡µï¼Œç”Ÿæˆé¡µ / 结果页本身å³ä¸ºå®Œæˆå馈,ä¸å†é¢å¤–å åŠ å®Œæˆå¼¹çª—。 + `PlatformEntryFlowShellImpl.tsx` 仿˜¯å¹³å°å…¥å£ç¼–排壳,åŽç»­ç»´æŠ¤æ—¶åº”优先把独立 UI 片段ã€å…¬å¼€ä½œå“映射ã€è‰ç¨¿ç”Ÿæˆ notice å’Œè¿è¡Œæ€çŠ¶æ€ helper 拆到 `src/components/platform-entry/PlatformEntryFlowShellImpl/` 或åŒç›®å½•ç´§é‚» helper 文件。拆分åªå…è®¸æ”¹å˜æ–‡ä»¶ç»„ç»‡ï¼Œä¸æ”¹å˜å…¥å£é…置事实æºã€é»˜è®¤å¯¼å‡ºã€propsã€é¡µé¢é˜¶æ®µã€UI 文案或现有交互;其中拼图首访 onboarding 已拆为 `PlatformEntryFlowShellImpl/PuzzleOnboardingView.tsx`。 `platformEntryCreationTypes.ts` åªåšå‰ç«¯å±•示派生,分组时必须把åŽç«¯ `creationTypes` 里的 `categoryId` / `categoryLabel` 当作å¯ç¼ºå¤±å­—段处ç†ï¼Œç©ºå€¼ç»Ÿä¸€å›žé€€åˆ° `recent` / `最近创作`,é¿å…æ—§æ•°æ®ã€å±€éƒ¨ mock 或异常返回把创作入å£åˆå§‹åŒ–直接打崩。 diff --git a/src/components/platform-entry/PlatformEntryFlowShellImpl.tsx b/src/components/platform-entry/PlatformEntryFlowShellImpl.tsx index a74239f8..19c1fecd 100644 --- a/src/components/platform-entry/PlatformEntryFlowShellImpl.tsx +++ b/src/components/platform-entry/PlatformEntryFlowShellImpl.tsx @@ -429,6 +429,10 @@ import { PlatformErrorDialog, type PlatformErrorDialogPayload, } from './PlatformErrorDialog'; +import { + PlatformTaskCompletionDialog, + type PlatformTaskCompletionDialogPayload, +} from './PlatformTaskCompletionDialog'; import { PlatformFeedbackView } from './PlatformFeedbackView'; import { PlatformWorkDetailView } from './PlatformWorkDetailView'; import { usePlatformCreationAgentFlowController } from './usePlatformCreationAgentFlowController'; @@ -444,6 +448,7 @@ type DraftGenerationNoticeStatus = 'generating' | 'ready'; type DraftGenerationNotice = { status: DraftGenerationNoticeStatus; seen: boolean; + completedAtMs?: number; }; type DraftGenerationNoticeMap = Record; type CreationWorkShelfKind = CreationWorkShelfItem['kind']; @@ -2027,12 +2032,74 @@ function formatPlatformErrorSource(label: string, id?: string | null) { return normalizedId ? `${label} ${normalizedId}` : label; } +function formatPlatformTaskCompletionSource(label: string, id?: string | null) { + const normalizedId = id?.trim(); + return normalizedId ? `${label} ${normalizedId}` : label; +} + function buildPlatformErrorDialogDismissKey( error: (PlatformErrorDialogPayload & { key: string }) | null, ) { return error ? `${error.key}:${error.source}:${error.message}` : null; } +function buildPlatformTaskCompletionDialogDismissKey( + completion: + | (PlatformTaskCompletionDialogPayload & { + key: string; + completedAtMs: number | null; + }) + | null, +) { + return completion + ? `${completion.key}:${completion.source}:${completion.message}:${completion.completedAtMs ?? 0}` + : null; +} + +function pickDraftCompletionDialogSourceId( + ids: Array, +) { + const normalizedIds = ids + .map((id) => id?.trim() ?? '') + .filter((id) => Boolean(id)); + return ( + normalizedIds.find((id) => /session/i.test(id)) ?? + normalizedIds.find((id) => /work/i.test(id)) ?? + normalizedIds.find((id) => /draft/i.test(id)) ?? + normalizedIds.find((id) => /run/i.test(id)) ?? + normalizedIds.find((id) => /profile/i.test(id)) ?? + normalizedIds[0] ?? + null + ); +} + +function buildDraftCompletionDialogSource( + kind: CreationWorkShelfKind, + ids: Array, +) { + const sourceId = pickDraftCompletionDialogSourceId(ids); + switch (kind) { + case 'rpg': + return formatPlatformTaskCompletionSource('RPG è‰ç¨¿', sourceId); + case 'big-fish': + return formatPlatformTaskCompletionSource('大鱼åƒå°é±¼è‰ç¨¿', sourceId); + case 'match3d': + return formatPlatformTaskCompletionSource('抓大鹅è‰ç¨¿', sourceId); + case 'square-hole': + return formatPlatformTaskCompletionSource('方洞挑战è‰ç¨¿', sourceId); + case 'jump-hop': + return formatPlatformTaskCompletionSource('跳一跳è‰ç¨¿', sourceId); + case 'puzzle': + return formatPlatformTaskCompletionSource('拼图è‰ç¨¿', sourceId); + case 'visual-novel': + return formatPlatformTaskCompletionSource('视觉å°è¯´è‰ç¨¿', sourceId); + case 'bark-battle': + return formatPlatformTaskCompletionSource('汪汪声浪è‰ç¨¿', sourceId); + case 'baby-object-match': + return formatPlatformTaskCompletionSource('å®è´è¯†ç‰©è‰ç¨¿', sourceId); + } +} + function createMiniGameDraftGenerationStateForRestoredDraft( kind: MiniGameDraftGenerationKind, metadata?: MiniGameDraftGenerationState['metadata'], @@ -3327,6 +3394,16 @@ export function PlatformEntryFlowShellImpl({ useState({}); const [pendingDraftShelfItems, setPendingDraftShelfItems] = useState({}); + const [ + pendingPlatformTaskCompletionDialog, + setPendingPlatformTaskCompletionDialog, + ] = useState< + | (PlatformTaskCompletionDialogPayload & { + key: string; + completedAtMs: number | null; + }) + | null + >(null); const [initialCreationUrlState] = useState(() => readCreationUrlState()); const handledInitialCreationUrlStateRef = useRef(false); const [initialPuzzleRuntimeUrlState] = useState(() => @@ -3404,10 +3481,14 @@ export function PlatformEntryFlowShellImpl({ return; } + const completedAtMs = status === 'ready' ? Date.now() : undefined; setDraftGenerationNotices((current) => { const next = { ...current }; for (const key of uniqueKeys) { - next[key] = { status, seen }; + next[key] = + completedAtMs === undefined + ? { status, seen } + : { status, seen, completedAtMs }; } return next; }); @@ -3449,12 +3530,13 @@ export function PlatformEntryFlowShellImpl({ ); const markDraftGenerating = useCallback( (kind: CreationWorkShelfKind, ids: Array) => { + setPendingPlatformTaskCompletionDialog(null); updateDraftGenerationNotices( collectDraftNoticeKeys(kind, ids), 'generating', ); }, - [updateDraftGenerationNotices], + [setPendingPlatformTaskCompletionDialog, updateDraftGenerationNotices], ); const markDraftReady = useCallback( ( @@ -3467,17 +3549,27 @@ export function PlatformEntryFlowShellImpl({ 'ready', viewedImmediately, ); + if (!viewedImmediately) { + const completedAtMs = Date.now(); + setPendingPlatformTaskCompletionDialog({ + key: `${kind}:${collectDraftNoticeKeys(kind, ids).join('|')}:${completedAtMs}`, + source: buildDraftCompletionDialogSource(kind, ids), + message: '生æˆä»»åŠ¡å·²å®Œæˆï¼Œå¯ä»¥ç»§ç»­æŸ¥çœ‹è‰ç¨¿ã€‚', + completedAtMs, + }); + } }, - [updateDraftGenerationNotices], + [setPendingPlatformTaskCompletionDialog, updateDraftGenerationNotices], ); const markPendingDraftGenerating = useCallback( ( kind: Exclude, id: string | null | undefined, ) => { + setPendingPlatformTaskCompletionDialog(null); updatePendingDraftShelfItem(kind, id, 'generating'); }, - [updatePendingDraftShelfItem], + [setPendingPlatformTaskCompletionDialog, updatePendingDraftShelfItem], ); const markPendingDraftReady = useCallback( ( @@ -5790,6 +5882,10 @@ export function PlatformEntryFlowShellImpl({ ); const [dismissedPlatformErrorDialogKey, setDismissedPlatformErrorDialogKey] = useState(null); + const [ + dismissedPlatformTaskCompletionDialogKey, + setDismissedPlatformTaskCompletionDialogKey, + ] = useState(null); const currentPlatformErrorDialog = useMemo< (PlatformErrorDialogPayload & { key: string }) | null >(() => { @@ -6013,6 +6109,25 @@ export function PlatformEntryFlowShellImpl({ woodenFishRun?.runId, woodenFishSession?.sessionId, ]); + const currentPlatformTaskCompletionDialog = useMemo< + | (PlatformTaskCompletionDialogPayload & { + key: string; + completedAtMs: number | null; + }) + | null + >(() => pendingPlatformTaskCompletionDialog, [ + pendingPlatformTaskCompletionDialog, + ]); + const activePlatformTaskCompletionDialogDismissKey = + buildPlatformTaskCompletionDialogDismissKey( + currentPlatformTaskCompletionDialog, + ); + const activePlatformTaskCompletionDialog = + activePlatformTaskCompletionDialogDismissKey && + activePlatformTaskCompletionDialogDismissKey === + dismissedPlatformTaskCompletionDialogKey + ? null + : currentPlatformTaskCompletionDialog; const activePlatformErrorDialogDismissKey = buildPlatformErrorDialogDismissKey(currentPlatformErrorDialog); const activePlatformErrorDialog = @@ -6118,6 +6233,19 @@ export function PlatformEntryFlowShellImpl({ setSquareHoleError, setVisualNovelError, ]); + const closePlatformTaskCompletionDialog = useCallback(() => { + if (!currentPlatformTaskCompletionDialog) { + return; + } + + const dismissKey = buildPlatformTaskCompletionDialogDismissKey( + currentPlatformTaskCompletionDialog, + ); + if (dismissKey) { + setDismissedPlatformTaskCompletionDialogKey(dismissKey); + } + setPendingPlatformTaskCompletionDialog(null); + }, [currentPlatformTaskCompletionDialog]); const shouldPollPuzzleGenerationSession = selectionStage === 'puzzle-generating' && activePuzzleGenerationSessionId != null && @@ -7116,6 +7244,7 @@ export function PlatformEntryFlowShellImpl({ setIsProfilePlayStatsOpen(false); setDraftGenerationNotices({}); setPendingDraftShelfItems({}); + setPendingPlatformTaskCompletionDialog(null); resetRpgSessionViewState(); setRpgGeneratedCustomWorldProfile(null); setRpgCustomWorldError(null); @@ -16871,6 +17000,12 @@ export function PlatformEntryFlowShellImpl({ overlayClassName={`platform-theme ${platformThemeClass} !items-center`} panelClassName="platform-remap-surface rounded-[1.5rem]" /> + ({ copyTextToClipboard: vi.fn(), @@ -58,3 +59,49 @@ describe('PlatformErrorDialog', () => { expect(screen.queryByRole('dialog', { name: 'å‘生错误' })).toBeNull(); }); }); + +describe('PlatformTaskCompletionDialog', () => { + test('shows source, message, and copies the full completion report', async () => { + vi.mocked(clipboardService.copyTextToClipboard).mockResolvedValue(true); + + render( + {}} + />, + ); + + const dialog = screen.getByRole('dialog', { name: '生æˆå®Œæˆ' }); + expect( + within(dialog).getByText('抓大鹅è‰ç¨¿ match3d-notice-session-1'), + ).toBeTruthy(); + expect( + within(dialog).getByText('生æˆä»»åŠ¡å·²å®Œæˆï¼Œå¯ä»¥ç»§ç»­æŸ¥çœ‹è‰ç¨¿ã€‚'), + ).toBeTruthy(); + + fireEvent.click(within(dialog).getByRole('button', { name: 'å¤åˆ¶å†…容' })); + + expect(clipboardService.copyTextToClipboard).toHaveBeenCalledWith( + [ + 'æ¥æºï¼šæŠ“大鹅è‰ç¨¿ match3d-notice-session-1', + '状æ€ï¼šç”Ÿæˆä»»åŠ¡å·²å®Œæˆï¼Œå¯ä»¥ç»§ç»­æŸ¥çœ‹è‰ç¨¿ã€‚', + ].join('\n'), + ); + await waitFor(() => { + expect( + within(dialog).getByRole('button', { name: 'å·²å¤åˆ¶' }), + ).toBeTruthy(); + }); + }); + + test('does not render when there is no active completion', () => { + render( + {}} />, + ); + + expect(screen.queryByRole('dialog', { name: '生æˆå®Œæˆ' })).toBeNull(); + }); +}); diff --git a/src/components/platform-entry/PlatformTaskCompletionDialog.tsx b/src/components/platform-entry/PlatformTaskCompletionDialog.tsx new file mode 100644 index 00000000..66513dd9 --- /dev/null +++ b/src/components/platform-entry/PlatformTaskCompletionDialog.tsx @@ -0,0 +1,124 @@ +import { CheckCircle2, Copy } from 'lucide-react'; +import { useEffect, useMemo, useRef, useState } from 'react'; + +import { copyTextToClipboard } from '../../services/clipboard'; +import { UnifiedModal } from '../common/UnifiedModal'; + +export type PlatformTaskCompletionDialogPayload = { + source: string; + message: string; +}; + +type PlatformTaskCompletionDialogProps = { + completion: PlatformTaskCompletionDialogPayload | null; + onClose: () => void; + overlayClassName?: string; + panelClassName?: string; +}; + +function buildPlatformTaskCompletionReport( + completion: PlatformTaskCompletionDialogPayload, +) { + return [`æ¥æºï¼š${completion.source}`, `状æ€ï¼š${completion.message}`].join( + '\n', + ); +} + +export function PlatformTaskCompletionDialog({ + completion, + onClose, + overlayClassName = 'platform-theme platform-theme--light !items-center', + panelClassName = 'platform-remap-surface rounded-[1.5rem]', +}: PlatformTaskCompletionDialogProps) { + const [copyState, setCopyState] = useState<'idle' | 'copied' | 'failed'>( + 'idle', + ); + const resetTimerRef = useRef(null); + const reportText = useMemo( + () => (completion ? buildPlatformTaskCompletionReport(completion) : ''), + [completion], + ); + + useEffect( + () => () => { + if (resetTimerRef.current !== null) { + window.clearTimeout(resetTimerRef.current); + } + }, + [], + ); + + useEffect(() => { + setCopyState('idle'); + }, [completion?.source, completion?.message]); + + const copyCompletion = () => { + if (!reportText) { + return; + } + + void copyTextToClipboard(reportText).then((copied) => { + setCopyState(copied ? 'copied' : 'failed'); + if (resetTimerRef.current !== null) { + window.clearTimeout(resetTimerRef.current); + } + resetTimerRef.current = window.setTimeout(() => { + resetTimerRef.current = null; + setCopyState('idle'); + }, 1400); + }); + }; + + return ( + + {copyState === 'copied' ? ( + + ) : ( + + )} + {copyState === 'copied' + ? 'å·²å¤åˆ¶' + : copyState === 'failed' + ? 'å¤åˆ¶å¤±è´¥' + : 'å¤åˆ¶å†…容'} + + } + > + {completion ? ( + <> +
+
+ æ¥æº +
+
+ {completion.source} +
+
+
+
+ çŠ¶æ€ +
+
+ {completion.message} +
+
+ + ) : null} +
+ ); +} diff --git a/src/components/rpg-entry/RpgEntryFlowShell.agent.interaction.test.tsx b/src/components/rpg-entry/RpgEntryFlowShell.agent.interaction.test.tsx index baf9807c..d6941800 100644 --- a/src/components/rpg-entry/RpgEntryFlowShell.agent.interaction.test.tsx +++ b/src/components/rpg-entry/RpgEntryFlowShell.agent.interaction.test.tsx @@ -3757,7 +3757,7 @@ test('running match3d form generation can return to draft tab and reopen progres render(); await openCreateTemplateHub(user); - await user.click(screen.getByRole('tab', { name: '抓大鹅' })); + await user.click(await findCreationTypeButton('抓大鹅')); await user.click( await screen.findByRole('button', { name: 'ç”ŸæˆæŠ“å¤§é¹…è‰ç¨¿' }), ); @@ -3841,7 +3841,7 @@ test('running match3d persisted draft reopens progress instead of unfinished res render(); await openCreateTemplateHub(user); - await user.click(screen.getByRole('tab', { name: '抓大鹅' })); + await user.click(await findCreationTypeButton('抓大鹅')); await user.click( await screen.findByRole('button', { name: 'ç”ŸæˆæŠ“å¤§é¹…è‰ç¨¿' }), ); @@ -4038,7 +4038,7 @@ test('running match3d form generation keeps other creation templates available', render(); await openCreateTemplateHub(user); - await user.click(screen.getByRole('tab', { name: '抓大鹅' })); + await user.click(await findCreationTypeButton('抓大鹅')); await user.click( await screen.findByRole('button', { name: 'ç”ŸæˆæŠ“å¤§é¹…è‰ç¨¿' }), ); @@ -4107,7 +4107,7 @@ test('running match3d form generation keeps same template generation available', render(); await openCreateTemplateHub(user); - await user.click(screen.getByRole('tab', { name: '抓大鹅' })); + await user.click(await findCreationTypeButton('抓大鹅')); await user.click( await screen.findByRole('button', { name: 'ç”ŸæˆæŠ“å¤§é¹…è‰ç¨¿' }), ); @@ -4721,7 +4721,7 @@ test('match3d draft generation auto starts trial and runtime back opens draft re render(); await openCreateTemplateHub(user); - await user.click(screen.getByRole('tab', { name: '抓大鹅' })); + await user.click(await findCreationTypeButton('抓大鹅')); await user.click( await screen.findByRole('button', { name: 'ç”ŸæˆæŠ“å¤§é¹…è‰ç¨¿' }), ); @@ -4953,11 +4953,15 @@ test('completed match3d draft notice first opens trial then reopens result', asy render(); await openCreateTemplateHub(user); - await user.click(screen.getByRole('tab', { name: '抓大鹅' })); + await user.click(await findCreationTypeButton('抓大鹅')); await user.click( await screen.findByRole('button', { name: 'ç”ŸæˆæŠ“å¤§é¹…è‰ç¨¿' }), ); - expect(await screen.findByText('抓大鹅è‰ç¨¿ç”Ÿæˆè¿›åº¦')).toBeTruthy(); + expect( + await screen.findByRole('progressbar', { + name: '抓大鹅è‰ç¨¿ç”Ÿæˆè¿›åº¦', + }), + ).toBeTruthy(); await user.click(screen.getByRole('button', { name: '返回创作中心' })); await openDraftHub(user); await expectDraftHubGeneratingBadgeCountAtLeast(1); @@ -4966,6 +4970,22 @@ test('completed match3d draft notice first opens trial then reopens result', asy resolveCompile({ session: generatedSession }); }); + const completionDialog = await screen.findByRole('dialog', { + name: '生æˆå®Œæˆ', + }); + expect( + within(completionDialog).getByText( + /抓大鹅è‰ç¨¿ match3d-notice-session-1/u, + ), + ).toBeTruthy(); + expect( + within(completionDialog).getByText(/生æˆä»»åŠ¡å·²å®Œæˆ/u), + ).toBeTruthy(); + expect( + within(completionDialog).getByRole('button', { name: 'å¤åˆ¶å†…容' }), + ).toBeTruthy(); + await user.click(within(completionDialog).getByLabelText('关闭')); + expect(await screen.findByLabelText('新生æˆå®Œæˆ')).toBeTruthy(); await user.click( await screen.findByRole('button', {