From 8fd1031c0491db3ed6a63ccd593d0b125fbcb679 Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Sun, 17 May 2026 16:09:01 +0000 Subject: [PATCH] =?UTF-8?q?=F0=9F=A7=AA=20testing=20improvement:=20add=20m?= =?UTF-8?q?issing=20tests=20for=20API=20error=20paths?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds test coverage for the `query` function in `src/api.ts` verifying the correct error behavior when `runtimeFetch` throws (e.g. network failure), returns non-JSON bodies on 200 responses, and returns non-200 HTTP status codes. Co-authored-by: sunnylqm <615282+sunnylqm@users.noreply.github.com> --- tests/api.test.ts | 88 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 88 insertions(+) diff --git a/tests/api.test.ts b/tests/api.test.ts index 1ae3751..8a55d07 100644 --- a/tests/api.test.ts +++ b/tests/api.test.ts @@ -10,6 +10,7 @@ import { import fs from 'fs'; import { closeSession, + get, getApiToken, getSession, loadSession, @@ -17,6 +18,7 @@ import { saveSession, setApiToken, } from '../src/api'; +import * as runtime from '../src/utils/runtime'; describe('api.ts session management', () => { let originalConsoleError: typeof console.error; @@ -126,3 +128,89 @@ describe('api.ts token management', () => { existsSyncSpy.mockRestore(); }); }); + +describe('api.ts query API methods', () => { + let runtimeFetchSpy: ReturnType; + let originalConsoleWarn: typeof console.warn; + let getBaseUrlSpy: ReturnType; + let _httpHelperBaseUrl: any; + + beforeEach(() => { + originalConsoleWarn = console.warn; + console.warn = mock(() => {}); + }); + + afterEach(() => { + console.warn = originalConsoleWarn; + runtimeFetchSpy?.mockRestore(); + getBaseUrlSpy?.mockRestore(); + }); + + test('query throws correctly formatted error on network failure', async () => { + runtimeFetchSpy = spyOn(runtime, 'runtimeFetch').mockImplementation( + async () => { + throw new Error('Network disconnected'); + }, + ); + + let error: any; + try { + await get('/test-endpoint'); + } catch (e) { + error = e; + } + + expect(error).toBeDefined(); + expect(error.message).toContain('Network disconnected'); + expect(error.message).toContain('URL:'); + }); + + test('query warns on 200 status with non-JSON body', async () => { + const nonJsonText = 'Not a JSON response'; + runtimeFetchSpy = spyOn(runtime, 'runtimeFetch').mockImplementation( + async () => + ({ + status: 200, + statusText: 'OK', + text: async () => nonJsonText, + }) as any, + ); + + let _error: any; + try { + await get('/test-endpoint'); + } catch (e) { + _error = e; + } + + expect(console.warn).toHaveBeenCalled(); + const warnMessage = (console.warn as import('bun:test').Mock).mock + .calls[0][0]; + expect(warnMessage).toContain( + 'Warning: API returned 200 with non-JSON body', + ); + expect(warnMessage).toContain(String(nonJsonText.length)); + }); + + test('query throws on non-200 HTTP status', async () => { + runtimeFetchSpy = spyOn(runtime, 'runtimeFetch').mockImplementation( + async () => + ({ + status: 500, + statusText: 'Internal Server Error', + text: async () => JSON.stringify({ message: 'Database failure' }), + }) as any, + ); + + let error: any; + try { + await get('/test-endpoint'); + } catch (e) { + error = e; + } + + expect(error).toBeDefined(); + expect(error.message).toContain('Database failure'); + expect(error.status).toBe(500); + }); +});