test(appliedFontStore): change mockFetch

This commit is contained in:
Ilia Mashkov
2026-02-18 20:16:50 +03:00
parent 4f181d1d92
commit 3abe5723c7

View File

@@ -12,9 +12,12 @@ import { AppliedFontsManager } from './appliedFontsStore.svelte';
describe('AppliedFontsManager', () => {
let manager: AppliedFontsManager;
let mockFontFaceSet: any;
let mockFetch: any;
let failUrls: Set<string>;
beforeEach(() => {
vi.useFakeTimers();
failUrls = new Set();
mockFontFaceSet = {
add: vi.fn(),
@@ -22,11 +25,13 @@ describe('AppliedFontsManager', () => {
};
// 1. Properly mock FontFace as a constructor function
const MockFontFace = vi.fn(function(this: any, name: string, url: string) {
// The actual implementation passes buffer (ArrayBuffer) as second arg, not URL string
const MockFontFace = vi.fn(function(this: any, name: string, bufferOrUrl: ArrayBuffer | string) {
this.name = name;
this.url = url;
this.bufferOrUrl = bufferOrUrl;
this.load = vi.fn().mockImplementation(() => {
if (url.includes('fail')) return Promise.reject(new Error('Load failed'));
// For error tests, we track which URLs should fail via failUrls
// The fetch mock will have already rejected for those URLs
return Promise.resolve(this);
});
});
@@ -44,18 +49,37 @@ describe('AppliedFontsManager', () => {
randomUUID: () => '11111111-1111-1111-1111-111111111111' as any,
});
// 3. Mock fetch to return fake ArrayBuffer data
mockFetch = vi.fn((url: string) => {
if (failUrls.has(url)) {
return Promise.reject(new Error('Network error'));
}
return Promise.resolve({
ok: true,
status: 200,
arrayBuffer: () => Promise.resolve(new ArrayBuffer(8)),
clone: () => ({
ok: true,
status: 200,
arrayBuffer: () => Promise.resolve(new ArrayBuffer(8)),
}),
} as Response);
});
vi.stubGlobal('fetch', mockFetch);
manager = new AppliedFontsManager();
});
afterEach(() => {
vi.clearAllTimers();
vi.useRealTimers();
vi.unstubAllGlobals();
});
it('should batch multiple font requests into a single process', async () => {
const configs = [
{ id: 'lato-400', name: 'Lato', url: 'lato.ttf', weight: 400 },
{ id: 'lato-700', name: 'Lato', url: 'lato-bold.ttf', weight: 700 },
{ id: 'lato-400', name: 'Lato', url: 'https://example.com/lato.ttf', weight: 400 },
{ id: 'lato-700', name: 'Lato', url: 'https://example.com/lato-bold.ttf', weight: 700 },
];
manager.touch(configs);
@@ -71,7 +95,10 @@ describe('AppliedFontsManager', () => {
// Suppress expected console error for clean test logs
const spy = vi.spyOn(console, 'error').mockImplementation(() => {});
const config = { id: 'broken', name: 'Broken', url: 'fail.ttf', weight: 400 };
const failUrl = 'https://example.com/fail.ttf';
failUrls.add(failUrl);
const config = { id: 'broken', name: 'Broken', url: failUrl, weight: 400 };
manager.touch([config]);
await vi.advanceTimersByTimeAsync(50);
@@ -81,7 +108,7 @@ describe('AppliedFontsManager', () => {
});
it('should purge fonts after TTL expires', async () => {
const config = { id: 'ephemeral', name: 'Temp', url: 'temp.ttf', weight: 400 };
const config = { id: 'ephemeral', name: 'Temp', url: 'https://example.com/temp.ttf', weight: 400 };
manager.touch([config]);
await vi.advanceTimersByTimeAsync(50);
@@ -96,7 +123,7 @@ describe('AppliedFontsManager', () => {
});
it('should NOT purge fonts that are still being "touched"', async () => {
const config = { id: 'active', name: 'Active', url: 'active.ttf', weight: 400 };
const config = { id: 'active', name: 'Active', url: 'https://example.com/active.ttf', weight: 400 };
manager.touch([config]);
await vi.advanceTimersByTimeAsync(50);