import assert from 'node:assert/strict'; import {after,before,test} from 'node:test'; import {createServer} from 'vite'; let server,PreviewLiveness,previewPlayback; before(async()=>{ server=await createServer({appType:'custom',logLevel:'silent',server:{middlewareMode:true}}); ({PreviewLiveness}=await server.ssrLoadModule('../../packages/sensor-ui/src/previewLiveness.ts')); ({previewPlayback}=await server.ssrLoadModule('../../packages/sensor-ui/src/previewPlayback.ts')); }); after(async()=>{await server?.close();}); test('offscreen RTP decode progress keeps a viewer live without DOM frame callbacks',()=>{ const h=new PreviewLiveness(0); for(let now=2000;now<180000;now+=2000){h.frame(now);assert.equal(h.state(now),'live');} }); test('one stale telemetry sample signals delay, never a camera restart',()=>{ const h=new PreviewLiveness(0);h.frame(1000);h.source(false,1100); assert.equal(h.state(1100),'delayed');h.source(true,1500);h.frame(1500);assert.equal(h.state(1500),'live'); }); test('capture recovery requires sustained fresh reports that the source stopped',()=>{ const h=new PreviewLiveness(0);h.frame(1000); for(let now=2000;now<=12000;now+=1000){h.source(false,now);assert.equal(h.state(now),'delayed');} h.source(false,14000);assert.equal(h.state(14000),'source-stalled'); h.source(true,14500);h.frame(14500);assert.equal(h.state(14500),'live'); }); test('missing telemetry and a stalled peer cannot be treated as proof to restart capture',()=>{ const h=new PreviewLiveness(0);h.frame(100);h.source(false,200); assert.equal(h.state(13000),'peer-stalled'); }); test('negotiation time does not consume the first-frame grace period',()=>{ const h=new PreviewLiveness(0);h.connected(45000); assert.equal(h.state(45001),'waiting');assert.equal(h.state(53001),'peer-stalled'); }); test('a browser-paused panel resumes the same stream and coalesces pending playback',async()=>{ const stream={},attempts=[]; const video={srcObject:stream,muted:false,paused:true,play(){return new Promise(resolve=>attempts.push(resolve));}}; const playback=previewPlayback(video); playback.resume();playback.resume();assert.equal(attempts.length,1);assert.equal(video.muted,true); video.paused=false;attempts[0]();await new Promise(resolve=>setImmediate(resolve)); playback.resume();assert.equal(attempts.length,1); video.paused=true;playback.resume();assert.equal(attempts.length,2);assert.equal(video.srcObject,stream); playback.dispose();attempts[1]();await new Promise(resolve=>setImmediate(resolve)); playback.resume();assert.equal(attempts.length,2); }); test('hidden-panel play rejection is retried on visibility without replacing the stream',async()=>{ const stream={};let attempts=0; const video={srcObject:stream,muted:true,paused:true,play(){attempts++;return Promise.reject(new Error('offscreen'));}}; const playback=previewPlayback(video); playback.resume();await new Promise(resolve=>setImmediate(resolve)); playback.resume();await new Promise(resolve=>setImmediate(resolve)); assert.equal(attempts,2);assert.equal(video.srcObject,stream); video.srcObject=null;playback.resume();assert.equal(attempts,2); });