mirror of
https://github.com/dz0ny/meshcore-sar.git
synced 2026-08-11 08:20:36 +00:00
feat: Improve live traffic packet help #0
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:meshcore_sar_app/models/channel.dart';
|
||||
import 'package:meshcore_sar_app/providers/channels_provider.dart';
|
||||
|
||||
void main() {
|
||||
@@ -22,4 +23,38 @@ void main() {
|
||||
expect(provider.selectedChannel, isNull);
|
||||
});
|
||||
});
|
||||
|
||||
group('ChannelsProvider mesh hash lookup', () {
|
||||
test('resolves a unique channel display name by hash byte', () {
|
||||
final provider = ChannelsProvider();
|
||||
final channel = Channel.create(index: 3, name: '#ops');
|
||||
|
||||
provider.addOrUpdateChannelObject(channel);
|
||||
|
||||
expect(
|
||||
provider.getUniqueChannelDisplayNameByHashByte(channel.hashByte),
|
||||
'#ops',
|
||||
);
|
||||
});
|
||||
|
||||
test('does not resolve ambiguous hash matches', () {
|
||||
final provider = ChannelsProvider();
|
||||
final secret = Uint8List.fromList(List<int>.filled(16, 7));
|
||||
final firstChannel = Channel.create(
|
||||
index: 1,
|
||||
name: 'Ops 1',
|
||||
explicitSecret: secret,
|
||||
);
|
||||
|
||||
provider.addOrUpdateChannelObject(firstChannel);
|
||||
provider.addOrUpdateChannelObject(
|
||||
Channel.create(index: 2, name: 'Ops 2', explicitSecret: secret),
|
||||
);
|
||||
|
||||
expect(
|
||||
provider.getUniqueChannelDisplayNameByHashByte(firstChannel.hashByte),
|
||||
isNull,
|
||||
);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -2,9 +2,12 @@ import 'dart:typed_data';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:meshcore_sar_app/models/channel.dart';
|
||||
import 'package:meshcore_sar_app/models/ble_packet_log.dart';
|
||||
import 'package:meshcore_sar_app/l10n/app_localizations.dart';
|
||||
import 'package:meshcore_sar_app/providers/channels_provider.dart';
|
||||
import 'package:meshcore_sar_app/screens/live_traffic_screen.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
BlePacketLog _log({
|
||||
required DateTime timestamp,
|
||||
@@ -51,12 +54,16 @@ List<int> _multiHopRaw({
|
||||
];
|
||||
}
|
||||
|
||||
Widget _testApp(Widget child) {
|
||||
return MaterialApp(
|
||||
Widget _testApp(Widget child, {ChannelsProvider? channelsProvider}) {
|
||||
final app = MaterialApp(
|
||||
localizationsDelegates: AppLocalizations.localizationsDelegates,
|
||||
supportedLocales: AppLocalizations.supportedLocales,
|
||||
home: child,
|
||||
);
|
||||
if (channelsProvider == null) {
|
||||
return app;
|
||||
}
|
||||
return ChangeNotifierProvider.value(value: channelsProvider, child: app);
|
||||
}
|
||||
|
||||
void main() {
|
||||
@@ -190,6 +197,82 @@ void main() {
|
||||
expect(find.textContaining('Size: 3 bytes'), findsOneWidget);
|
||||
});
|
||||
|
||||
testWidgets('shows known channel name for group traffic', (tester) async {
|
||||
final logs = <BlePacketLog>[];
|
||||
final refresh = ValueNotifier<int>(0);
|
||||
final channel = Channel.create(index: 3, name: '#ops');
|
||||
final channelsProvider = ChannelsProvider()
|
||||
..initializePublicChannel()
|
||||
..addOrUpdateChannelObject(channel);
|
||||
final now = DateTime(2026, 3, 12, 12, 0, 0);
|
||||
|
||||
logs.add(
|
||||
_log(
|
||||
timestamp: now.subtract(const Duration(seconds: 4)),
|
||||
direction: PacketDirection.rx,
|
||||
rawData: [
|
||||
..._multiHopRaw(hops: [0xC0, 0x10], payloadType: 0x05),
|
||||
channel.hashByte,
|
||||
],
|
||||
responseCode: 0x88,
|
||||
),
|
||||
);
|
||||
|
||||
await tester.pumpWidget(
|
||||
_testApp(
|
||||
LiveTrafficScreen(
|
||||
logReader: () => logs,
|
||||
refreshListenable: refresh,
|
||||
now: () => now,
|
||||
),
|
||||
channelsProvider: channelsProvider,
|
||||
),
|
||||
);
|
||||
|
||||
expect(find.text('#ops'), findsOneWidget);
|
||||
expect(find.text('Channel: #ops (${channel.hashHex})'), findsOneWidget);
|
||||
expect(find.text('FLOOD GROUP_TEXT'), findsNothing);
|
||||
});
|
||||
|
||||
testWidgets('shows packet type help sheet from the app bar', (tester) async {
|
||||
final logs = <BlePacketLog>[];
|
||||
final refresh = ValueNotifier<int>(0);
|
||||
final now = DateTime(2026, 3, 12, 12, 0, 0);
|
||||
|
||||
await tester.pumpWidget(
|
||||
_testApp(
|
||||
LiveTrafficScreen(
|
||||
logReader: () => logs,
|
||||
refreshListenable: refresh,
|
||||
now: () => now,
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
await tester.tap(find.byTooltip('Packet type help'));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
expect(find.text('Packet Types'), findsOneWidget);
|
||||
await tester.scrollUntilVisible(
|
||||
find.text('FLOOD RETURNED_PATH'),
|
||||
300,
|
||||
scrollable: find.byType(Scrollable).last,
|
||||
);
|
||||
await tester.pumpAndSettle();
|
||||
expect(find.text('FLOOD RETURNED_PATH'), findsOneWidget);
|
||||
expect(
|
||||
find.textContaining('stores that returned path as the peer\'s direct out-path'),
|
||||
findsOneWidget,
|
||||
);
|
||||
await tester.scrollUntilVisible(
|
||||
find.text('FLOOD CONTROL'),
|
||||
300,
|
||||
scrollable: find.byType(Scrollable).last,
|
||||
);
|
||||
await tester.pumpAndSettle();
|
||||
expect(find.text('FLOOD CONTROL'), findsOneWidget);
|
||||
});
|
||||
|
||||
testWidgets('summary metrics expand across wide layouts', (tester) async {
|
||||
tester.view.physicalSize = const Size(1200, 900);
|
||||
tester.view.devicePixelRatio = 1;
|
||||
|
||||
@@ -196,5 +196,18 @@ void main() {
|
||||
1,
|
||||
);
|
||||
});
|
||||
|
||||
test('exposes detailed descriptions for known packet types', () {
|
||||
final returnedPath = LiveTrafficEntry.payloadTypeDetails(0x08);
|
||||
final control = LiveTrafficEntry.payloadTypeDetails(0x0B);
|
||||
|
||||
expect(returnedPath.title, 'FLOOD RETURNED_PATH');
|
||||
expect(
|
||||
returnedPath.description,
|
||||
contains('stores that returned path as the peer\'s direct out-path'),
|
||||
);
|
||||
expect(control.label, 'Control packet');
|
||||
expect(control.description, contains('discovery request and response'));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user