From 368134ff3d0dab7699355403fb66e1b0196465f5 Mon Sep 17 00:00:00 2001 From: notgitika Date: Mon, 29 Jun 2026 19:17:05 -0400 Subject: [PATCH] fix(tui): validate empty input in SecretInput before triggering cancel Previously, pressing Enter with an empty value in SecretInput would call onCancel (which navigates back) even when customValidation rejected empty values. Now validation runs first, showing the error message instead of silently going back. Fixes #1618 --- src/cli/tui/components/SecretInput.tsx | 9 +++++++-- .../components/__tests__/SecretInput.test.tsx | 17 +++++++++++++++++ 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/src/cli/tui/components/SecretInput.tsx b/src/cli/tui/components/SecretInput.tsx index 7794b4aa6..ff6049996 100644 --- a/src/cli/tui/components/SecretInput.tsx +++ b/src/cli/tui/components/SecretInput.tsx @@ -38,8 +38,6 @@ export interface SecretInputProps { } function validateValue(value: string, schema?: ZodString, customValidation?: CustomValidation): string | undefined { - if (!value) return undefined; - if (customValidation) { const result = customValidation(value); if (result !== true) { @@ -47,6 +45,8 @@ function validateValue(value: string, schema?: ZodString, customValidation?: Cus } } + if (!value) return undefined; + if (schema) { const parseResult = schema.safeParse(value); if (!parseResult.success) { @@ -89,6 +89,11 @@ export function SecretInput({ onSubmit: val => { const trimmed = val.trim(); if (!trimmed) { + const validationError = validateValue(trimmed, schema, customValidation); + if (validationError) { + setShowError(true); + return; + } if (onSkip) { onSkip(); } else { diff --git a/src/cli/tui/components/__tests__/SecretInput.test.tsx b/src/cli/tui/components/__tests__/SecretInput.test.tsx index cf00b0378..d16814f09 100644 --- a/src/cli/tui/components/__tests__/SecretInput.test.tsx +++ b/src/cli/tui/components/__tests__/SecretInput.test.tsx @@ -150,6 +150,23 @@ describe('SecretInput', () => { expect(onCancel).toHaveBeenCalledTimes(1); }); + it('shows validation error instead of calling onCancel when customValidation rejects empty value', async () => { + const onCancel = vi.fn(); + const onSubmit = vi.fn(); + const customValidation = (val: string) => val.trim().length > 0 || 'API key is required'; + const { lastFrame, stdin } = render( + + ); + + await delay(); + stdin.write(ENTER); + await delay(); + + expect(onCancel).not.toHaveBeenCalled(); + expect(onSubmit).not.toHaveBeenCalled(); + expect(lastFrame()).toContain('API key is required'); + }); + it('shows skip hint when onSkip is provided', () => { const { lastFrame } = render();