Skip to content

Commit fb495d2

Browse files
committed
Update handleStacResponse tests
1 parent 93045d9 commit fb495d2

File tree

2 files changed

+26
-36
lines changed

2 files changed

+26
-36
lines changed

src/utils/handleStacResponse.test.ts

Lines changed: 17 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,19 @@ describe('handleStacResponse', () => {
66
it('should parse and return JSON data', async () => {
77
const mockData = { id: 'collection-1', type: 'Collection' };
88
const jsonFn = jest.fn().mockResolvedValue(mockData);
9+
const cloneFn = jest.fn();
910
const mockResponse = {
1011
ok: true,
1112
status: 200,
1213
url: 'https://api.example.com/collections/collection-1',
1314
json: jsonFn,
15+
clone: cloneFn,
1416
} as unknown as Response;
1517

1618
const result = await handleStacResponse(mockResponse);
1719
expect(result).toEqual(mockData);
1820
expect(jsonFn).toHaveBeenCalledTimes(1);
21+
expect(cloneFn).toHaveBeenCalledTimes(1);
1922
});
2023

2124
it('should handle different data types', async () => {
@@ -25,6 +28,7 @@ describe('handleStacResponse', () => {
2528
status: 200,
2629
url: 'https://api.example.com/search',
2730
json: jest.fn().mockResolvedValue(mockData),
31+
clone: jest.fn(),
2832
} as unknown as Response;
2933

3034
const result = await handleStacResponse(mockResponse);
@@ -41,12 +45,13 @@ describe('handleStacResponse', () => {
4145
statusText: 'Not Found',
4246
url: 'https://api.example.com/collections/missing',
4347
json: jest.fn().mockResolvedValue(errorDetail),
48+
clone: jest.fn(),
4449
} as unknown as Response;
4550

4651
await expect(handleStacResponse(mockResponse)).rejects.toThrow(ApiError);
4752
await expect(handleStacResponse(mockResponse)).rejects.toMatchObject({
4853
status: 404,
49-
statusText: 'Not Found',
54+
message: 'Not Found',
5055
detail: errorDetail,
5156
url: 'https://api.example.com/collections/missing',
5257
});
@@ -68,32 +73,11 @@ describe('handleStacResponse', () => {
6873
await expect(handleStacResponse(mockResponse)).rejects.toThrow(ApiError);
6974
await expect(handleStacResponse(mockResponse)).rejects.toMatchObject({
7075
status: 500,
71-
statusText: 'Internal Server Error',
76+
message: 'Internal Server Error',
7277
detail: errorText,
7378
url: 'https://api.example.com/search',
7479
});
7580
});
76-
77-
it('should handle case where both JSON and text parsing fail', async () => {
78-
const mockResponse = {
79-
ok: false,
80-
status: 502,
81-
statusText: 'Bad Gateway',
82-
url: 'https://api.example.com/search',
83-
json: jest.fn().mockRejectedValue(new Error('Invalid JSON')),
84-
clone: jest.fn().mockReturnValue({
85-
text: jest.fn().mockRejectedValue(new Error('Cannot read text')),
86-
}),
87-
} as unknown as Response;
88-
89-
await expect(handleStacResponse(mockResponse)).rejects.toThrow(ApiError);
90-
await expect(handleStacResponse(mockResponse)).rejects.toMatchObject({
91-
status: 502,
92-
statusText: 'Bad Gateway',
93-
detail: 'Unable to parse error response',
94-
url: 'https://api.example.com/search',
95-
});
96-
});
9781
});
9882

9983
describe('invalid JSON responses', () => {
@@ -103,11 +87,14 @@ describe('handleStacResponse', () => {
10387
status: 200,
10488
url: 'https://api.example.com/collections',
10589
json: jest.fn().mockRejectedValue(new SyntaxError('Unexpected token')),
90+
clone: jest.fn().mockReturnValue({
91+
text: jest.fn().mockResolvedValue('Invalid JSON'),
92+
}),
10693
} as unknown as Response;
10794

10895
await expect(handleStacResponse(mockResponse)).rejects.toThrow(ApiError);
10996
await expect(handleStacResponse(mockResponse)).rejects.toMatchObject({
110-
statusText: 'Invalid JSON Response',
97+
message: 'Invalid JSON: Unexpected token',
11198
status: 200,
11299
url: 'https://api.example.com/collections',
113100
});
@@ -119,6 +106,9 @@ describe('handleStacResponse', () => {
119106
status: 200,
120107
url: 'https://api.example.com/collections',
121108
json: jest.fn().mockRejectedValue(new SyntaxError('Unexpected end of JSON input')),
109+
clone: jest.fn().mockReturnValue({
110+
text: jest.fn().mockResolvedValue('Original non jsnon response'),
111+
}),
122112
} as unknown as Response;
123113

124114
try {
@@ -127,8 +117,8 @@ describe('handleStacResponse', () => {
127117
} catch (error) {
128118
expect(error).toBeInstanceOf(ApiError);
129119
const apiError = error as ApiError;
130-
expect(apiError.detail).toContain('Response is not valid JSON');
131-
expect(apiError.detail).toContain('Unexpected end of JSON input');
120+
expect(apiError.detail).toContain('Original non jsnon response');
121+
expect(apiError.message).toContain('Invalid JSON: Unexpected end of JSON input');
132122
}
133123
});
134124
});
@@ -142,6 +132,7 @@ describe('handleStacResponse', () => {
142132
status: 200,
143133
url: 'https://api.example.com/collections/col-1',
144134
json: jest.fn().mockResolvedValue(mockData),
135+
clone: jest.fn(),
145136
} as unknown as Response;
146137

147138
const result = await handleStacResponse<Collection>(mockResponse);

src/utils/handleStacResponse.ts

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -24,29 +24,28 @@ import { ApiError } from './ApiError';
2424
* ```
2525
*/
2626
export async function handleStacResponse<T>(response: Response): Promise<T> {
27+
// Some STAC APIs return errors as JSON others as string.
28+
// Clone the response so we can read the body as text if json fails.
29+
const clone = response.clone();
30+
2731
if (!response.ok) {
2832
let detail;
2933
try {
3034
detail = await response.json();
3135
} catch {
32-
const clone = response.clone();
33-
try {
34-
detail = await clone.text();
35-
} catch {
36-
detail = 'Unable to parse error response';
37-
}
36+
detail = await clone.text();
3837
}
39-
4038
throw new ApiError(response.statusText, response.status, detail, response.url);
4139
}
4240

4341
try {
44-
return await response.json();
42+
const result: T = await response.json();
43+
return result;
4544
} catch (error) {
4645
throw new ApiError(
47-
'Invalid JSON Response',
46+
`Invalid JSON: ${error instanceof Error ? error.message : String(error)}`,
4847
response.status,
49-
`Response is not valid JSON: ${error instanceof Error ? error.message : String(error)}`,
48+
await clone.text(),
5049
response.url
5150
);
5251
}

0 commit comments

Comments
 (0)