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();