feat(observation): expose offline sources with transparent viewport headers

This commit is contained in:
DCCONSTRUCTIONS
2026-09-25 19:14:21 +03:00
parent db3b1d7b67
commit 8283f9ba85
13 changed files with 124 additions and 30 deletions
@@ -1,11 +1,12 @@
import assert from 'node:assert/strict';
import {after,before,test} from 'node:test';
import {createServer} from 'vite';
let server,layout,source,fanout;
let server,layout,source,fanout,catalog;
before(async()=>{
server=await createServer({appType:'custom',logLevel:'silent',server:{middlewareMode:true}});
layout=await server.ssrLoadModule('/src/core/fleet/observationLayout.ts');
source=await server.ssrLoadModule('../../packages/sensor-ui/src/observation.ts');
catalog=await server.ssrLoadModule('../../packages/sensor-ui/src/observationCatalog.ts');
({observationRerun:fanout}=await server.ssrLoadModule('@xgrids-k1/frontend/sensors/observationRerun.ts'));
});
after(async()=>{await server?.close();});
@@ -41,3 +42,21 @@ test('two Rerun views share bytes, apply independent blueprints once and dispose
assert.equal(sent[0].length,2);assert.deepEqual(started,[0,1]);host.dispose();assert.deepEqual(closed,[0,1]);
}finally{globalThis.fetch=fetchBefore;}
});
test('known offline D455 remains selectable; connected capabilities override the catalog',()=>{
const offline={name:'RealSense D455',model:'RealSense D455',online:false,layers:[]};
assert.deepEqual(source.cameraObservationViews(offline)[0].layers.map(v=>v.value),['color','depth','infrared1','infrared2','points','motion']);
assert.deepEqual(source.cameraObservationViews({...offline,online:true,layers:['depth']})[0].layers.map(v=>v.value),['depth']);
assert.deepEqual(source.cameraObservationViews({...offline,model:'unknown'}),[]);
});
test('unbound catalog views have no device authority; connected instances replace templates without aliasing',()=>{
const plugin={kind:'k1',observation:{catalog:{label:'K1',views:[{id:'points',label:'Points'},{id:'camera',label:'Camera'}]}}};
const entries=catalog.unboundObservationViews([],[plugin]);
assert.equal(entries.length,2);assert.notEqual(entries[0].key,entries[1].key);
assert.equal(entries[0].deviceID,undefined);assert.equal(entries[0].device,undefined);
assert.deepEqual(catalog.unboundObservationViews([{id:'one',kind:'k1'}],[plugin]),[]);
assert.deepEqual(catalog.unboundObservationViews([],[plugin,plugin]),[]);
const persisted=layout.decodeObservationLayout({...layout.emptyObservationLayout(),catalogVisible:[entries[0].key,entries[0].key,null]});
assert.deepEqual(persisted.catalogVisible,[entries[0].key]);
});