Skip to content

Commit 76779f6

Browse files
committed
test(core): add unit tests for normalizeHeaders and createFetchWithInit
1 parent 3466a9e commit 76779f6

File tree

1 file changed

+142
-0
lines changed

1 file changed

+142
-0
lines changed
Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
import { createFetchWithInit, type FetchLike, normalizeHeaders } from '../../src/shared/transport.js';
2+
3+
describe('normalizeHeaders', () => {
4+
test('returns empty object for undefined', () => {
5+
expect(normalizeHeaders(undefined)).toEqual({});
6+
});
7+
8+
test('handles Headers instance', () => {
9+
const headers = new Headers({
10+
'x-foo': 'bar',
11+
'content-type': 'application/json'
12+
});
13+
expect(normalizeHeaders(headers)).toEqual({
14+
'x-foo': 'bar',
15+
'content-type': 'application/json'
16+
});
17+
});
18+
19+
test('handles array of tuples', () => {
20+
const headers: [string, string][] = [
21+
['x-foo', 'bar'],
22+
['x-baz', 'qux']
23+
];
24+
expect(normalizeHeaders(headers)).toEqual({
25+
'x-foo': 'bar',
26+
'x-baz': 'qux'
27+
});
28+
});
29+
30+
test('handles plain object', () => {
31+
const headers = { 'x-foo': 'bar', 'x-baz': 'qux' };
32+
expect(normalizeHeaders(headers)).toEqual({
33+
'x-foo': 'bar',
34+
'x-baz': 'qux'
35+
});
36+
});
37+
38+
test('returns a shallow copy for plain objects', () => {
39+
const headers = { 'x-foo': 'bar' };
40+
const result = normalizeHeaders(headers);
41+
expect(result).not.toBe(headers);
42+
expect(result).toEqual(headers);
43+
});
44+
});
45+
46+
describe('createFetchWithInit', () => {
47+
test('returns baseFetch unchanged when no baseInit provided', () => {
48+
const mockFetch: FetchLike = vi.fn();
49+
const result = createFetchWithInit(mockFetch);
50+
expect(result).toBe(mockFetch);
51+
});
52+
53+
test('passes baseInit to fetch when no call init provided', async () => {
54+
const mockFetch: FetchLike = vi.fn();
55+
const baseInit: RequestInit = {
56+
method: 'POST',
57+
credentials: 'include'
58+
};
59+
60+
const wrappedFetch = createFetchWithInit(mockFetch, baseInit);
61+
await wrappedFetch('https://example.com');
62+
63+
expect(mockFetch).toHaveBeenCalledWith(
64+
'https://example.com',
65+
expect.objectContaining({
66+
method: 'POST',
67+
credentials: 'include'
68+
})
69+
);
70+
});
71+
72+
test('merges baseInit with call init, call init wins for non-header fields', async () => {
73+
const mockFetch: FetchLike = vi.fn();
74+
const baseInit: RequestInit = {
75+
method: 'POST',
76+
credentials: 'include'
77+
};
78+
79+
const wrappedFetch = createFetchWithInit(mockFetch, baseInit);
80+
await wrappedFetch('https://example.com', { method: 'PUT' });
81+
82+
expect(mockFetch).toHaveBeenCalledWith(
83+
'https://example.com',
84+
expect.objectContaining({
85+
method: 'PUT',
86+
credentials: 'include'
87+
})
88+
);
89+
});
90+
91+
test('merges headers from both base and call init', async () => {
92+
const mockFetch: FetchLike = vi.fn();
93+
const baseInit: RequestInit = {
94+
headers: { 'x-base': 'base-value', 'x-shared': 'base' }
95+
};
96+
97+
const wrappedFetch = createFetchWithInit(mockFetch, baseInit);
98+
await wrappedFetch('https://example.com', {
99+
headers: { 'x-call': 'call-value', 'x-shared': 'call' }
100+
});
101+
102+
expect(mockFetch).toHaveBeenCalledWith(
103+
'https://example.com',
104+
expect.objectContaining({
105+
headers: {
106+
'x-base': 'base-value',
107+
'x-call': 'call-value',
108+
'x-shared': 'call'
109+
}
110+
})
111+
);
112+
});
113+
114+
test('uses baseInit headers when call init has no headers', async () => {
115+
const mockFetch: FetchLike = vi.fn();
116+
const baseInit: RequestInit = {
117+
headers: { 'x-base': 'base-value' }
118+
};
119+
120+
const wrappedFetch = createFetchWithInit(mockFetch, baseInit);
121+
await wrappedFetch('https://example.com', { method: 'POST' });
122+
123+
expect(mockFetch).toHaveBeenCalledWith(
124+
'https://example.com',
125+
expect.objectContaining({
126+
method: 'POST',
127+
headers: { 'x-base': 'base-value' }
128+
})
129+
);
130+
});
131+
132+
test('handles URL object as first argument', async () => {
133+
const mockFetch: FetchLike = vi.fn();
134+
const baseInit: RequestInit = { method: 'GET' };
135+
136+
const wrappedFetch = createFetchWithInit(mockFetch, baseInit);
137+
const url = new URL('https://example.com/path');
138+
await wrappedFetch(url);
139+
140+
expect(mockFetch).toHaveBeenCalledWith(url, expect.objectContaining({ method: 'GET' }));
141+
});
142+
});

0 commit comments

Comments
 (0)