From 25ab37d0fe791d04b27716cbb1a71e71d1240d38 Mon Sep 17 00:00:00 2001 From: mptyl Date: Thu, 2 Jul 2026 18:52:12 +0200 Subject: [PATCH] fix(frontend): disable 'Altro' Send until non-whitespace text (no empty freetext) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Backlog T2 from the reviewer-gate-ux review: the Send button on the reserved "Other — specify" textarea emitted control:freetext with an empty payload when clicked on an empty/whitespace field. Guard with disabled={!text.trim()}. Co-Authored-By: Claude Opus 4.8 --- frontend/src/widgets/ReservedControls.test.tsx | 14 ++++++++++++++ frontend/src/widgets/ReservedControls.tsx | 6 +++++- 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/frontend/src/widgets/ReservedControls.test.tsx b/frontend/src/widgets/ReservedControls.test.tsx index e607e7ec..98e35b19 100644 --- a/frontend/src/widgets/ReservedControls.test.tsx +++ b/frontend/src/widgets/ReservedControls.test.tsx @@ -21,3 +21,17 @@ test("other reveals a textarea and emits freetext with the typed text", async () await userEvent.click(screen.getByRole("button", { name: /send/i })); expect(onControl).toHaveBeenCalledWith("freetext", "usa la tabella X"); }); + +test("Send stays disabled until non-whitespace text is entered", async () => { + const onControl = vi.fn(); + render(); + await userEvent.click(screen.getByRole("button", { name: /other — specify/i })); + const send = screen.getByRole("button", { name: /send/i }); + expect(send).toBeDisabled(); + await userEvent.type(screen.getByRole("textbox"), " "); + expect(send).toBeDisabled(); + await userEvent.click(send); + expect(onControl).not.toHaveBeenCalled(); + await userEvent.type(screen.getByRole("textbox"), "ok"); + expect(send).not.toBeDisabled(); +}); diff --git a/frontend/src/widgets/ReservedControls.tsx b/frontend/src/widgets/ReservedControls.tsx index 7fd37e7f..821c1a31 100644 --- a/frontend/src/widgets/ReservedControls.tsx +++ b/frontend/src/widgets/ReservedControls.tsx @@ -32,7 +32,11 @@ export function ReservedControls({ value={text} onChange={(e) => setText(e.target.value)} /> -