import { describe, it, expect } from 'vitest'; import { preloadDicts } from './preload'; import type { Variant } from '../model'; import type { Dawg } from './dawg'; // A non-null stand-in for a loaded reader — preloadDicts only checks getDawg's result for null. const DAWG = {} as Dawg; const noSleep = (): Promise => Promise.resolve(); describe('preloadDicts', () => { it('fetches every enabled variant that has a known version', async () => { const calls: string[] = []; const res = await preloadDicts({ scrabble_en: 'v1', scrabble_ru: 'v2', erudit_ru: 'v3' }, ['scrabble_en', 'erudit_ru'], { getDawg: async (v: Variant, ver: string) => { calls.push(`${v}@${ver}`); return DAWG; }, disabled: () => false, sleep: noSleep, }); expect(res.ok).toEqual(['scrabble_en', 'erudit_ru']); expect(res.failed).toEqual([]); expect(calls).toEqual(['scrabble_en@v1', 'erudit_ru@v3']); }); it('marks a variant with no known version as failed without fetching it', async () => { const calls: string[] = []; const res = await preloadDicts({ scrabble_en: 'v1' }, ['scrabble_en', 'scrabble_ru'], { getDawg: async (v: Variant) => { calls.push(v); return DAWG; }, disabled: () => false, sleep: noSleep, }); expect(res.ok).toEqual(['scrabble_en']); expect(res.failed).toEqual(['scrabble_ru']); expect(calls).toEqual(['scrabble_en']); }); it('retries a transient failure with linear backoff, then succeeds', async () => { let attempts = 0; const waits: number[] = []; const res = await preloadDicts({ scrabble_en: 'v1' }, ['scrabble_en'], { getDawg: async () => (++attempts >= 3 ? DAWG : null), disabled: () => false, sleep: async (ms: number) => void waits.push(ms), retries: 3, backoffMs: 100, }); expect(res.ok).toEqual(['scrabble_en']); expect(attempts).toBe(3); expect(waits).toEqual([100, 200]); }); it('gives up a persistent failure after the retry budget', async () => { let attempts = 0; const res = await preloadDicts({ scrabble_en: 'v1' }, ['scrabble_en'], { getDawg: async () => { attempts++; return null; }, disabled: () => false, sleep: noSleep, retries: 2, }); expect(res.failed).toEqual(['scrabble_en']); expect(res.ok).toEqual([]); expect(attempts).toBe(3); }); it('stops retrying once the session miss-breaker trips', async () => { let attempts = 0; const res = await preloadDicts({ scrabble_en: 'v1' }, ['scrabble_en'], { getDawg: async () => { attempts++; return null; }, disabled: () => true, sleep: noSleep, retries: 5, }); expect(res.failed).toEqual(['scrabble_en']); expect(attempts).toBe(1); }); });