forked from Lilly-Protocol/lily-sdk
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy patherror-request-metadata.test.ts
More file actions
87 lines (78 loc) · 2.92 KB
/
Copy patherror-request-metadata.test.ts
File metadata and controls
87 lines (78 loc) · 2.92 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
import { describe, it, expect, vi } from 'vitest';
import { createFetchHttpClient } from '../src/http/fetch-http-client';
import { resolveLilySdkConfig } from '../src/config/resolve-config';
import { LilyApiError, LilyAuthenticationError, LilyTransportError } from '../src/errors/sdk-error';
describe('transport error request metadata', () => {
const baseConfig = resolveLilySdkConfig({ baseUrl: 'https://api.example.com' });
interface MockResponseInit {
ok?: boolean;
status?: number;
headers?: HeadersInit;
json?: unknown;
text?: string;
}
function mockFetch(response: MockResponseInit): typeof fetch {
const init: ResponseInit = {
status: response.status ?? 200,
};
if (response.headers !== undefined) {
init.headers = response.headers;
}
const res = new Response(JSON.stringify(response.json ?? ''), init);
if (response.ok !== undefined) {
Object.defineProperty(res, 'ok', { value: response.ok });
}
if (response.text !== undefined) {
const textValue = response.text;
res.text = () => Promise.resolve(textValue);
}
return vi.fn().mockResolvedValue(res);
}
it('attaches metadata to LilyApiError on non-retryable failure', async () => {
const client = createFetchHttpClient({
...baseConfig,
fetch: mockFetch({ ok: false, status: 400, json: { message: 'bad' } }),
});
try {
await client.request({ method: 'POST', path: '/payments', body: { amount: 10 } });
expect.fail('should have thrown');
} catch (err) {
if (!(err instanceof LilyApiError)) throw err;
expect(err.request).toEqual({
method: 'POST',
path: '/payments',
url: 'https://api.example.com/payments',
});
}
});
it('attaches metadata to LilyAuthenticationError on 401', async () => {
const client = createFetchHttpClient({
...baseConfig,
fetch: mockFetch({ ok: false, status: 401, json: { error: 'unauthorized' } }),
});
try {
await client.request({ method: 'GET', path: '/wallet/me' });
expect.fail('should have thrown');
} catch (err) {
if (!(err instanceof LilyAuthenticationError)) throw err;
expect(err.request?.path).toBe('/wallet/me');
expect(err.request?.method).toBe('GET');
}
});
it('attaches metadata to LilyTransportError on network failure', async () => {
const networkFail = vi.fn().mockRejectedValue(new TypeError('Failed to fetch'));
const client = createFetchHttpClient({
...baseConfig,
retry: { retries: 0, retryDelayMs: 0, retryableStatusCodes: [] },
fetch: networkFail as typeof fetch,
});
try {
await client.request({ method: 'GET', path: '/health' });
expect.fail('should have thrown');
} catch (err) {
if (!(err instanceof LilyTransportError)) throw err;
expect(err.request?.url).toContain('/health');
expect(err.code).toBe('TRANSPORT_ERROR');
}
}, 10000);
});