Skip to content

Commit 393d3ba

Browse files
committed
improve error handling and add comprehensive error tests
- Replace console.error with throw Error in all OpenProcessing API functions - Ensure build fails immediately when API calls fail instead of continuing with invalid data - Add comprehensive error handling tests for all API functions - Test various error scenarios: 500 Internal Server Error, 429 Rate Limit, 404 Not Found - Improve build reliability by failing fast on API issues - Export priorityIds for better test maintainability
1 parent a21097e commit 393d3ba

File tree

2 files changed

+91
-9
lines changed

2 files changed

+91
-9
lines changed

src/api/OpenProcessing.ts

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -50,16 +50,16 @@ export const getCurationSketches = memoize(async (
5050
const response1 = await fetch(
5151
`${openProcessingEndpoint}curation/${curationId}/sketches?${limitParam}`,
5252
);
53-
if(!response1.ok){ //log error instead of throwing error to not cache result in memoize
54-
console.error('getCurationSketches', response1.status, response1.statusText)
53+
if(!response1.ok){
54+
throw new Error(`getCurationSketches: ${response1.status} ${response1.statusText}`)
5555
}
5656
const payload1 = await response1.json();
5757

5858
const response2 = await fetch(
5959
`${openProcessingEndpoint}curation/${newCurationId}/sketches?${limitParam}`,
6060
);
61-
if(!response2.ok){ //log error instead of throwing error to not cache result in memoize
62-
console.error('getCurationSketches', response2.status, response2.statusText)
61+
if(!response2.ok){
62+
throw new Error(`getCurationSketches: ${response2.status} ${response2.statusText}`)
6363
}
6464
const payload2 = await response2.json();
6565

@@ -124,8 +124,7 @@ export const getSketch = memoize(
124124
// check for sketch data in Open Processing API
125125
const response = await fetch(`${openProcessingEndpoint}sketch/${id}`);
126126
if (!response.ok) {
127-
//log error instead of throwing error to not cache result in memoize
128-
console.error("getSketch", id, response.status, response.statusText);
127+
throw new Error(`getSketch: ${id} ${response.status} ${response.statusText}`)
129128
}
130129
const payload = await response.json();
131130
return payload as OpenProcessingSketchResponse;
@@ -143,8 +142,8 @@ export const getSketchSize = memoize(async (id: number) => {
143142
}
144143

145144
const response = await fetch(`${openProcessingEndpoint}sketch/${id}/code`);
146-
if(!response.ok){ //log error instead of throwing error to not cache result in memoize
147-
console.error('getSketchSize', id, response.status, response.statusText)
145+
if(!response.ok){
146+
throw new Error(`getSketchSize: ${id} ${response.status} ${response.statusText}`)
148147
}
149148
const payload = await response.json();
150149

test/api/OpenProcessing.test.ts

Lines changed: 84 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,4 +145,87 @@ describe('OpenProcessing API Caching', () => {
145145
expect(mockFetch).toHaveBeenCalledTimes(expectedCalls);
146146

147147
});
148-
});
148+
});
149+
150+
describe('Error Handling', () => {
151+
152+
beforeEach(() => {
153+
vi.clearAllMocks();
154+
155+
getCurationSketches.cache.clear?.();
156+
getSketch.cache.clear?.();
157+
getSketchSize.cache.clear?.();
158+
});
159+
160+
it('should throw an error when getCurationSketches API call fails', async () => {
161+
mockFetch.mockResolvedValue({
162+
ok: false,
163+
status: 500,
164+
statusText: 'Internal Server Error',
165+
});
166+
167+
await expect(getCurationSketches()).rejects.toThrow(
168+
'getCurationSketches: 500 Internal Server Error'
169+
);
170+
});
171+
172+
it('should throw an error when rate limit is exceeded (429)', async () => {
173+
mockFetch.mockResolvedValue({
174+
ok: false,
175+
status: 429,
176+
statusText: 'Too Many Requests',
177+
});
178+
179+
await expect(getCurationSketches()).rejects.toThrow(
180+
'getCurationSketches: 429 Too Many Requests'
181+
);
182+
});
183+
184+
it('should throw an error when getSketch API call fails for individual sketch', async () => {
185+
// Setup empty curations first
186+
mockFetch.mockResolvedValueOnce({
187+
ok: true,
188+
json: () => Promise.resolve([])
189+
}).mockResolvedValueOnce({
190+
ok: true,
191+
json: () => Promise.resolve([])
192+
});
193+
194+
await getCurationSketches(); // Create empty cache
195+
196+
// Individual sketch API call fails with 429
197+
mockFetch.mockResolvedValueOnce({
198+
ok: false,
199+
status: 429,
200+
statusText: 'Too Many Requests'
201+
});
202+
203+
await expect(getSketch(999)).rejects.toThrow(
204+
'getSketch: 999 429 Too Many Requests'
205+
);
206+
});
207+
208+
it('should throw an error when getSketchSize API call fails', async () => {
209+
// Setup sketch data first
210+
mockFetch.mockResolvedValueOnce({
211+
ok: true,
212+
json: () => Promise.resolve([getCurationSketchesData[0]])
213+
}).mockResolvedValueOnce({
214+
ok: true,
215+
json: () => Promise.resolve([])
216+
});
217+
218+
await getCurationSketches();
219+
220+
// getSketchSize API call fails with rate limit
221+
mockFetch.mockResolvedValueOnce({
222+
ok: false,
223+
status: 429,
224+
statusText: 'Too Many Requests'
225+
});
226+
227+
await expect(getSketchSize(getCurationSketchesData[0].visualID)).rejects.toThrow(
228+
`getSketchSize: ${getCurationSketchesData[0].visualID} 429 Too Many Requests`
229+
);
230+
});
231+
});

0 commit comments

Comments
 (0)