feature/test-coverage #27

Merged
ilia merged 12 commits from feature/test-coverage into main 2026-02-22 07:46:55 +00:00
Showing only changes of commit 3abe5723c7 - Show all commits

View File

@@ -12,9 +12,12 @@ import { AppliedFontsManager } from './appliedFontsStore.svelte';
describe('AppliedFontsManager', () => { describe('AppliedFontsManager', () => {
let manager: AppliedFontsManager; let manager: AppliedFontsManager;
let mockFontFaceSet: any; let mockFontFaceSet: any;
let mockFetch: any;
let failUrls: Set<string>;
beforeEach(() => { beforeEach(() => {
vi.useFakeTimers(); vi.useFakeTimers();
failUrls = new Set();
mockFontFaceSet = { mockFontFaceSet = {
add: vi.fn(), add: vi.fn(),
@@ -22,11 +25,13 @@ describe('AppliedFontsManager', () => {
}; };
// 1. Properly mock FontFace as a constructor function // 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.name = name;
this.url = url; this.bufferOrUrl = bufferOrUrl;
this.load = vi.fn().mockImplementation(() => { 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); return Promise.resolve(this);
}); });
}); });
@@ -44,18 +49,37 @@ describe('AppliedFontsManager', () => {
randomUUID: () => '11111111-1111-1111-1111-111111111111' as any, 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(); manager = new AppliedFontsManager();
}); });
afterEach(() => { afterEach(() => {
vi.clearAllTimers(); vi.clearAllTimers();
vi.useRealTimers(); vi.useRealTimers();
vi.unstubAllGlobals();
}); });
it('should batch multiple font requests into a single process', async () => { it('should batch multiple font requests into a single process', async () => {
const configs = [ const configs = [
{ id: 'lato-400', name: 'Lato', url: 'lato.ttf', weight: 400 }, { id: 'lato-400', name: 'Lato', url: 'https://example.com/lato.ttf', weight: 400 },
{ id: 'lato-700', name: 'Lato', url: 'lato-bold.ttf', weight: 700 }, { id: 'lato-700', name: 'Lato', url: 'https://example.com/lato-bold.ttf', weight: 700 },
]; ];
manager.touch(configs); manager.touch(configs);
@@ -71,7 +95,10 @@ describe('AppliedFontsManager', () => {
// Suppress expected console error for clean test logs // Suppress expected console error for clean test logs
const spy = vi.spyOn(console, 'error').mockImplementation(() => {}); 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]); manager.touch([config]);
await vi.advanceTimersByTimeAsync(50); await vi.advanceTimersByTimeAsync(50);
@@ -81,7 +108,7 @@ describe('AppliedFontsManager', () => {
}); });
it('should purge fonts after TTL expires', async () => { 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]); manager.touch([config]);
await vi.advanceTimersByTimeAsync(50); await vi.advanceTimersByTimeAsync(50);
@@ -96,7 +123,7 @@ describe('AppliedFontsManager', () => {
}); });
it('should NOT purge fonts that are still being "touched"', async () => { 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]); manager.touch([config]);
await vi.advanceTimersByTimeAsync(50); await vi.advanceTimersByTimeAsync(50);