mirror of
https://github.com/EasyTier/EasyTier.git
synced 2026-08-06 04:29:52 +00:00
fix(web): preserve managed config and status compatibility (#2389)
Fix web/frontend compat bugs in managed config & runtime status - Preserve [[peer]].peer_public_key when TOML configs round-trip through the web/managed NetworkConfig path - Keep old peer_urls clients working while adding structured peer metadata for new clients - Make frontend protobuf JSON normalization preserve omitted-field semantics instead of turning missing data into misleading defaults - Harden runtime status rendering against omitted or string-encoded backend fields - Expose peer-route feature flags in the web status UI
This commit is contained in:
@@ -0,0 +1,84 @@
|
||||
import { describe, expect, it } from 'vitest'
|
||||
import { latencyMs, lossRate } from '../src/modules/statusDisplay'
|
||||
import { ipv4ToString, ipv6ToString } from '../src/modules/utils'
|
||||
|
||||
function peerRoutePair(conns: any[]) {
|
||||
return {
|
||||
route: {
|
||||
ipv4_addr: '10.0.0.2',
|
||||
hostname: 'peer',
|
||||
version: 'test',
|
||||
},
|
||||
peer: {
|
||||
conns,
|
||||
},
|
||||
} as any
|
||||
}
|
||||
|
||||
function peerRoutePairWithDefaultConn(conns: any[], defaultConnId: string) {
|
||||
const [part1, part2, part3, part4] = defaultConnId
|
||||
.replaceAll('-', '')
|
||||
.match(/.{8}/g)!
|
||||
.map((part) => Number.parseInt(part, 16))
|
||||
|
||||
return {
|
||||
...peerRoutePair(conns),
|
||||
peer: {
|
||||
default_conn_id: {
|
||||
part1,
|
||||
part2,
|
||||
part3,
|
||||
part4,
|
||||
},
|
||||
conns,
|
||||
},
|
||||
} as any
|
||||
}
|
||||
|
||||
describe('status display helpers', () => {
|
||||
it('does not render missing IP values as zero addresses', () => {
|
||||
expect(ipv4ToString(undefined)).toBe('')
|
||||
expect(ipv4ToString(null)).toBe('')
|
||||
expect(ipv4ToString({} as any)).toBe('0.0.0.0')
|
||||
expect(ipv4ToString({ addr: 0 })).toBe('0.0.0.0')
|
||||
|
||||
expect(ipv6ToString(undefined)).toBe('')
|
||||
expect(ipv6ToString(null)).toBe('')
|
||||
expect(ipv6ToString({} as any)).toBe('::0')
|
||||
expect(ipv6ToString({ part1: 0, part2: 0, part3: 0, part4: 0 })).toBe('::0')
|
||||
expect(ipv6ToString({ part4: 1 } as any)).toBe('::1')
|
||||
})
|
||||
|
||||
it('skips missing latency and loss values', () => {
|
||||
expect(latencyMs(peerRoutePair([
|
||||
{ conn_id: 'missing', stats: {} },
|
||||
{ conn_id: 'valid', stats: { latency_us: '2500' } },
|
||||
{ conn_id: 'invalid', stats: { latency_us: 'unknown' } },
|
||||
]))).toBe('3ms')
|
||||
expect(latencyMs(peerRoutePair([
|
||||
{ conn_id: 'missing', stats: {} },
|
||||
{ conn_id: 'invalid', stats: { latency_us: 'unknown' } },
|
||||
]))).toBe('')
|
||||
|
||||
expect(lossRate(peerRoutePair([
|
||||
{ conn_id: 'missing' },
|
||||
{ conn_id: 'valid', loss_rate: '0.25' },
|
||||
{ conn_id: 'invalid', loss_rate: 'unknown' },
|
||||
]))).toBe('25%')
|
||||
expect(lossRate(peerRoutePair([
|
||||
{ conn_id: 'missing' },
|
||||
{ conn_id: 'invalid', loss_rate: 'unknown' },
|
||||
]))).toBe('')
|
||||
})
|
||||
|
||||
it('prefers the default connection when its metric is valid', () => {
|
||||
const defaultConnId = '00000001-0002-0003-0004-000000000005'
|
||||
const conns = [
|
||||
{ conn_id: 'fallback', stats: { latency_us: '1000' }, loss_rate: '0.01' },
|
||||
{ conn_id: defaultConnId, stats: { latency_us: '9000' }, loss_rate: '0.5' },
|
||||
]
|
||||
|
||||
expect(latencyMs(peerRoutePairWithDefaultConn(conns, defaultConnId))).toBe('9ms')
|
||||
expect(lossRate(peerRoutePairWithDefaultConn(conns, defaultConnId))).toBe('50%')
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user