Skip to content

Commit 8fd1031

Browse files
🧪 testing improvement: add missing tests for API error paths
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>
1 parent 2be3698 commit 8fd1031

1 file changed

Lines changed: 88 additions & 0 deletions

File tree

‎tests/api.test.ts‎

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,15 @@ import {
1010
import fs from 'fs';
1111
import {
1212
closeSession,
13+
get,
1314
getApiToken,
1415
getSession,
1516
loadSession,
1617
replaceSession,
1718
saveSession,
1819
setApiToken,
1920
} from '../src/api';
21+
import * as runtime from '../src/utils/runtime';
2022

2123
describe('api.ts session management', () => {
2224
let originalConsoleError: typeof console.error;
@@ -126,3 +128,89 @@ describe('api.ts token management', () => {
126128
existsSyncSpy.mockRestore();
127129
});
128130
});
131+
132+
describe('api.ts query API methods', () => {
133+
let runtimeFetchSpy: ReturnType<typeof spyOn>;
134+
let originalConsoleWarn: typeof console.warn;
135+
let getBaseUrlSpy: ReturnType<typeof spyOn>;
136+
let _httpHelperBaseUrl: any;
137+
138+
beforeEach(() => {
139+
originalConsoleWarn = console.warn;
140+
console.warn = mock(() => {});
141+
});
142+
143+
afterEach(() => {
144+
console.warn = originalConsoleWarn;
145+
runtimeFetchSpy?.mockRestore();
146+
getBaseUrlSpy?.mockRestore();
147+
});
148+
149+
test('query throws correctly formatted error on network failure', async () => {
150+
runtimeFetchSpy = spyOn(runtime, 'runtimeFetch').mockImplementation(
151+
async () => {
152+
throw new Error('Network disconnected');
153+
},
154+
);
155+
156+
let error: any;
157+
try {
158+
await get('/test-endpoint');
159+
} catch (e) {
160+
error = e;
161+
}
162+
163+
expect(error).toBeDefined();
164+
expect(error.message).toContain('Network disconnected');
165+
expect(error.message).toContain('URL:');
166+
});
167+
168+
test('query warns on 200 status with non-JSON body', async () => {
169+
const nonJsonText = 'Not a JSON response';
170+
runtimeFetchSpy = spyOn(runtime, 'runtimeFetch').mockImplementation(
171+
async () =>
172+
({
173+
status: 200,
174+
statusText: 'OK',
175+
text: async () => nonJsonText,
176+
}) as any,
177+
);
178+
179+
let _error: any;
180+
try {
181+
await get('/test-endpoint');
182+
} catch (e) {
183+
_error = e;
184+
}
185+
186+
expect(console.warn).toHaveBeenCalled();
187+
const warnMessage = (console.warn as import('bun:test').Mock<any>).mock
188+
.calls[0][0];
189+
expect(warnMessage).toContain(
190+
'Warning: API returned 200 with non-JSON body',
191+
);
192+
expect(warnMessage).toContain(String(nonJsonText.length));
193+
});
194+
195+
test('query throws on non-200 HTTP status', async () => {
196+
runtimeFetchSpy = spyOn(runtime, 'runtimeFetch').mockImplementation(
197+
async () =>
198+
({
199+
status: 500,
200+
statusText: 'Internal Server Error',
201+
text: async () => JSON.stringify({ message: 'Database failure' }),
202+
}) as any,
203+
);
204+
205+
let error: any;
206+
try {
207+
await get('/test-endpoint');
208+
} catch (e) {
209+
error = e;
210+
}
211+
212+
expect(error).toBeDefined();
213+
expect(error.message).toContain('Database failure');
214+
expect(error.status).toBe(500);
215+
});
216+
});

0 commit comments

Comments
 (0)