172 lines
5.2 KiB
TypeScript
172 lines
5.2 KiB
TypeScript
/**
|
|
* Tests for proxy API client
|
|
*/
|
|
|
|
import {
|
|
beforeEach,
|
|
describe,
|
|
expect,
|
|
test,
|
|
vi,
|
|
} from 'vitest';
|
|
import type { UnifiedFont } from '../../model/types';
|
|
import type { ProxyFontsResponse } from './proxyFonts';
|
|
|
|
vi.mock('$shared/api/api', () => ({
|
|
api: {
|
|
get: vi.fn(),
|
|
},
|
|
}));
|
|
|
|
import { api } from '$shared/api/api';
|
|
import {
|
|
fetchFontsByIds,
|
|
fetchProxyFontById,
|
|
fetchProxyFonts,
|
|
} from './proxyFonts';
|
|
|
|
const PROXY_API_URL = 'https://api.glyphdiff.com/api/v1/fonts';
|
|
|
|
function createMockFont(overrides: Partial<UnifiedFont> = {}): UnifiedFont {
|
|
return {
|
|
id: 'roboto',
|
|
family: 'Roboto',
|
|
provider: 'google',
|
|
category: 'sans-serif',
|
|
variants: [],
|
|
subsets: [],
|
|
...overrides,
|
|
} as UnifiedFont;
|
|
}
|
|
|
|
function mockApiGet<T>(data: T) {
|
|
vi.mocked(api.get).mockResolvedValueOnce({ data, status: 200 });
|
|
}
|
|
|
|
describe('proxyFonts', () => {
|
|
beforeEach(() => {
|
|
vi.mocked(api.get).mockReset();
|
|
});
|
|
|
|
describe('fetchProxyFonts', () => {
|
|
test('should fetch fonts with no params', async () => {
|
|
const mockResponse: ProxyFontsResponse = {
|
|
fonts: [createMockFont()],
|
|
total: 1,
|
|
limit: 50,
|
|
offset: 0,
|
|
};
|
|
mockApiGet(mockResponse);
|
|
|
|
const result = await fetchProxyFonts();
|
|
|
|
expect(api.get).toHaveBeenCalledWith(PROXY_API_URL);
|
|
expect(result).toEqual(mockResponse);
|
|
});
|
|
|
|
test('should build URL with query params', async () => {
|
|
const mockResponse: ProxyFontsResponse = {
|
|
fonts: [createMockFont()],
|
|
total: 1,
|
|
limit: 20,
|
|
offset: 0,
|
|
};
|
|
mockApiGet(mockResponse);
|
|
|
|
await fetchProxyFonts({ provider: 'google', category: 'sans-serif', limit: 20, offset: 0 });
|
|
|
|
const calledUrl = vi.mocked(api.get).mock.calls[0][0];
|
|
expect(calledUrl).toContain('provider=google');
|
|
expect(calledUrl).toContain('category=sans-serif');
|
|
expect(calledUrl).toContain('limit=20');
|
|
expect(calledUrl).toContain('offset=0');
|
|
});
|
|
|
|
test('should throw on invalid response (missing fonts array)', async () => {
|
|
mockApiGet({ total: 0 });
|
|
|
|
await expect(fetchProxyFonts()).rejects.toThrow('Proxy API returned invalid response');
|
|
});
|
|
|
|
test('should throw on null response data', async () => {
|
|
vi.mocked(api.get).mockResolvedValueOnce({ data: null, status: 200 });
|
|
|
|
await expect(fetchProxyFonts()).rejects.toThrow('Proxy API returned invalid response');
|
|
});
|
|
});
|
|
|
|
describe('fetchProxyFontById', () => {
|
|
test('should return font matching the ID', async () => {
|
|
const targetFont = createMockFont({ id: 'satoshi', name: 'Satoshi' });
|
|
const mockResponse: ProxyFontsResponse = {
|
|
fonts: [createMockFont(), targetFont],
|
|
total: 2,
|
|
limit: 1000,
|
|
offset: 0,
|
|
};
|
|
mockApiGet(mockResponse);
|
|
|
|
const result = await fetchProxyFontById('satoshi');
|
|
|
|
expect(result).toEqual(targetFont);
|
|
});
|
|
|
|
test('should return undefined when font not found', async () => {
|
|
const mockResponse: ProxyFontsResponse = {
|
|
fonts: [createMockFont()],
|
|
total: 1,
|
|
limit: 1000,
|
|
offset: 0,
|
|
};
|
|
mockApiGet(mockResponse);
|
|
|
|
const result = await fetchProxyFontById('nonexistent');
|
|
|
|
expect(result).toBeUndefined();
|
|
});
|
|
|
|
test('should search with the ID as query param', async () => {
|
|
const mockResponse: ProxyFontsResponse = {
|
|
fonts: [],
|
|
total: 0,
|
|
limit: 1000,
|
|
offset: 0,
|
|
};
|
|
mockApiGet(mockResponse);
|
|
|
|
await fetchProxyFontById('Roboto');
|
|
|
|
const calledUrl = vi.mocked(api.get).mock.calls[0][0];
|
|
expect(calledUrl).toContain('limit=1000');
|
|
expect(calledUrl).toContain('q=Roboto');
|
|
});
|
|
});
|
|
|
|
describe('fetchFontsByIds', () => {
|
|
test('should return empty array for empty input', async () => {
|
|
const result = await fetchFontsByIds([]);
|
|
|
|
expect(result).toEqual([]);
|
|
expect(api.get).not.toHaveBeenCalled();
|
|
});
|
|
|
|
test('should call batch endpoint with comma-separated IDs', async () => {
|
|
const fonts = [createMockFont({ id: 'roboto' }), createMockFont({ id: 'satoshi' })];
|
|
mockApiGet(fonts);
|
|
|
|
const result = await fetchFontsByIds(['roboto', 'satoshi']);
|
|
|
|
expect(api.get).toHaveBeenCalledWith(`${PROXY_API_URL}/batch?ids=roboto,satoshi`);
|
|
expect(result).toEqual(fonts);
|
|
});
|
|
|
|
test('should return empty array when response data is nullish', async () => {
|
|
vi.mocked(api.get).mockResolvedValueOnce({ data: null, status: 200 });
|
|
|
|
const result = await fetchFontsByIds(['roboto']);
|
|
|
|
expect(result).toEqual([]);
|
|
});
|
|
});
|
|
});
|