
























@@ -1633,6 +1633,109 @@ describe("chat voice controls", () => {
16331633});
16341634});
163516351636+describe("chat composer IME composition", () => {
1637+it("defers draft sync while IME composition is active", () => {
1638+const onDraftChange = vi.fn();
1639+const onRequestUpdate = vi.fn();
1640+const container = renderChatView({ onDraftChange, onRequestUpdate });
1641+const textarea = requireElement(
1642+container,
1643+".agent-chat__composer-combobox > textarea",
1644+"composer textarea",
1645+) as HTMLTextAreaElement;
1646+1647+textarea.dispatchEvent(new CompositionEvent("compositionstart", { bubbles: true }));
1648+textarea.value = "dangqian";
1649+textarea.dispatchEvent(new InputEvent("input", { bubbles: true, isComposing: true }));
1650+1651+expect(onDraftChange).not.toHaveBeenCalled();
1652+expect(onRequestUpdate).not.toHaveBeenCalled();
1653+1654+textarea.value = "当前";
1655+textarea.dispatchEvent(new CompositionEvent("compositionend", { bubbles: true }));
1656+1657+expect(onDraftChange).toHaveBeenCalledTimes(1);
1658+expect(onDraftChange).toHaveBeenLastCalledWith("当前");
1659+});
1660+1661+it("preserves composing text across host rerenders with stale draft props", () => {
1662+const onDraftChange = vi.fn();
1663+const onRequestUpdate = vi.fn();
1664+const container = document.createElement("div");
1665+const props = createChatProps({ draft: "", onDraftChange, onRequestUpdate });
1666+1667+render(renderChat(props), container);
1668+const textarea = requireElement(
1669+container,
1670+".agent-chat__composer-combobox > textarea",
1671+"composer textarea",
1672+) as HTMLTextAreaElement;
1673+1674+textarea.dispatchEvent(new CompositionEvent("compositionstart", { bubbles: true }));
1675+textarea.value = "dangqian";
1676+textarea.dispatchEvent(new InputEvent("input", { bubbles: true, isComposing: true }));
1677+1678+expect(onDraftChange).not.toHaveBeenCalled();
1679+expect(onRequestUpdate).not.toHaveBeenCalled();
1680+1681+render(renderChat({ ...props, draft: "" }), container);
1682+1683+expect(container.querySelector<HTMLTextAreaElement>("textarea")?.value).toBe("dangqian");
1684+1685+const rerenderedTextarea = requireElement(
1686+container,
1687+".agent-chat__composer-combobox > textarea",
1688+"composer textarea",
1689+) as HTMLTextAreaElement;
1690+rerenderedTextarea.value = "当前";
1691+rerenderedTextarea.dispatchEvent(new CompositionEvent("compositionend", { bubbles: true }));
1692+1693+expect(onDraftChange).toHaveBeenCalledTimes(1);
1694+expect(onDraftChange).toHaveBeenLastCalledWith("当前");
1695+});
1696+1697+it("leaves keyboard events to the browser while IME composition is active", () => {
1698+const onHistoryKeydown = vi.fn(() => ({
1699+handled: true,
1700+preventDefault: true,
1701+restoreCaret: null,
1702+decision: "handled:history-up" as const,
1703+historyNavigationActiveBefore: false,
1704+historyNavigationActiveAfter: false,
1705+selectionStart: 0,
1706+selectionEnd: 0,
1707+valueLength: 0,
1708+}));
1709+const onSend = vi.fn();
1710+const container = renderChatView({ onHistoryKeydown, onSend });
1711+const textarea = requireElement(
1712+container,
1713+".agent-chat__composer-combobox > textarea",
1714+"composer textarea",
1715+) as HTMLTextAreaElement;
1716+1717+textarea.dispatchEvent(new CompositionEvent("compositionstart", { bubbles: true }));
1718+textarea.value = "dangqian";
1719+const enterEvent = new KeyboardEvent("keydown", {
1720+key: "Enter",
1721+bubbles: true,
1722+cancelable: true,
1723+});
1724+const arrowEvent = new KeyboardEvent("keydown", {
1725+key: "ArrowUp",
1726+bubbles: true,
1727+cancelable: true,
1728+});
1729+textarea.dispatchEvent(enterEvent);
1730+textarea.dispatchEvent(arrowEvent);
1731+1732+expect(enterEvent.defaultPrevented).toBe(false);
1733+expect(arrowEvent.defaultPrevented).toBe(false);
1734+expect(onSend).not.toHaveBeenCalled();
1735+expect(onHistoryKeydown).not.toHaveBeenCalled();
1736+});
1737+});
1738+16361739describe("chat slash menu accessibility", () => {
16371740function inputDraft(container: HTMLElement, value: string) {
16381741const textarea = container.querySelector<HTMLTextAreaElement>("textarea");
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。