import {test} from 'node:test'; import assert from 'node:assert/strict'; import {KeyedRows} from '../../YouleNexus/assets/framework/presentation/keyed-rows.ts'; import {ResourceLeaseCache} from '../../YouleNexus/assets/framework/presentation/resource-lease-cache.ts'; test('append preserves existing rows; updates, removals and teardown affect only owned rows',()=>{ const created:number[]=[],destroyed:number[]=[]; const rows=new KeyedRows<{id:number;text:string},{id:number}>({key:item=>item.id,create:item=>{created.push(item.id);return {id:item.id};},update:()=>{},remove:row=>destroyed.push(row.id)}); const one={id:1,text:'a'};rows.render([one]);const original=rows.get(1); rows.render([one,{id:2,text:'b'}]);assert.equal(rows.get(1),original);assert.deepEqual(created,[1,2]);assert.deepEqual(destroyed,[]); rows.render([{id:2,text:'changed'}]);assert.deepEqual(destroyed,[1]);rows.dispose();assert.deepEqual(destroyed,[1,2]); }); test('avatar loads are deduplicated, late completion after release is bounded and cleanup is exact',async()=>{ let loadCount=0;const disposed:string[]=[];let resolve!:(value:string)=>void; const cache=new ResourceLeaseCache({idleCapacity:0,load:()=>{loadCount++;return new Promise(r=>resolve=r);},destroy:value=>disposed.push(value)}); const a=cache.acquire('url'),b=cache.acquire('url');assert.equal(loadCount,1);a.release();resolve('texture'); assert.equal(await b.value,'texture');assert.equal(cache.leases,1);b.release();b.release();assert.equal(cache.leases,0);assert.deepEqual(disposed,['texture']); }); test('an idle cache retains only the explicitly configured budget and retries failed loads',async()=>{ let calls=0;const destroyed:string[]=[]; const cache=new ResourceLeaseCache({idleCapacity:1,load:async url=>{calls++;if(url==='bad')throw Error('load');return url;},destroy:x=>destroyed.push(x)}); for(const url of ['a','b']){const lease=cache.acquire(url);await lease.value;lease.release();} assert.deepEqual(destroyed,['a']);assert.equal(cache.size,1); const bad=cache.acquire('bad');await assert.rejects(bad.value);bad.release();const retry=cache.acquire('bad');await assert.rejects(retry.value);retry.release();assert.equal(calls,4); cache.clear();assert.deepEqual(destroyed,['a','b']); });