From 12c4d275068add7227f8b96a3854bf22143dce2b Mon Sep 17 00:00:00 2001 From: Mahima Shanware Date: Mon, 30 Mar 2026 22:32:47 +0000 Subject: [PATCH] fix(cli): implement robust error extraction logic and tests for useBtw --- packages/cli/src/ui/hooks/useBtw.test.ts | 60 ++++++++++++++++++++++++ packages/cli/src/ui/hooks/useBtw.ts | 11 +++-- 2 files changed, 66 insertions(+), 5 deletions(-) diff --git a/packages/cli/src/ui/hooks/useBtw.test.ts b/packages/cli/src/ui/hooks/useBtw.test.ts index 45171ae6f2..4ca69a0675 100644 --- a/packages/cli/src/ui/hooks/useBtw.test.ts +++ b/packages/cli/src/ui/hooks/useBtw.test.ts @@ -91,6 +91,66 @@ describe('useBtw', () => { expect(result.current.isStreaming).toBe(false); }); + it('should handle string errors', async () => { + const mockStream = (async function* () { + yield { + type: GeminiEventType.Error, + value: { error: 'Direct string error' }, + }; + })(); + mockGeminiClient.sendBtwStream.mockReturnValue(mockStream); + + const { result } = await renderHook(() => + useBtw(mockGeminiClient as unknown as GeminiClient), + ); + + await act(async () => { + await result.current.submitBtw('test query'); + }); + + expect(result.current.error).toBe('Direct string error'); + }); + + it('should handle whitespace errors by falling back to Unknown error', async () => { + const mockStream = (async function* () { + yield { + type: GeminiEventType.Error, + value: { error: { message: ' ' } }, + }; + })(); + mockGeminiClient.sendBtwStream.mockReturnValue(mockStream); + + const { result } = await renderHook(() => + useBtw(mockGeminiClient as unknown as GeminiClient), + ); + + await act(async () => { + await result.current.submitBtw('test query'); + }); + + expect(result.current.error).toBe('Unknown error'); + }); + + it('should handle unknown error shapes', async () => { + const mockStream = (async function* () { + yield { + type: GeminiEventType.Error, + value: 'Just some raw string value', + }; + })(); + mockGeminiClient.sendBtwStream.mockReturnValue(mockStream); + + const { result } = await renderHook(() => + useBtw(mockGeminiClient as unknown as GeminiClient), + ); + + await act(async () => { + await result.current.submitBtw('test query'); + }); + + expect(result.current.error).toBe('Just some raw string value'); + }); + it('should reset state on dismiss', async () => { const mockStream = (async function* () { yield { type: GeminiEventType.Content, value: 'partial' }; diff --git a/packages/cli/src/ui/hooks/useBtw.ts b/packages/cli/src/ui/hooks/useBtw.ts index 23aeb41175..137d075fea 100644 --- a/packages/cli/src/ui/hooks/useBtw.ts +++ b/packages/cli/src/ui/hooks/useBtw.ts @@ -150,17 +150,18 @@ export const useBtw = ( if ( typeof value === 'object' && value !== null && - 'error' in value && - typeof value.error === 'object' && - value.error !== null + 'error' in value ) { const errorObj = value.error; - errorMessage = + const extracted = + typeof errorObj === 'object' && + errorObj !== null && 'message' in errorObj ? String(errorObj.message) : String(errorObj); + errorMessage = extracted.trim() || 'Unknown error'; } else { - errorMessage = String(value); + errorMessage = String(value).trim() || 'Unknown error'; } dispatch({ type: 'ERROR',