import { beforeEach, describe, expect, it } from 'vitest'; import { CUSTOM_MODULE_KEEP_ALIVE_MAX, touchLru, useCustomModuleCacheStore, } from './custom-module-cache-store'; describe('touchLru', () => { it('setzt ein neues Modul nach vorn ohne zu verwerfen', () => { expect(touchLru(['a', 'b'], 'c', 5)).toEqual({ recent: ['c', 'a', 'b'], evicted: [] }); }); it('holt ein vorhandenes Modul nach vorn, ohne es zu verdoppeln', () => { expect(touchLru(['a', 'b', 'c'], 'c', 5)).toEqual({ recent: ['c', 'a', 'b'], evicted: [] }); }); it('verwirft ueber der Grenze das am laengsten unbenutzte', () => { expect(touchLru(['e', 'd', 'c', 'b', 'a'], 'f', 5)).toEqual({ recent: ['f', 'e', 'd', 'c', 'b'], evicted: ['a'], }); }); it('haelt das gerade benutzte Modul auch bei unsinniger Grenze', () => { expect(touchLru(['a'], 'b', 0)).toEqual({ recent: ['b'], evicted: ['a'] }); }); }); describe('useCustomModuleCacheStore', () => { const slot = () => document.createElement('div'); const remember = (id: string) => useCustomModuleCacheStore.getState().remember({ id, name: id, url: `https://x.test/${id}` }); beforeEach(() => { useCustomModuleCacheStore.getState().clear(); }); it('haelt die Einhaengereihenfolge stabil und verwirft nach LRU', () => { const ids = Array.from({ length: CUSTOM_MODULE_KEEP_ALIVE_MAX + 1 }, (_, i) => `m${i}`); for (const id of ids) remember(id); const { activate } = useCustomModuleCacheStore.getState(); for (const id of ids.slice(0, CUSTOM_MODULE_KEEP_ALIVE_MAX)) activate(id, slot()); // m0 erneut benutzen -> m1 ist jetzt am laengsten unbenutzt. activate('m0', slot()); expect(useCustomModuleCacheStore.getState().openIds).toEqual(['m0', 'm1', 'm2', 'm3', 'm4']); activate('m5', slot()); const state = useCustomModuleCacheStore.getState(); expect(state.openIds).toEqual(['m0', 'm2', 'm3', 'm4', 'm5']); expect(state.recent[0]).toBe('m5'); // Metadaten bleiben — nur der offene Rahmen wird verworfen. expect(state.modules.m1).toBeDefined(); }); it('aktiviert kein Modul ohne Metadaten', () => { useCustomModuleCacheStore.getState().activate('unbekannt', slot()); expect(useCustomModuleCacheStore.getState().openIds).toEqual([]); expect(useCustomModuleCacheStore.getState().active).toBeNull(); }); it('deaktiviert nur den eigenen Platzhalter', () => { remember('a'); const first = slot(); const { activate, deactivate } = useCustomModuleCacheStore.getState(); activate('a', first); deactivate(slot()); expect(useCustomModuleCacheStore.getState().active?.slot).toBe(first); deactivate(first); expect(useCustomModuleCacheStore.getState().active).toBeNull(); expect(useCustomModuleCacheStore.getState().openIds).toEqual(['a']); }); it('vergisst ein Modul samt offenem Rahmen', () => { remember('a'); useCustomModuleCacheStore.getState().activate('a', slot()); useCustomModuleCacheStore.getState().forget('a'); const state = useCustomModuleCacheStore.getState(); expect(state.modules).toEqual({}); expect(state.openIds).toEqual([]); expect(state.recent).toEqual([]); expect(state.active).toBeNull(); }); });