fix(ui): проверять данные трафика без подстановки нулей в серии

This commit is contained in:
Denozordec committed 2026-10-03 23:00:02 +07:00
1 parent f0eaa94e02
commit a28f871fd4
7 files changed
+49 -39

No files matched your search

+12
View File
@@ -0,0 +1,12 @@
import assert from "node:assert/strict"
import {test} from "node:test"
import {parseDashboardTraffic} from "./dashboard-traffic"
const row={id:"1",rxNow:2,txNow:1,rxSeries:[1,2],txSeries:[0,1]}
test("traffic sums aligned observed series and does not invent sixty samples",()=>{
assert.deepEqual(parseDashboardTraffic({servers:[row,{...row,id:"2"}]}),{rx:[2,4],tx:[0,2],rxNow:4,txNow:2})
assert.deepEqual(parseDashboardTraffic({servers:[]}),{rx:[],tx:[],rxNow:0,txNow:0})
assert.deepEqual(parseDashboardTraffic({servers:[{...row,rxSeries:[],txSeries:[]}]}),{rx:[],tx:[],rxNow:2,txNow:1})
})
test("missing, duplicate, null, invalid, misaligned and overflowing traffic cannot replace a snapshot",()=>{
for(const raw of [{},{servers:[row,row]},{servers:[{...row,rxNow:null}]},{servers:[{...row,txNow:-1}]},{servers:[{...row,rxSeries:[null,1]}]},{servers:[{...row,txSeries:[1]}]},{servers:[row,{...row,id:"2",rxSeries:[],txSeries:[]}]},{servers:[{...row,rxNow:Number.MAX_VALUE},{...row,id:"2",rxNow:Number.MAX_VALUE}]}])assert.throws(()=>parseDashboardTraffic(raw))
})
+14
View File
@@ -0,0 +1,14 @@
import {z} from "zod"
const rate=z.number().finite().nonnegative()
const row=z.object({id:z.string().trim().min(1),rxNow:rate,txNow:rate,rxSeries:z.array(rate),txSeries:z.array(rate)})
const payload=z.object({servers:z.array(row)}).refine(data=>new Set(data.servers.map(r=>r.id)).size===data.servers.length&&data.servers.every(r=>r.rxSeries.length===r.txSeries.length&&r.rxSeries.length===data.servers[0].rxSeries.length))
export interface DashboardTraffic {rx:number[];tx:number[];rxNow:number;txNow:number}
/** API series share an index axis; unequal series cannot be completed with assumed zero. */
export function parseDashboardTraffic(raw:unknown):DashboardTraffic {
const parsed=payload.safeParse(raw)
if(!parsed.success)throw Error("Некорректные данные трафика: проверьте счётчики и согласованность серий")
const rows=parsed.data.servers,length=rows[0]?.rxSeries.length??0
const total={rx:Array.from({length},(_,i)=>rows.reduce((sum,r)=>sum+r.rxSeries[i],0)),tx:Array.from({length},(_,i)=>rows.reduce((sum,r)=>sum+r.txSeries[i],0)),rxNow:rows.reduce((sum,r)=>sum+r.rxNow,0),txNow:rows.reduce((sum,r)=>sum+r.txNow,0)}
if(![total.rxNow,total.txNow,...total.rx,...total.tx].every(Number.isFinite))throw Error("Суммарный трафик превышает допустимый диапазон")
return total
}