Preserve RRD preview frames and clarify onboard K1 status
This commit is contained in:
@@ -35,11 +35,28 @@ test('active acquisition exposes STOP and Rerun without another START',()=>{
|
||||
const active={...device,control:{...device.control,can_start:false,can_stop:true},snapshot:{...device.snapshot,acquisition:'streaming'}};
|
||||
const markup=render(active);
|
||||
assert.match(markup,/Остановить устройство/);
|
||||
assert.match(markup,/sensor-live-layout/);
|
||||
assert.match(markup,/k1-preview-spatial/);
|
||||
assert.match(markup,/>Статус</);
|
||||
assert.match(markup,/>Rerun</);
|
||||
assert.doesNotMatch(markup,/Восстановить просмотр|nodedc-activity-indicator/);
|
||||
assert.doesNotMatch(markup,/Инициировать запуск|Обновить просмотр/);
|
||||
assert.equal(presentation.k1ManualState(active,false).canStart,false);
|
||||
assert.equal(presentation.k1ManualState(active,false).showStop,true);
|
||||
});
|
||||
test('calibration loader stays inside the primary action',()=>{
|
||||
const starting={...device,control:{...device.control,can_start:false},snapshot:{...device.snapshot,acquisition:'starting'}};
|
||||
const markup=render(starting);
|
||||
assert.match(markup,/<button[^>]*aria-busy="true"[\s\S]*?nodedc-activity-indicator[\s\S]*?Запускаем устройство<\/button>/);
|
||||
assert.equal((markup.match(/nodedc-activity-indicator"/g)||[]).length,1);
|
||||
assert.doesNotMatch(markup,/Остановить устройство|k1-preview-spatial/);
|
||||
});
|
||||
test('completed STOP remains visible while the control connection is checked again',()=>{
|
||||
const stopped={...device,online:false,verified:false,control:{...device.control,phase:'completed',can_start:false,network_applied:true}};
|
||||
const markup=render(stopped);
|
||||
assert.match(markup,/Устройство остановлено/);
|
||||
assert.match(markup,/Проверить состояние K1/);
|
||||
assert.doesNotMatch(markup,/Инициировать запуск|нет управления/);
|
||||
});
|
||||
test('enrollment handoff opens only the verified current session',()=>{
|
||||
const inventory={fresh:true,items:[device],operations:[]};
|
||||
assert.equal(enrolledDevice(inventory,'exact-session'),device);
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
import assert from 'node:assert/strict';
|
||||
import {before,after,test} from 'node:test';
|
||||
import {execFileSync} from 'node:child_process';
|
||||
import {createServer} from 'vite';
|
||||
let server,previewFrames,assertRrd;
|
||||
before(async()=>{
|
||||
server=await createServer({appType:'custom',logLevel:'silent',server:{middlewareMode:true}});
|
||||
({previewFrames,assertRrd}=await server.ssrLoadModule('@xgrids-k1/frontend/sensors/previewFrames.ts'));
|
||||
});
|
||||
after(async()=>{await server?.close();});
|
||||
const array=bytes=>Uint8Array.from(bytes).buffer;
|
||||
const header=size=>{const value=new Uint8Array(8);value.set([77,67,70,49]);new DataView(value.buffer).setUint32(4,size);return value.buffer;};
|
||||
test('native RRD crosses many RTC fragments and reaches decoder once, byte-for-byte',()=>{
|
||||
const payload=execFileSync('../../.venv/bin/python',['-c',`import rerun as rr, numpy as np, sys
|
||||
r=rr.RecordingStream('synthetic-r10-js'); b=r.binary_stream()
|
||||
r.log('points',rr.Points3D(np.random.default_rng(42).random((5000,3))))
|
||||
sys.stdout.buffer.write(b.read())`]);
|
||||
assert.ok(payload.length>16384);
|
||||
const calls=[];
|
||||
const receiver=previewFrames(value=>{assertRrd(value);calls.push(value);});
|
||||
for(let record=0;record<2;record++){
|
||||
receiver.push(header(payload.length));
|
||||
for(let offset=0;offset<payload.length;offset+=16384){
|
||||
receiver.push(array(payload.subarray(offset,offset+16384)));
|
||||
if(offset+16384<payload.length)assert.equal(calls.length,record);
|
||||
}
|
||||
assert.deepEqual(Buffer.from(calls[record]),payload);
|
||||
}
|
||||
assert.equal(calls.length,2);
|
||||
receiver.close();
|
||||
});
|
||||
test('partial, oversized, unframed and invalid records never enter the decoder',()=>{
|
||||
let calls=0;
|
||||
const receiver=previewFrames(value=>{assertRrd(value);calls++;});
|
||||
assert.throws(()=>receiver.push(array([1,2,3])));
|
||||
assert.throws(()=>receiver.push(header(8*1024*1024+1)));
|
||||
assert.throws(()=>receiver.push(header(0)));
|
||||
receiver.push(header(20));receiver.push(array([1,2]));receiver.close();
|
||||
assert.equal(calls,0);
|
||||
receiver.push(header(12));assert.throws(()=>receiver.push(array(new Uint8Array(13))));receiver.close();
|
||||
receiver.push(header(12));assert.throws(()=>receiver.push(array(new Uint8Array(12))));
|
||||
assert.equal(calls,0);
|
||||
});
|
||||
@@ -11,7 +11,7 @@ import sys
|
||||
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[1]
|
||||
VERSION = "0.8.7"
|
||||
VERSION = "0.8.8"
|
||||
sys.path.insert(0, str(ROOT.parents[1] / "scripts/packaging"))
|
||||
from debian import package
|
||||
|
||||
|
||||
Reference in New Issue
Block a user