From 6fcf42e4ac8c49762a3cc369ad526ea7d76d87b4 Mon Sep 17 00:00:00 2001 From: Suzumiya Date: Thu, 17 Sep 2026 19:44:48 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=20appSurface=20=E7=94=9F=E6=88=90?= =?UTF-8?q?=E4=BB=BB=E5=8A=A1=E7=94=A8=E4=BE=8B=E7=9A=84=E5=BC=82=E6=AD=A5?= =?UTF-8?q?=E6=8E=92=E7=A9=BA=EF=BC=9A=E7=AD=89=E9=98=B6=E6=AE=B5=E5=90=88?= =?UTF-8?q?=E5=B9=B6=E3=80=81=E7=AD=89=E8=BD=AE=E8=AF=A2=E9=80=80=E5=87=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 阶段文案与徽标改用 waitFor:本地队列的「排队中。」先于后端记录合并,同步断言在整套连跑时抢跑 - 用例收尾连等两个 poll 周期(2s)并断言账本读计数不再增长,确认这条轮询链在本用例内退出 - 留在线上的轮询醒来会打进下一个用例的 spy(宿主按调用时读 __TAURI__),故排空放在用例内,未动全局 harness - 未改生产:后台任务跨面板保活保持原样 --- .../appSurface/project-development.suite.ts | 33 +++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) diff --git a/apps/ai-game-creator-shell/tests/appSurface/project-development.suite.ts b/apps/ai-game-creator-shell/tests/appSurface/project-development.suite.ts index 3e061dba9..f05b625e9 100644 --- a/apps/ai-game-creator-shell/tests/appSurface/project-development.suite.ts +++ b/apps/ai-game-creator-shell/tests/appSurface/project-development.suite.ts @@ -11831,8 +11831,15 @@ export function registerProjectAgentStatusTests() { // 2) 面板关掉之后任务仍在「生成任务」面板里,阶段文案来自后端记录。 const taskPanel = await screen.findByRole('region', { name: '生成任务' }); expect(within(taskPanel).getByText('第一条设计图')).not.toBeNull(); - expect(within(taskPanel).getByText('正在生成。')).not.toBeNull(); - expect(within(taskPanel).getByText('生成中')).not.toBeNull(); + /** + * 阶段文案与徽标要**等**后端记录并进来:刚提交时任务还停在本地队列的「排队中。」, + * 记录合并发生在第一轮账本轮询(间隔 2s)之后。同步断言在这里读到的会是本地阶段, + * 在整套连跑时必然抢跑(隔离单跑时那一拍刚好落在窗口内,所以只在全量里红)。 + */ + await waitFor(() => { + expect(within(taskPanel).getByText('正在生成。')).not.toBeNull(); + expect(within(taskPanel).getByText('生成中')).not.toBeNull(); + }); // 非模态:没有全屏遮罩、没有 aria-modal。 expect(taskPanel.getAttribute('aria-modal')).toBeNull(); expect(document.querySelector('[aria-modal="true"]')).toBeNull(); @@ -11890,6 +11897,28 @@ export function registerProjectAgentStatusTests() { expect( calls.filter((call) => call.command === 'get_local_game_manifest').length, ).toBeGreaterThanOrEqual(manifestReadsBefore + 2); + + /** + * 5) 等轮询真的退出:两个 mock 任务都已收口 completed,再连等两个 poll 周期 + * (间隔 2s),账本读计数不再增长才算这条异步链跑完。 + * + * 宿主读账本用的是「调用时」的 `window.__TAURI__`,而 afterEach 会把它删掉、下一个用例 + * 再装自己的 mock:留下一条在途/在睡的轮询,下一轮醒来就会打进**下一个用例**的 spy + * (实测就是 `does not open a preview before a local project is initialized` 那条变红, + * 且看到的 projectPath 是本案的)。所以排空必须发生在本用例内部,而不是靠全局 harness 掩盖。 + */ + const ledgerReads = () => + calls.filter( + (call) => call.command === 'list_local_project_asset_generations', + ).length; + await act(async () => { + await new Promise((resolve) => setTimeout(resolve, 2_200)); + }); + const ledgerReadsAfterFirstQuietPeriod = ledgerReads(); + await act(async () => { + await new Promise((resolve) => setTimeout(resolve, 2_200)); + }); + expect(ledgerReads()).toBe(ledgerReadsAfterFirstQuietPeriod); }, 30_000); /**