forked from Lilly-Protocol/lily-sdk
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathnon-json-204.test.ts
More file actions
120 lines (105 loc) · 3.83 KB
/
Copy pathnon-json-204.test.ts
File metadata and controls
120 lines (105 loc) · 3.83 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
import { describe, it, expect, vi, beforeEach } from 'vitest';
import { createFetchHttpClient } from '../src/http/fetch-http-client';
import type { ResolvedLilySdkConfig } from '../src/config/types';
function createMockConfig(
overrides: Partial<ResolvedLilySdkConfig> = {},
): ResolvedLilySdkConfig {
return {
baseUrl: new URL('https://api.example.com'),
apiKey: 'test-key',
authToken: undefined,
userAgent: 'lily-sdk/test',
defaultHeaders: {},
timeoutMs: 5000,
retry: { retries: 0, retryDelayMs: 100, retryableStatusCodes: [] },
fetch: vi.fn(),
...overrides,
} as unknown as ResolvedLilySdkConfig;
}
describe('fetch-http-client non-JSON and 204 handling', () => {
let config: ResolvedLilySdkConfig;
beforeEach(() => {
config = createMockConfig();
});
it('returns null data for 204 No Content responses', async () => {
const mockResponse = {
ok: true,
status: 204,
headers: new Headers({ 'content-type': 'application/json' }),
json: vi
.fn()
.mockRejectedValue(new Error('Should not call json() on 204')),
text: vi.fn().mockResolvedValue(''),
};
vi.mocked(config.fetch).mockResolvedValue(
mockResponse as unknown as Response,
);
const client = createFetchHttpClient(config);
const result = await client.request({
method: 'DELETE',
path: '/v1/resource/1',
});
expect(result.status).toBe(204);
expect(result.data).toBeNull();
expect(mockResponse.json).not.toHaveBeenCalled();
});
it('parses response as text when content-type is not JSON', async () => {
const plainText = 'OK - Service Running';
const mockResponse = {
ok: true,
status: 200,
headers: new Headers({ 'content-type': 'text/plain' }),
json: vi
.fn()
.mockRejectedValue(new Error('Should not call json() for text/plain')),
text: vi.fn().mockResolvedValue(plainText),
};
vi.mocked(config.fetch).mockResolvedValue(
mockResponse as unknown as Response,
);
const client = createFetchHttpClient(config);
const result = await client.request({ method: 'GET', path: '/health' });
expect(result.status).toBe(200);
expect(result.data).toBe(plainText);
expect(mockResponse.text).toHaveBeenCalled();
expect(mockResponse.json).not.toHaveBeenCalled();
});
it('parses response as JSON when content-type includes application/json', async () => {
const jsonData = { status: 'ok' };
const mockResponse = {
ok: true,
status: 200,
headers: new Headers({
'content-type': 'application/json; charset=utf-8',
}),
json: vi.fn().mockResolvedValue(jsonData),
text: vi.fn().mockResolvedValue(JSON.stringify(jsonData)),
};
vi.mocked(config.fetch).mockResolvedValue(
mockResponse as unknown as Response,
);
const client = createFetchHttpClient(config);
const result = await client.request({ method: 'GET', path: '/v1/status' });
expect(result.data).toEqual(jsonData);
// New implementation reads text once then JSON.parse, not response.json()
expect(mockResponse.text).toHaveBeenCalled();
expect(mockResponse.json).not.toHaveBeenCalled();
});
it('falls back to text parsing when content-type header is missing', async () => {
const rawBody = '<html>OK</html>';
const mockResponse = {
ok: true,
status: 200,
headers: new Headers(),
json: vi.fn().mockRejectedValue(new SyntaxError('Unexpected token <')),
text: vi.fn().mockResolvedValue(rawBody),
};
vi.mocked(config.fetch).mockResolvedValue(
mockResponse as unknown as Response,
);
const client = createFetchHttpClient(config);
const result = await client.request({ method: 'GET', path: '/legacy' });
expect(result.data).toBe(rawBody);
expect(mockResponse.text).toHaveBeenCalled();
});
});