import assert from "node:assert/strict"; import { readFileSync } from "node:fs"; import test from "node:test"; import { rectificationChatSurface } from "./rectification-chat-surface.ts"; const page = readFileSync(new URL("../src/app/(app)/page.tsx", import.meta.url), "utf8"); // 原值: 读 rectification-agentic-chat.tsx 单文件。新值: rectificationChatSurface(容器 + 拆出的 hook / 参数函数 / 块,见 rectification-chat-surface.ts)。原因: TASK-rectification-code-split-20260926 只搬不改,整文件断言跟着代码走;切片断言另行改为调用函数。 const rectification = rectificationChatSurface; const guide = readFileSync(new URL("../src/components/birth-time-guide-turn.tsx", import.meta.url), "utf8"); function onKeyDownBlock(source: string, marker: string) { const start = source.indexOf(marker); assert.notEqual(start, -1, `missing onKeyDown near ${marker}`); const slice = source.slice(start, start + 600); const handler = slice.match(/onKeyDown=\{\(event\) => \{[\s\S]*?\n\s*\}\}/) ?? slice.match(/function handleComposerKeyDown[\s\S]*?\n \}/); assert.ok(handler, `could not isolate onKeyDown from ${marker}`); return handler[0]; } test("all three composers ignore Enter while an IME is composing", () => { const main = page.slice( page.indexOf("function handleComposerKeyDown"), page.indexOf("\n\n if (!hydrated"), ); const rectificationHandler = onKeyDownBlock(rectification, "onKeyDown={(event) => {"); const guideHandler = onKeyDownBlock(guide, "onKeyDown={(event) => {"); for (const [name, handler] of [ ["main composer", main], ["rectification composer", rectificationHandler], ["birth-time guide", guideHandler], ] as const) { assert.match(handler, /event\.nativeEvent\.isComposing/, `${name} must ignore composing Enter`); } }); test("the guide turn sends with Enter and wraps with Shift+Enter, matching the other two", () => { const handler = onKeyDownBlock(guide, "onKeyDown={(event) => {"); assert.match(handler, /event\.key === "Enter" && !event\.shiftKey/); assert.doesNotMatch(handler, /metaKey \|\| event\.ctrlKey/); assert.match(guide, /Enter 发送,Shift\+Enter 换行/); });