forked from Lilly-Protocol/lily-sdk
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy patharray-query-serialization.test.ts
More file actions
122 lines (103 loc) · 4.14 KB
/
Copy patharray-query-serialization.test.ts
File metadata and controls
122 lines (103 loc) · 4.14 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
121
122
import { describe, it, expect, vi } from 'vitest';
import { createFetchHttpClient } from '../src/http/fetch-http-client';
import type { ResolvedLilySdkConfig } from '../src/config/types';
/**
* Bounty #66 — $85
* "Support array values in query string serialization"
*
* Tests that array query parameters are serialized correctly
* (e.g. `?tags=a&tags=b` or `?tags[]=a&tags[]=b`).
*/
describe('array values in query string serialization', () => {
function createConfigWithFetch(fetchImpl: typeof globalThis.fetch): ResolvedLilySdkConfig {
return {
baseUrl: new URL('https://api.example.com/'),
timeoutMs: 5000,
retry: { retries: 0, retryDelayMs: 0, retryableStatusCodes: [429] },
defaultHeaders: {},
userAgent: 'test',
fetch: fetchImpl,
toHeaders: () => ({ accept: 'application/json' }),
};
}
it('serializes array query params by repeating the key', async () => {
const fetchMock = vi.fn().mockResolvedValue(
new Response('{}', { status: 200, headers: { 'content-type': 'application/json' } }),
);
const client = createFetchHttpClient(createConfigWithFetch(fetchMock as typeof fetch));
await client.request({
method: 'GET',
path: '/v1/items',
query: { tags: ['a', 'b', 'c'] },
});
const url = fetchMock.mock.calls[0][0] as URL;
expect(url.searchParams.getAll('tags')).toEqual(['a', 'b', 'c']);
});
it('handles mixed scalar and array params', async () => {
const fetchMock = vi.fn().mockResolvedValue(
new Response('{}', { status: 200, headers: { 'content-type': 'application/json' } }),
);
const client = createFetchHttpClient(createConfigWithFetch(fetchMock as typeof fetch));
await client.request({
method: 'GET',
path: '/v1/items',
query: { page: 1, tags: ['x', 'y'] },
});
const url = fetchMock.mock.calls[0][0] as URL;
expect(url.searchParams.get('page')).toBe('1');
expect(url.searchParams.getAll('tags')).toEqual(['x', 'y']);
});
it('handles empty arrays by omitting the param', async () => {
const fetchMock = vi.fn().mockResolvedValue(
new Response('{}', { status: 200, headers: { 'content-type': 'application/json' } }),
);
const client = createFetchHttpClient(createConfigWithFetch(fetchMock as typeof fetch));
await client.request({
method: 'GET',
path: '/v1/items',
query: { tags: [] },
});
const url = fetchMock.mock.calls[0][0] as URL;
expect(url.searchParams.has('tags')).toBe(false);
});
it('handles number arrays', async () => {
const fetchMock = vi.fn().mockResolvedValue(
new Response('{}', { status: 200, headers: { 'content-type': 'application/json' } }),
);
const client = createFetchHttpClient(createConfigWithFetch(fetchMock as typeof fetch));
await client.request({
method: 'GET',
path: '/v1/items',
query: { ids: [1, 2, 3] },
});
const url = fetchMock.mock.calls[0][0] as URL;
expect(url.searchParams.getAll('ids')).toEqual(['1', '2', '3']);
});
it('handles mixed array of numbers and strings', async () => {
const fetchMock = vi.fn().mockResolvedValue(
new Response('{}', { status: 200, headers: { 'content-type': 'application/json' } }),
);
const client = createFetchHttpClient(createConfigWithFetch(fetchMock as typeof fetch));
await client.request({
method: 'GET',
path: '/v1/items',
query: { filter: ['active', 42] },
});
const url = fetchMock.mock.calls[0][0] as URL;
expect(url.searchParams.getAll('filter')).toEqual(['active', '42']);
});
it('preserves undefined values (omits them)', async () => {
const fetchMock = vi.fn().mockResolvedValue(
new Response('{}', { status: 200, headers: { 'content-type': 'application/json' } }),
);
const client = createFetchHttpClient(createConfigWithFetch(fetchMock as typeof fetch));
await client.request({
method: 'GET',
path: '/v1/items',
query: { page: undefined, tags: ['a'] },
});
const url = fetchMock.mock.calls[0][0] as URL;
expect(url.searchParams.has('page')).toBe(false);
expect(url.searchParams.getAll('tags')).toEqual(['a']);
});
});