From e979f51ea5bd53951a0d10dbe1d5725fc1d37dc6 Mon Sep 17 00:00:00 2001 From: Graham Neubig Date: Wed, 11 Dec 2024 22:18:38 -0800 Subject: [PATCH] Fix chat input not clearing after image paste/drop (#5342) Co-authored-by: openhands --- .../components/interactive-chat-box.test.tsx | 58 ++++++++++++++++++- .../components/features/chat/chat-input.tsx | 10 +++- .../features/chat/interactive-chat-box.tsx | 3 + 3 files changed, 67 insertions(+), 4 deletions(-) diff --git a/frontend/__tests__/components/interactive-chat-box.test.tsx b/frontend/__tests__/components/interactive-chat-box.test.tsx index fa0d3a1b8e30..fe6ba329763b 100644 --- a/frontend/__tests__/components/interactive-chat-box.test.tsx +++ b/frontend/__tests__/components/interactive-chat-box.test.tsx @@ -1,4 +1,4 @@ -import { render, screen, within } from "@testing-library/react"; +import { render, screen, within, fireEvent } from "@testing-library/react"; import userEvent from "@testing-library/user-event"; import { afterEach, beforeAll, describe, expect, it, vi } from "vitest"; import { InteractiveChatBox } from "#/components/features/chat/interactive-chat-box"; @@ -131,4 +131,60 @@ describe("InteractiveChatBox", () => { await user.click(stopButton); expect(onStopMock).toHaveBeenCalledOnce(); }); + + it("should handle image upload and message submission correctly", async () => { + const user = userEvent.setup(); + const onSubmit = vi.fn(); + const onStop = vi.fn(); + const onChange = vi.fn(); + + const { rerender } = render( + + ); + + // Upload an image via the upload button - this should NOT clear the text input + const file = new File(["dummy content"], "test.png", { type: "image/png" }); + const input = screen.getByTestId("upload-image-input"); + await user.upload(input, file); + + // Verify text input was not cleared + expect(screen.getByRole("textbox")).toHaveValue("test message"); + expect(onChange).not.toHaveBeenCalledWith(""); + + // Submit the message with image + const submitButton = screen.getByRole("button", { name: "Send" }); + await user.click(submitButton); + + // Verify onSubmit was called with the message and image + expect(onSubmit).toHaveBeenCalledWith("test message", [file]); + + // Verify onChange was called to clear the text input + expect(onChange).toHaveBeenCalledWith(""); + + // Simulate parent component updating the value prop + rerender( + + ); + + // Verify the text input was cleared + expect(screen.getByRole("textbox")).toHaveValue(""); + + // Upload another image - this should NOT clear the text input + onChange.mockClear(); + await user.upload(input, file); + + // Verify text input is still empty and onChange was not called + expect(screen.getByRole("textbox")).toHaveValue(""); + expect(onChange).not.toHaveBeenCalled(); + }); }); diff --git a/frontend/src/components/features/chat/chat-input.tsx b/frontend/src/components/features/chat/chat-input.tsx index 815eb1933720..44a86d675c22 100644 --- a/frontend/src/components/features/chat/chat-input.tsx +++ b/frontend/src/components/features/chat/chat-input.tsx @@ -83,9 +83,13 @@ export function ChatInput({ }; const handleSubmitMessage = () => { - if (textareaRef.current?.value) { - onSubmit(textareaRef.current.value); - textareaRef.current.value = ""; + if (value || (textareaRef.current?.value && !value)) { + onSubmit(value || textareaRef.current?.value || ""); + if (value) { + onChange?.(""); + } else if (textareaRef.current) { + textareaRef.current.value = ""; + } } }; diff --git a/frontend/src/components/features/chat/interactive-chat-box.tsx b/frontend/src/components/features/chat/interactive-chat-box.tsx index e96339adf0a7..09dcf84b32d6 100644 --- a/frontend/src/components/features/chat/interactive-chat-box.tsx +++ b/frontend/src/components/features/chat/interactive-chat-box.tsx @@ -38,6 +38,9 @@ export function InteractiveChatBox({ const handleSubmit = (message: string) => { onSubmit(message, images); setImages([]); + if (message) { + onChange?.(""); + } }; return (