Group onboard wireless steps and trace journalled Bluetooth failures

This commit is contained in:
DCCONSTRUCTIONS
2026-09-07 13:27:21 +03:00
parent a0732386f1
commit d7986cb62f
10 changed files with 217 additions and 27 deletions
@@ -2,10 +2,11 @@ import assert from 'node:assert/strict';
import {before,after,test} from 'node:test';
import {readFileSync,readdirSync} from 'node:fs';
import {createServer} from 'vite';
let server,api,resolveContribution,wirelessContributions;
let server,api,resolveContribution,wirelessContributions,revealEnrollment;
before(async()=>{
server=await createServer({appType:'custom',logLevel:'silent',server:{middlewareMode:true}});
api=await server.ssrLoadModule('@xgrids-k1/frontend/sensors/enrollment.ts');
({revealEnrollment}=await server.ssrLoadModule('@xgrids-k1/frontend/sensors/revealEnrollment.ts'));
({sensorContribution:resolveContribution}=await server.ssrLoadModule('../../packages/sensor-ui/src/extensions.ts'));
({wirelessContributions}=await server.ssrLoadModule('../../packages/sensor-ui/src/extensions.ts'));
});
@@ -78,6 +79,33 @@ test('station refusal is the same message in onboard and LAB presentations',()=>
assert.match(api.enrollmentNotice(state),/Проверьте название сети и пароль/);
assert.doesNotMatch(api.enrollmentNotice(state),/Bluetooth.*ошиб/);
});
test('Bluetooth failure before dispatch asks for discovery without blaming Wi-Fi',()=>{
const state={...initial,connection_attempt:{schema_version:'missioncore.xgrids-k1-connection-attempt/v1',attempt_id:'test',status:'failed',stage:'connect-failed',phase:'network_not_applied',public_error_code:'BleakError',side_effect_status:'none'}};
assert.equal(api.enrollmentBluetoothFailure(state),true);
assert.match(api.enrollmentNotice(state),/Bluetooth.*не были отправлены/s);
assert.doesNotMatch(api.enrollmentNotice(state),/Проверьте.*пароль/);
const unknown={...state,connection_attempt:{...state.connection_attempt,phase:'network_outcome_unknown',side_effect_status:'unknown'}};
assert.equal(api.enrollmentBluetoothFailure(unknown),false);
assert.doesNotMatch(api.enrollmentNotice(unknown),/не были отправлены/);
});
test('new workflow content scrolls only the containing viewport without stealing focus',()=>{
const original={document:globalThis.document,window:globalThis.window,getComputedStyle:globalThis.getComputedStyle};
const calls=[];let reduced=false;
const body={};
const scroller={parentElement:body,scrollHeight:1600,clientHeight:500,scrollTop:100,
getBoundingClientRect:()=>({top:100,bottom:600}),scrollTo:value=>calls.push(value)};
globalThis.document={body,documentElement:{}};
globalThis.window={matchMedia:()=>({matches:reduced})};
globalThis.getComputedStyle=element=>({overflowY:element===scroller?'auto':'visible'});
const target=(top,height)=>({parentElement:scroller,getBoundingClientRect:()=>({top,bottom:top+height,height}),focus:()=>assert.fail('focus must remain with the operator')});
try{
revealEnrollment(target(120,250));assert.equal(calls.length,0);
revealEnrollment(target(620,100));assert.deepEqual(calls.pop(),{top:220,behavior:'smooth'});
reduced=true;
revealEnrollment(target(620,800));assert.deepEqual(calls.pop(),{top:620,behavior:'instant'});
revealEnrollment({...target(700,100),parentElement:body});assert.equal(calls.length,0);
}finally{Object.assign(globalThis,original);}
});
test('sensor host can resolve zero or unrelated integrations and rejects ambiguity',()=>{
const alpha={kind:'alpha',Detail:()=>null},beta={kind:'beta',Detail:()=>null};
assert.equal(resolveContribution([],{kind:'alpha'}),undefined);