import { describe, expect, it, } from 'vitest'; import type { UnifiedFont } from '../../model/types'; import { createFontLoadRequestContfig } from './createFontLoadRequestContfig'; /** * Minimal UnifiedFont mock — override only the fields a case exercises. */ function createMockFont(overrides: Partial = {}): UnifiedFont { const baseFont: UnifiedFont = { id: 'test-font', name: 'Test Font', provider: 'google', category: 'sans-serif', subsets: ['latin'], variants: [], styles: {}, metadata: { cachedAt: Date.now(), }, features: { isVariable: false, tags: [], }, }; return { ...baseFont, ...overrides }; } describe('createFontLoadRequestContfig', () => { it('builds a single-element config when a URL resolves', () => { const font = createMockFont({ id: 'roboto', name: 'Roboto', styles: { variants: { '400': 'https://example.com/roboto-400.woff2' } }, }); const result = createFontLoadRequestContfig(font, 400); expect(result).toEqual([ { id: 'roboto', name: 'Roboto', weight: 400, url: 'https://example.com/roboto-400.woff2', isVariable: false, }, ]); }); it('returns an empty array when no URL resolves (flatMap drops the font)', () => { const font = createMockFont({ styles: {} }); expect(createFontLoadRequestContfig(font, 400)).toEqual([]); }); it('forwards isVariable from font features', () => { const font = createMockFont({ features: { isVariable: true, tags: [] }, styles: { variants: { '700': 'https://example.com/inter-vf.woff2' } }, }); const [config] = createFontLoadRequestContfig(font, 700); expect(config.isVariable).toBe(true); }); it('sets isVariable to undefined when features is absent', () => { // features is non-optional on UnifiedFont, but upstream data can be partial — // the optional chain must not throw, and isVariable stays undefined. const font = createMockFont({ styles: { variants: { '400': 'https://example.com/font.woff2' } }, }); // @ts-expect-error — deliberately drop the guaranteed field to exercise the optional chain font.features = undefined; const [config] = createFontLoadRequestContfig(font, 400); expect(config.isVariable).toBeUndefined(); }); it('uses the resolved fallback URL, not just exact matches', () => { // getFontUrl falls back to styles.regular when the exact weight is missing; // the config must carry whatever URL actually resolved. const font = createMockFont({ styles: { regular: 'https://example.com/font-regular.woff2' }, }); const [config] = createFontLoadRequestContfig(font, 900); expect(config.url).toBe('https://example.com/font-regular.woff2'); expect(config.weight).toBe(900); }); it('carries the requested weight even when the URL is a shared fallback', () => { const font = createMockFont({ styles: { variants: { '400': 'https://example.com/shared.woff2' } }, }); expect(createFontLoadRequestContfig(font, 700)[0].weight).toBe(700); }); it('propagates the invalid-weight error from getFontUrl', () => { const font = createMockFont(); expect(() => createFontLoadRequestContfig(font, 450)).toThrow('Invalid weight: 450'); }); });