test(core): add unit tests for normalizeHeaders and createFetchWithInit (#1374)
Co-authored-by: Felix Weinberger <3823880+felixweinberger@users.noreply.github.com>
This commit is contained in:
parent
cce3ac7512
commit
905b1e5c1a
1 changed files with 182 additions and 0 deletions
182
packages/core/test/shared/transport.test.ts
Normal file
182
packages/core/test/shared/transport.test.ts
Normal file
|
|
@ -0,0 +1,182 @@
|
|||
import { createFetchWithInit, type FetchLike, normalizeHeaders } from '../../src/shared/transport.js';
|
||||
|
||||
describe('normalizeHeaders', () => {
|
||||
test('returns empty object for undefined', () => {
|
||||
expect(normalizeHeaders(undefined)).toEqual({});
|
||||
});
|
||||
|
||||
test('handles Headers instance', () => {
|
||||
const headers = new Headers({
|
||||
'x-foo': 'bar',
|
||||
'content-type': 'application/json'
|
||||
});
|
||||
expect(normalizeHeaders(headers)).toEqual({
|
||||
'x-foo': 'bar',
|
||||
'content-type': 'application/json'
|
||||
});
|
||||
});
|
||||
|
||||
test('handles array of tuples', () => {
|
||||
const headers: [string, string][] = [
|
||||
['x-foo', 'bar'],
|
||||
['x-baz', 'qux']
|
||||
];
|
||||
expect(normalizeHeaders(headers)).toEqual({
|
||||
'x-foo': 'bar',
|
||||
'x-baz': 'qux'
|
||||
});
|
||||
});
|
||||
|
||||
test('handles plain object', () => {
|
||||
const headers = { 'x-foo': 'bar', 'x-baz': 'qux' };
|
||||
expect(normalizeHeaders(headers)).toEqual({
|
||||
'x-foo': 'bar',
|
||||
'x-baz': 'qux'
|
||||
});
|
||||
});
|
||||
|
||||
test('returns a shallow copy for plain objects', () => {
|
||||
const headers = { 'x-foo': 'bar' };
|
||||
const result = normalizeHeaders(headers);
|
||||
expect(result).not.toBe(headers);
|
||||
expect(result).toEqual(headers);
|
||||
});
|
||||
});
|
||||
|
||||
describe('createFetchWithInit', () => {
|
||||
test('returns baseFetch unchanged when no baseInit provided', () => {
|
||||
const mockFetch: FetchLike = vi.fn();
|
||||
const result = createFetchWithInit(mockFetch);
|
||||
expect(result).toBe(mockFetch);
|
||||
});
|
||||
|
||||
test('passes baseInit to fetch when no call init provided', async () => {
|
||||
const mockFetch: FetchLike = vi.fn();
|
||||
const baseInit: RequestInit = {
|
||||
method: 'POST',
|
||||
credentials: 'include'
|
||||
};
|
||||
|
||||
const wrappedFetch = createFetchWithInit(mockFetch, baseInit);
|
||||
await wrappedFetch('https://example.com');
|
||||
|
||||
expect(mockFetch).toHaveBeenCalledWith(
|
||||
'https://example.com',
|
||||
expect.objectContaining({
|
||||
method: 'POST',
|
||||
credentials: 'include'
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
test('merges baseInit with call init, call init wins for non-header fields', async () => {
|
||||
const mockFetch: FetchLike = vi.fn();
|
||||
const baseInit: RequestInit = {
|
||||
method: 'POST',
|
||||
credentials: 'include'
|
||||
};
|
||||
|
||||
const wrappedFetch = createFetchWithInit(mockFetch, baseInit);
|
||||
await wrappedFetch('https://example.com', { method: 'PUT' });
|
||||
|
||||
expect(mockFetch).toHaveBeenCalledWith(
|
||||
'https://example.com',
|
||||
expect.objectContaining({
|
||||
method: 'PUT',
|
||||
credentials: 'include'
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
test('merges headers from both base and call init', async () => {
|
||||
const mockFetch: FetchLike = vi.fn();
|
||||
const baseInit: RequestInit = {
|
||||
headers: { 'x-base': 'base-value', 'x-shared': 'base' }
|
||||
};
|
||||
|
||||
const wrappedFetch = createFetchWithInit(mockFetch, baseInit);
|
||||
await wrappedFetch('https://example.com', {
|
||||
headers: { 'x-call': 'call-value', 'x-shared': 'call' }
|
||||
});
|
||||
|
||||
expect(mockFetch).toHaveBeenCalledWith(
|
||||
'https://example.com',
|
||||
expect.objectContaining({
|
||||
headers: {
|
||||
'x-base': 'base-value',
|
||||
'x-call': 'call-value',
|
||||
'x-shared': 'call'
|
||||
}
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
test('uses baseInit headers when call init has no headers', async () => {
|
||||
const mockFetch: FetchLike = vi.fn();
|
||||
const baseInit: RequestInit = {
|
||||
headers: { 'x-base': 'base-value' }
|
||||
};
|
||||
|
||||
const wrappedFetch = createFetchWithInit(mockFetch, baseInit);
|
||||
await wrappedFetch('https://example.com', { method: 'POST' });
|
||||
|
||||
expect(mockFetch).toHaveBeenCalledWith(
|
||||
'https://example.com',
|
||||
expect.objectContaining({
|
||||
method: 'POST',
|
||||
headers: { 'x-base': 'base-value' }
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
test('handles URL object as first argument', async () => {
|
||||
const mockFetch: FetchLike = vi.fn();
|
||||
const baseInit: RequestInit = { method: 'GET' };
|
||||
|
||||
const wrappedFetch = createFetchWithInit(mockFetch, baseInit);
|
||||
const url = new URL('https://example.com/path');
|
||||
await wrappedFetch(url);
|
||||
|
||||
expect(mockFetch).toHaveBeenCalledWith(url, expect.objectContaining({ method: 'GET' }));
|
||||
});
|
||||
|
||||
test('passes all baseInit properties when call init is empty object', async () => {
|
||||
const mockFetch: FetchLike = vi.fn();
|
||||
const baseInit: RequestInit = {
|
||||
method: 'POST',
|
||||
credentials: 'include',
|
||||
headers: { 'x-base': 'value' }
|
||||
};
|
||||
|
||||
const wrappedFetch = createFetchWithInit(mockFetch, baseInit);
|
||||
await wrappedFetch('https://example.com', {});
|
||||
|
||||
expect(mockFetch).toHaveBeenCalledWith(
|
||||
'https://example.com',
|
||||
expect.objectContaining({
|
||||
method: 'POST',
|
||||
credentials: 'include',
|
||||
headers: { 'x-base': 'value' }
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
test('passes Headers instance through when call init has no headers', async () => {
|
||||
const mockFetch: FetchLike = vi.fn();
|
||||
const baseHeaders = new Headers({ 'x-base': 'value' });
|
||||
const baseInit: RequestInit = {
|
||||
headers: baseHeaders
|
||||
};
|
||||
|
||||
const wrappedFetch = createFetchWithInit(mockFetch, baseInit);
|
||||
await wrappedFetch('https://example.com', { method: 'POST' });
|
||||
|
||||
expect(mockFetch).toHaveBeenCalledWith(
|
||||
'https://example.com',
|
||||
expect.objectContaining({
|
||||
method: 'POST',
|
||||
headers: baseHeaders
|
||||
})
|
||||
);
|
||||
});
|
||||
});
|
||||
Loading…
Reference in a new issue