diff --git a/frontend/tests/chat-navigation-a11y-contract.test.ts b/frontend/tests/chat-navigation-a11y-contract.test.ts index 75b643fa..88820b30 100644 --- a/frontend/tests/chat-navigation-a11y-contract.test.ts +++ b/frontend/tests/chat-navigation-a11y-contract.test.ts @@ -125,10 +125,14 @@ test("the streaming reply announces state transitions, never streamed deltas", ( const pageFile = readFileSync(new URL("../src/app/(app)/page.tsx", import.meta.url), "utf8"); assert.equal(layout.match(/
/g)?.length, 1); assert.doesNotMatch(pageFile, /
/); - assert.match( - pageFile, - /return \(\s*<>\s*\{replyAnnouncement\}<\/span>/, - ); + // 原值: 播报是 return 片段的第一个子节点。 + // 新值: 播报仍在 page.tsx,且在 aria-busy 消息列表之前。当前人物绑定和深链可以排在它前面。 + // 原因: 星盘档案要在首页挂上人物绑定,播报仍在对话页、仍在忙碌列表之外。 + const announcement = '{replyAnnouncement}'; + const announcementAt = pageFile.indexOf(announcement); + const busyListAt = pageFile.indexOf('
'); + assert.ok(announcementAt >= 0, "reply announcement missing from the chat page"); + assert.ok(busyListAt > announcementAt, "reply announcement must stay outside the busy message list"); // Then: the region is fed a phase-derived string, not the streaming text. assert.match(pageSource, /const replyAnnouncement = chatReplyAnnouncement\(replyPhase, activeReplyOutcome\?\.replyOrdinal \?\? 0\)/);