import { describe, expect, it } from 'vitest'; import { analyzeRepeaterTraffic, buildAmbiguousRepeaterLabel, buildAmbiguousRepeaterNodeId, parsePacket, recordTrafficObservation, type RepeaterTrafficData, } from '../utils/visualizerUtils'; import { PayloadType } from '@michaelhart/meshcore-decoder'; describe('visualizer multibyte hop identity helpers', () => { it('preserves the full hop token in ambiguous node ids', () => { expect(buildAmbiguousRepeaterNodeId('aa11')).toBe('?aa11'); expect(buildAmbiguousRepeaterNodeId('bb22cc')).toBe('?bb22cc'); }); it('preserves the full current and next hop tokens in traffic split ids', () => { expect(buildAmbiguousRepeaterNodeId('aa', 'bb22')).toBe('?aa:>bb22'); expect(buildAmbiguousRepeaterNodeId('aa11', 'cc33dd')).toBe('?aa11:>cc33dd'); }); it('formats labels from full hop tokens', () => { expect(buildAmbiguousRepeaterLabel('aa11')).toBe('AA11'); expect(buildAmbiguousRepeaterLabel('aa11', 'bb22')).toBe('AA11:>BB22'); }); }); describe('visualizer traffic pattern grouping', () => { it('tracks traffic using full hop tokens instead of first-byte buckets', () => { const traffic = new Map(); for (let i = 0; i < 20; i += 1) { recordTrafficObservation(traffic, 'aa11', `src-a-${i}`, 'bb22'); recordTrafficObservation(traffic, 'aa22', `src-b-${i}`, 'bb33'); } expect(traffic.has('aa11')).toBe(true); expect(traffic.has('aa22')).toBe(true); expect(traffic.has('aa')).toBe(false); const firstTraffic = traffic.get('aa11'); const secondTraffic = traffic.get('aa22'); expect(firstTraffic).toBeDefined(); expect(secondTraffic).toBeDefined(); const first = analyzeRepeaterTraffic(firstTraffic!); const second = analyzeRepeaterTraffic(secondTraffic!); expect(first.shouldSplit).toBe(false); expect(second.shouldSplit).toBe(false); }); }); describe('visualizer packet parsing', () => { it('uses trace payload hashes instead of outer SNR bytes for TRACE packets', () => { const parsed = parsePacket('260233277e17b0f300000000007df6'); expect(parsed).not.toBeNull(); expect(parsed?.payloadType).toBe(PayloadType.Trace); expect(parsed?.pathBytes).toEqual(['7D', 'F6']); }); });